Merge pull request #1766 from Anson-Huang/master
Add more SIP runtime service for i.MX8
diff --git a/Makefile b/Makefile
index 3de7b3f..ad1ba15 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -584,7 +584,6 @@
$(eval $(call assert_boolean,CTX_INCLUDE_AARCH32_REGS))
$(eval $(call assert_boolean,CTX_INCLUDE_FPREGS))
$(eval $(call assert_boolean,DEBUG))
-$(eval $(call assert_boolean,DISABLE_PEDANTIC))
$(eval $(call assert_boolean,DYN_DISABLE_AUTH))
$(eval $(call assert_boolean,EL3_EXCEPTION_HANDLING))
$(eval $(call assert_boolean,ENABLE_AMU))
@@ -613,7 +612,7 @@
$(eval $(call assert_boolean,SAVE_KEYS))
$(eval $(call assert_boolean,SEPARATE_CODE_AND_RODATA))
$(eval $(call assert_boolean,SPIN_ON_BL1_EXIT))
-$(eval $(call assert_boolean,SPM_DEPRECATED))
+$(eval $(call assert_boolean,SPM_MM))
$(eval $(call assert_boolean,TRUSTED_BOARD_BOOT))
$(eval $(call assert_boolean,USE_COHERENT_MEM))
$(eval $(call assert_boolean,USE_ROMLIB))
@@ -667,7 +666,7 @@
$(eval $(call add_define,SMCCC_MAJOR_VERSION))
$(eval $(call add_define,SPD_${SPD}))
$(eval $(call add_define,SPIN_ON_BL1_EXIT))
-$(eval $(call add_define,SPM_DEPRECATED))
+$(eval $(call add_define,SPM_MM))
$(eval $(call add_define,TRUSTED_BOARD_BOOT))
$(eval $(call add_define,USE_COHERENT_MEM))
$(eval $(call add_define,USE_ROMLIB))
diff --git a/bl31/bl31.mk b/bl31/bl31.mk
index eddd164..89f5896 100644
--- a/bl31/bl31.mk
+++ b/bl31/bl31.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -8,12 +8,12 @@
# Include SPM Makefile
################################################################################
ifeq (${ENABLE_SPM},1)
- ifeq (${SPM_DEPRECATED},1)
+ ifeq (${SPM_MM},1)
ifeq (${EL3_EXCEPTION_HANDLING},0)
$(error EL3_EXCEPTION_HANDLING must be 1 for SPM support)
endif
- $(info Including deprecated SPM makefile)
- include services/std_svc/spm_deprecated/spm.mk
+ $(info Including makefile of SPM based on MM)
+ include services/std_svc/spm_mm/spm.mk
else
$(info Including SPM makefile)
include services/std_svc/spm/spm.mk
diff --git a/docs/plat/nvidia-tegra.rst b/docs/plat/nvidia-tegra.rst
index e244c1c..90d2ae1 100644
--- a/docs/plat/nvidia-tegra.rst
+++ b/docs/plat/nvidia-tegra.rst
@@ -82,6 +82,8 @@
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
diff --git a/docs/plat/warp7.rst b/docs/plat/warp7.rst
index 51c2609..6c04d91 100644
--- a/docs/plat/warp7.rst
+++ b/docs/plat/warp7.rst
@@ -31,36 +31,84 @@
make warp7_bl33_defconfig;
make u-boot.imx arch=ARM CROSS_COMPILE=arm-linux-gnueabihf-
-## TF-A:
+## OP-TEE:
-https://github.com/ARM-software/arm-trusted-firmware.git
+https://github.com/OP-TEE/optee_os.git
.. code:: shell
- make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=warp7 ARCH=aarch32 ARM_ARCH_MAJOR=7 ARM_CORTEX_A7=yes AARCH32_SP=optee 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
+ 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
-## OP-TEE:
+## TF-A:
-https://github.com/OP-TEE/optee_os.git
+https://github.com/ARM-software/arm-trusted-firmware.git
-.. code:: shell
+The following commands assume that a directory exits in the top-level TFA build
+directory "fiptool_images". "fiptool_images" contains
- 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
+- 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
-## FIP:
+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/uboot/u-boot.bin 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/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 warp7.fip
+
+ 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
diff --git a/drivers/st/bsec/bsec.c b/drivers/st/bsec/bsec.c
new file mode 100644
index 0000000..aaecf1f
--- /dev/null
+++ b/drivers/st/bsec/bsec.c
@@ -0,0 +1,913 @@
+/*
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <limits.h>
+
+#include <libfdt.h>
+
+#include <platform_def.h>
+
+#include <arch_helpers.h>
+#include <common/debug.h>
+#include <drivers/st/bsec.h>
+#include <lib/mmio.h>
+#include <lib/spinlock.h>
+
+#define BSEC_IP_VERSION_1_0 0x10
+#define BSEC_COMPAT "st,stm32mp15-bsec"
+
+#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)
+{
+ const uint32_t mask = SCTLR_M_BIT | SCTLR_C_BIT;
+
+ /* Lock is currently required only when MMU and cache are enabled */
+ if ((read_sctlr() & mask) == mask) {
+ spin_lock(&bsec_spinlock);
+ }
+}
+
+static void bsec_unlock(void)
+{
+ const uint32_t mask = SCTLR_M_BIT | SCTLR_C_BIT;
+
+ /* Unlock is required only when MMU and cache are enabled */
+ if ((read_sctlr() & mask) == mask) {
+ spin_unlock(&bsec_spinlock);
+ }
+}
+
+static int bsec_get_dt_node(struct dt_node_info *info)
+{
+ int node;
+
+ node = dt_get_node(info, -1, BSEC_COMPAT);
+ if (node < 0) {
+ return -FDT_ERR_NOTFOUND;
+ }
+
+ return node;
+}
+
+#if defined(IMAGE_BL32)
+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)) != 0;
+}
+
+static int 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 reg;
+ uint32_t i;
+ uint32_t size;
+ uint8_t status;
+
+ cuint = fdt_getprop(fdt, bsec_subnode, "reg", NULL);
+ if (cuint == NULL) {
+ panic();
+ }
+
+ reg = fdt32_to_cpu(*cuint) / sizeof(uint32_t);
+ if (reg < STM32MP1_UPPER_OTP_START) {
+ continue;
+ }
+
+ status = fdt_get_status(bsec_subnode);
+ if ((status & DT_NON_SECURE) == 0U) {
+ continue;
+ }
+
+ size = fdt32_to_cpu(*(cuint + 1)) / sizeof(uint32_t);
+
+ if ((fdt32_to_cpu(*(cuint + 1)) % sizeof(uint32_t)) != 0) {
+ size++;
+ }
+
+ for (i = reg; i < (reg + size); i++) {
+ enable_non_secure_access(i);
+ }
+ }
+
+ return 0;
+}
+#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);
+}
+
+static uint32_t bsec_check_error(uint32_t otp)
+{
+ uint32_t bit = BIT(otp & BSEC_OTP_MASK);
+ uint32_t bank = otp_bank_offset(otp);
+
+ if ((mmio_read_32(bsec_base + BSEC_DISTURBED_OFF + bank) & bit) != 0U) {
+ return BSEC_DISTURBED;
+ }
+
+ if ((mmio_read_32(bsec_base + BSEC_ERROR_OFF + bank) & bit) != 0U) {
+ return BSEC_ERROR;
+ }
+
+ return BSEC_OK;
+}
+
+/*
+ * bsec_probe: initialize BSEC driver.
+ * return value: BSEC_OK if no error.
+ */
+uint32_t bsec_probe(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();
+ }
+
+ bsec_base = bsec_info.base;
+
+#if defined(IMAGE_BL32)
+ bsec_dt_otp_nsec_access(fdt, node);
+#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;
+ int32_t result;
+
+ 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 power_up = false;
+
+ if (otp > STM32MP1_OTP_MAX_ID) {
+ return BSEC_INVALID_PARAM;
+ }
+
+ /* Check if shadowing of OTP is locked */
+ if (bsec_read_sr_lock(otp)) {
+ VERBOSE("BSEC: OTP %i 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();
+
+ /* Set BSEC_OTP_CTRL_OFF and set ADDR with the OTP value */
+ 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);
+
+ 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)
+{
+ uint32_t result;
+
+ if (otp > STM32MP1_OTP_MAX_ID) {
+ return BSEC_INVALID_PARAM;
+ }
+
+ bsec_lock();
+
+ *val = mmio_read_32(bsec_base + BSEC_OTP_DATA_OFF +
+ (otp * sizeof(uint32_t)));
+
+ result = bsec_check_error(otp);
+
+ bsec_unlock();
+
+ return result;
+}
+
+/*
+ * 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;
+
+ if (otp > STM32MP1_OTP_MAX_ID) {
+ return BSEC_INVALID_PARAM;
+ }
+
+ /* Check if programming of OTP is locked */
+ if (bsec_read_sw_lock(otp)) {
+ VERBOSE("BSEC: OTP %i is locked and write will be ignored\n",
+ otp);
+ }
+
+ bsec_lock();
+
+ mmio_write_32(bsec_base + BSEC_OTP_DATA_OFF +
+ (otp * sizeof(uint32_t)), val);
+
+ result = bsec_check_error(otp);
+
+ 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;
+
+ if (otp > STM32MP1_OTP_MAX_ID) {
+ return BSEC_INVALID_PARAM;
+ }
+
+ /* Check if programming of OTP is locked */
+ if (bsec_read_sp_lock(otp)) {
+ WARN("BSEC: OTP locked, prog will be ignored\n");
+ }
+
+ 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();
+
+ /* Set value in write register */
+ mmio_write_32(bsec_base + BSEC_OTP_WRDATA_OFF, val);
+
+ /* Set BSEC_OTP_CTRL_OFF and set ADDR with the OTP value */
+ 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);
+ }
+
+ 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 (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();
+
+ /* Set value in write register */
+ mmio_write_32(bsec_base + BSEC_OTP_WRDATA_OFF, data);
+
+ /* Set BSEC_OTP_CTRL_OFF and set ADDR with the OTP value */
+ 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);
+ }
+
+ 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: BSEC_OK if no error.
+ */
+uint32_t bsec_write_debug_conf(uint32_t val)
+{
+ uint32_t result = BSEC_ERROR;
+ uint32_t masked_val = val & BSEC_DEN_ALL_MSK;
+
+ bsec_lock();
+
+ mmio_write_32(bsec_base + BSEC_DEN_OFF, masked_val);
+
+ if ((mmio_read_32(bsec_base + BSEC_DEN_OFF) ^ masked_val) == 0U) {
+ result = BSEC_OK;
+ }
+
+ bsec_unlock();
+
+ return result;
+}
+
+/*
+ * bsec_read_debug_conf: read debug configuration.
+ */
+uint32_t bsec_read_debug_conf(void)
+{
+ return mmio_read_32(bsec_base + BSEC_DEN_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.
+ */
+uint32_t bsec_get_hw_conf(void)
+{
+ return mmio_read_32(bsec_base + BSEC_IPHW_CFG_OFF);
+}
+
+/*
+ * bsec_get_version: return BSEC version.
+ */
+uint32_t bsec_get_version(void)
+{
+ return mmio_read_32(bsec_base + BSEC_IPVR_OFF);
+}
+
+/*
+ * bsec_get_id: return BSEC ID.
+ */
+uint32_t bsec_get_id(void)
+{
+ return mmio_read_32(bsec_base + BSEC_IP_ID_OFF);
+}
+
+/*
+ * bsec_get_magic_id: return BSEC magic number.
+ */
+uint32_t bsec_get_magic_id(void)
+{
+ return mmio_read_32(bsec_base + BSEC_IP_MAGIC_ID_OFF);
+}
+
+/*
+ * bsec_write_sr_lock: write shadow-read lock.
+ * otp: OTP number.
+ * value: value to write in the register.
+ * Must be always 1.
+ * return: true if OTP is locked, else false.
+ */
+bool bsec_write_sr_lock(uint32_t otp, uint32_t value)
+{
+ bool result = false;
+ uint32_t bank = otp_bank_offset(otp);
+ uint32_t bank_value;
+ uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
+
+ bsec_lock();
+
+ bank_value = mmio_read_32(bsec_base + BSEC_SRLOCK_OFF + bank);
+
+ if ((bank_value & otp_mask) == value) {
+ /*
+ * In case of write don't need to write,
+ * the lock is already set.
+ */
+ if (value != 0U) {
+ result = true;
+ }
+ } else {
+ if (value != 0U) {
+ bank_value = bank_value | otp_mask;
+ } else {
+ bank_value = bank_value & ~otp_mask;
+ }
+
+ /*
+ * We can write 0 in all other OTP
+ * if the lock is activated in one of other OTP.
+ * Write 0 has no effect.
+ */
+ mmio_write_32(bsec_base + BSEC_SRLOCK_OFF + bank, bank_value);
+ result = true;
+ }
+
+ bsec_unlock();
+
+ return result;
+}
+
+/*
+ * bsec_read_sr_lock: read shadow-read lock.
+ * otp: OTP number.
+ * return: true if otp is locked, else false.
+ */
+bool bsec_read_sr_lock(uint32_t otp)
+{
+ uint32_t bank = otp_bank_offset(otp);
+ uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
+ uint32_t bank_value = mmio_read_32(bsec_base + BSEC_SRLOCK_OFF + bank);
+
+ return (bank_value & otp_mask) != 0U;
+}
+
+/*
+ * bsec_write_sw_lock: write shadow-write lock.
+ * otp: OTP number.
+ * value: Value to write in the register.
+ * Must be always 1.
+ * return: true if OTP is locked, else false.
+ */
+bool bsec_write_sw_lock(uint32_t otp, uint32_t value)
+{
+ bool result = false;
+ uint32_t bank = otp_bank_offset(otp);
+ uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
+ uint32_t bank_value;
+
+ bsec_lock();
+
+ bank_value = mmio_read_32(bsec_base + BSEC_SWLOCK_OFF + bank);
+
+ if ((bank_value & otp_mask) == value) {
+ /*
+ * In case of write don't need to write,
+ * the lock is already set.
+ */
+ if (value != 0U) {
+ result = true;
+ }
+ } else {
+ if (value != 0U) {
+ bank_value = bank_value | otp_mask;
+ } else {
+ bank_value = bank_value & ~otp_mask;
+ }
+
+ /*
+ * We can write 0 in all other OTP
+ * if the lock is activated in one of other OTP.
+ * Write 0 has no effect.
+ */
+ mmio_write_32(bsec_base + BSEC_SWLOCK_OFF + bank, bank_value);
+ result = true;
+ }
+
+ bsec_unlock();
+
+ return result;
+}
+
+/*
+ * bsec_read_sw_lock: read shadow-write lock.
+ * otp: OTP number.
+ * return: true if OTP is locked, else false.
+ */
+bool bsec_read_sw_lock(uint32_t otp)
+{
+ uint32_t bank = otp_bank_offset(otp);
+ uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
+ uint32_t bank_value = mmio_read_32(bsec_base + BSEC_SWLOCK_OFF + bank);
+
+ return (bank_value & otp_mask) != 0U;
+}
+
+/*
+ * bsec_write_sp_lock: write shadow-program lock.
+ * otp: OTP number.
+ * value: Value to write in the register.
+ * Must be always 1.
+ * return: true if OTP is locked, else false.
+ */
+bool bsec_write_sp_lock(uint32_t otp, uint32_t value)
+{
+ bool result = false;
+ uint32_t bank = otp_bank_offset(otp);
+ uint32_t bank_value;
+ uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
+
+ bsec_lock();
+
+ bank_value = mmio_read_32(bsec_base + BSEC_SPLOCK_OFF + bank);
+
+ if ((bank_value & otp_mask) == value) {
+ /*
+ * In case of write don't need to write,
+ * the lock is already set.
+ */
+ if (value != 0U) {
+ result = true;
+ }
+ } else {
+ if (value != 0U) {
+ bank_value = bank_value | otp_mask;
+ } else {
+ bank_value = bank_value & ~otp_mask;
+ }
+
+ /*
+ * We can write 0 in all other OTP
+ * if the lock is activated in one of other OTP.
+ * Write 0 has no effect.
+ */
+ mmio_write_32(bsec_base + BSEC_SPLOCK_OFF + bank, bank_value);
+ result = true;
+ }
+
+ bsec_unlock();
+
+ return result;
+}
+
+/*
+ * bsec_read_sp_lock: read shadow-program lock.
+ * otp: OTP number.
+ * return: true if OTP is locked, else false.
+ */
+bool bsec_read_sp_lock(uint32_t otp)
+{
+ uint32_t bank = otp_bank_offset(otp);
+ uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK);
+ uint32_t bank_value = mmio_read_32(bsec_base + BSEC_SPLOCK_OFF + bank);
+
+ return (bank_value & otp_mask) != 0U;
+}
+
+/*
+ * bsec_wr_lock: Read permanent lock status.
+ * otp: OTP number.
+ * return: true if OTP is locked, else false.
+ */
+bool bsec_wr_lock(uint32_t otp)
+{
+ uint32_t bank = otp_bank_offset(otp);
+ uint32_t lock_bit = BIT(otp & BSEC_OTP_MASK);
+
+ if ((mmio_read_32(bsec_base + BSEC_WRLOCK_OFF + bank) &
+ lock_bit) != 0U) {
+ /*
+ * In case of write don't need to write,
+ * the lock is already set.
+ */
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * bsec_otp_lock: Lock Upper OTP or Global programming or debug enable
+ * service: Service to lock see header file.
+ * value: Value to write must always set to 1 (only use for debug purpose).
+ * return: BSEC_OK if succeed.
+ */
+uint32_t bsec_otp_lock(uint32_t service, uint32_t value)
+{
+ uintptr_t reg = bsec_base + BSEC_OTP_LOCK_OFF;
+
+ switch (service) {
+ case BSEC_LOCK_UPPER_OTP:
+ mmio_write_32(reg, value << BSEC_LOCK_UPPER_OTP);
+ break;
+ case BSEC_LOCK_DEBUG:
+ mmio_write_32(reg, value << BSEC_LOCK_DEBUG);
+ break;
+ case BSEC_LOCK_PROGRAM:
+ mmio_write_32(reg, value << 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: BSEC_OK if succeed.
+ */
+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);
+
+ /* Waiting loop */
+ 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_mode_is_closed_device: read OTP secure sub-mode.
+ * return: false if open_device and true of closed_device.
+ */
+bool bsec_mode_is_closed_device(void)
+{
+ uint32_t value;
+
+ if ((bsec_shadow_register(DATA0_OTP) != BSEC_OK) ||
+ (bsec_read_otp(&value, DATA0_OTP) != BSEC_OK)) {
+ return true;
+ }
+
+ return (value & DATA0_OTP_SECURED) == DATA0_OTP_SECURED;
+}
+
+/*
+ * 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 %i\n", word, result);
+ return result;
+ }
+
+ result = bsec_read_otp(otp_value, word);
+ if (result != BSEC_OK) {
+ ERROR("BSEC: %u Read Error %i\n", word, result);
+ }
+
+ return result;
+}
+
+/*
+ * bsec_check_nsec_access_rights: check non-secure access rights to target OTP.
+ * otp: OTP number.
+ * return: 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) {
+ /* Check if BSEC is in OTP-SECURED closed_device state. */
+ if (bsec_mode_is_closed_device()) {
+ if (!non_secure_can_access(otp)) {
+ return BSEC_ERROR;
+ }
+ }
+ }
+#endif
+
+ return BSEC_OK;
+}
+
diff --git a/drivers/st/clk/stm32mp1_clkfunc.c b/drivers/st/clk/stm32mp1_clkfunc.c
index 1d92271..19dfe1b 100644
--- a/drivers/st/clk/stm32mp1_clkfunc.c
+++ b/drivers/st/clk/stm32mp1_clkfunc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -32,10 +32,18 @@
};
/*******************************************************************************
+ * This function returns the RCC node in the device tree.
+ ******************************************************************************/
+static int fdt_get_rcc_node(void *fdt)
+{
+ return fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT);
+}
+
+/*******************************************************************************
* This function reads the frequency of an oscillator from its name.
* It reads the value indicated inside the device tree.
- * Returns 0 if success, and a negative value else.
- * If success, value is stored in the second parameter.
+ * Returns 0 on success, and a negative FDT/ERRNO error code on failure.
+ * On success, value is stored in the second parameter.
******************************************************************************/
int fdt_osc_read_freq(const char *name, uint32_t *freq)
{
@@ -127,7 +135,7 @@
/*******************************************************************************
* This function reads a value of a oscillator property from its id.
- * Returns value if success, and a default value if property not found.
+ * Returns value on success, and a default value if property not found.
* Default value is passed as parameter.
******************************************************************************/
uint32_t fdt_osc_read_uint32_default(enum stm32mp_osc_id osc_id,
@@ -240,7 +248,7 @@
/*******************************************************************************
* This function gets the subnode offset in rcc-clk section from its name.
* It reads the values indicated inside the device tree.
- * Returns offset if success, and a negative value else.
+ * Returns offset on success, and a negative FDT/ERRNO error code on failure.
******************************************************************************/
int fdt_rcc_subnode_offset(const char *name)
{
@@ -251,7 +259,7 @@
return -ENOENT;
}
- node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT);
+ node = fdt_get_rcc_node(fdt);
if (node < 0) {
return -FDT_ERR_NOTFOUND;
}
@@ -280,7 +288,7 @@
return NULL;
}
- node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT);
+ node = fdt_get_rcc_node(fdt);
if (node < 0) {
return NULL;
}
@@ -297,7 +305,7 @@
/*******************************************************************************
* This function gets the secure status for rcc node.
* It reads secure-status in device tree.
- * Returns 1 if rcc is available from secure world, 0 else.
+ * Returns true if rcc is available from secure world, false if not.
******************************************************************************/
bool fdt_get_rcc_secure_status(void)
{
@@ -308,18 +316,18 @@
return false;
}
- node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_COMPAT);
+ node = fdt_get_rcc_node(fdt);
if (node < 0) {
return false;
}
- return fdt_check_secure_status(node);
+ return (fdt_get_status(node) & DT_SECURE) != 0U;
}
/*******************************************************************************
* This function reads the stgen base address.
* It reads the value indicated inside the device tree.
- * Returns address if success, and NULL value else.
+ * Returns address on success, and NULL value on failure.
******************************************************************************/
uintptr_t fdt_get_stgen_base(void)
{
@@ -347,7 +355,7 @@
/*******************************************************************************
* This function gets the clock ID of the given node.
* It reads the value indicated inside the device tree.
- * Returns ID if success, and a negative value else.
+ * Returns ID on success, and a negative FDT/ERRNO error code on failure.
******************************************************************************/
int fdt_get_clock_id(int node)
{
diff --git a/drivers/st/ddr/stm32mp1_ddr.c b/drivers/st/ddr/stm32mp1_ddr.c
index aca0450..79aff6e 100644
--- a/drivers/st/ddr/stm32mp1_ddr.c
+++ b/drivers/st/ddr/stm32mp1_ddr.c
@@ -1,9 +1,10 @@
/*
- * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
*/
+#include <errno.h>
#include <stddef.h>
#include <platform_def.h>
@@ -12,10 +13,10 @@
#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/delay_timer.h>
+#include <drivers/st/stm32mp_pmic.h>
#include <drivers/st/stm32mp1_clk.h>
#include <drivers/st/stm32mp1_ddr.h>
#include <drivers/st/stm32mp1_ddr_regs.h>
-#include <drivers/st/stm32mp1_pmic.h>
#include <drivers/st/stm32mp1_pwr.h>
#include <drivers/st/stm32mp1_ram.h>
#include <drivers/st/stm32mp1_rcc.h>
@@ -233,40 +234,67 @@
static const struct ddr_reg_info ddr_registers[REG_TYPE_NB] = {
[REG_REG] = {
- "static", ddr_reg, ARRAY_SIZE(ddr_reg), DDR_BASE
+ .name = "static",
+ .desc = ddr_reg,
+ .size = ARRAY_SIZE(ddr_reg),
+ .base = DDR_BASE
},
[REG_TIMING] = {
- "timing", ddr_timing, ARRAY_SIZE(ddr_timing), DDR_BASE
+ .name = "timing",
+ .desc = ddr_timing,
+ .size = ARRAY_SIZE(ddr_timing),
+ .base = DDR_BASE
},
[REG_PERF] = {
- "perf", ddr_perf, ARRAY_SIZE(ddr_perf), DDR_BASE
+ .name = "perf",
+ .desc = ddr_perf,
+ .size = ARRAY_SIZE(ddr_perf),
+ .base = DDR_BASE
},
[REG_MAP] = {
- "map", ddr_map, ARRAY_SIZE(ddr_map), DDR_BASE
+ .name = "map",
+ .desc = ddr_map,
+ .size = ARRAY_SIZE(ddr_map),
+ .base = DDR_BASE
},
[REGPHY_REG] = {
- "static", ddrphy_reg, ARRAY_SIZE(ddrphy_reg), DDRPHY_BASE
+ .name = "static",
+ .desc = ddrphy_reg,
+ .size = ARRAY_SIZE(ddrphy_reg),
+ .base = DDRPHY_BASE
},
[REGPHY_TIMING] = {
- "timing", ddrphy_timing, ARRAY_SIZE(ddrphy_timing), DDRPHY_BASE
+ .name = "timing",
+ .desc = ddrphy_timing,
+ .size = ARRAY_SIZE(ddrphy_timing),
+ .base = DDRPHY_BASE
},
[REGPHY_CAL] = {
- "cal", ddrphy_cal, ARRAY_SIZE(ddrphy_cal), DDRPHY_BASE
+ .name = "cal",
+ .desc = ddrphy_cal,
+ .size = ARRAY_SIZE(ddrphy_cal),
+ .base = DDRPHY_BASE
},
[REG_DYN] = {
- "dyn", ddr_dyn, ARRAY_SIZE(ddr_dyn), DDR_BASE
+ .name = "dyn",
+ .desc = ddr_dyn,
+ .size = ARRAY_SIZE(ddr_dyn),
+ .base = DDR_BASE
},
[REGPHY_DYN] = {
- "dyn", ddrphy_dyn, ARRAY_SIZE(ddrphy_dyn), DDRPHY_BASE
+ .name = "dyn",
+ .desc = ddrphy_dyn,
+ .size = ARRAY_SIZE(ddrphy_dyn),
+ .base = DDRPHY_BASE
},
};
-static uint32_t get_base_addr(const struct ddr_info *priv, enum base_type base)
+static uintptr_t get_base_addr(const struct ddr_info *priv, enum base_type base)
{
if (base == DDRPHY_BASE) {
- return (uint32_t)priv->phy;
+ return (uintptr_t)priv->phy;
} else {
- return (uint32_t)priv->ctl;
+ return (uintptr_t)priv->ctl;
}
}
@@ -275,21 +303,22 @@
const void *param)
{
unsigned int i;
- unsigned int *ptr, value;
+ unsigned int value;
enum base_type base = ddr_registers[type].base;
- uint32_t base_addr = get_base_addr(priv, base);
+ uintptr_t base_addr = get_base_addr(priv, base);
const struct reg_desc *desc = ddr_registers[type].desc;
VERBOSE("init %s\n", ddr_registers[type].name);
for (i = 0; i < ddr_registers[type].size; i++) {
- ptr = (unsigned int *)(base_addr + desc[i].offset);
+ 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 *)((uint32_t)param +
+ value = *((uint32_t *)((uintptr_t)param +
desc[i].par_offset));
- mmio_write_32((uint32_t)ptr, value);
+ mmio_write_32(ptr, value);
}
}
}
@@ -305,15 +334,15 @@
time0 = start;
do {
- pgsr = mmio_read_32((uint32_t)&phy->pgsr);
+ pgsr = mmio_read_32((uintptr_t)&phy->pgsr);
time = get_timer(start);
if (time != time0) {
- VERBOSE(" > [0x%x] pgsr = 0x%x &\n",
- (uint32_t)&phy->pgsr, pgsr);
- VERBOSE(" [0x%x] pir = 0x%x (time=%x)\n",
- (uint32_t)&phy->pir,
- mmio_read_32((uint32_t)&phy->pir),
- (uint32_t)time);
+ VERBOSE(" > [0x%lx] pgsr = 0x%x &\n",
+ (uintptr_t)&phy->pgsr, pgsr);
+ VERBOSE(" [0x%lx] pir = 0x%x (time=%lx)\n",
+ (uintptr_t)&phy->pir,
+ mmio_read_32((uintptr_t)&phy->pir),
+ time);
}
time0 = time;
@@ -341,18 +370,18 @@
error++;
}
} while ((pgsr & DDRPHYC_PGSR_IDONE) == 0U && error == 0);
- VERBOSE("\n[0x%x] pgsr = 0x%x\n",
- (uint32_t)&phy->pgsr, pgsr);
+ VERBOSE("\n[0x%lx] pgsr = 0x%x\n",
+ (uintptr_t)&phy->pgsr, pgsr);
}
static void stm32mp1_ddrphy_init(struct stm32mp1_ddrphy *phy, uint32_t pir)
{
uint32_t pir_init = pir | DDRPHYC_PIR_INIT;
- mmio_write_32((uint32_t)&phy->pir, pir_init);
- VERBOSE("[0x%x] pir = 0x%x -> 0x%x\n",
- (uint32_t)&phy->pir, pir_init,
- mmio_read_32((uint32_t)&phy->pir));
+ 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);
@@ -364,9 +393,9 @@
/* Start quasi dynamic register update */
static void stm32mp1_start_sw_done(struct stm32mp1_ddrctl *ctl)
{
- mmio_clrbits_32((uint32_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE);
- VERBOSE("[0x%x] swctl = 0x%x\n",
- (uint32_t)&ctl->swctl, mmio_read_32((uint32_t)&ctl->swctl));
+ 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 */
@@ -375,15 +404,15 @@
unsigned long start;
uint32_t swstat;
- mmio_setbits_32((uint32_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE);
- VERBOSE("[0x%x] swctl = 0x%x\n",
- (uint32_t)&ctl->swctl, mmio_read_32((uint32_t)&ctl->swctl));
+ 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));
start = get_timer(0);
do {
- swstat = mmio_read_32((uint32_t)&ctl->swstat);
- VERBOSE("[0x%x] swstat = 0x%x ",
- (uint32_t)&ctl->swstat, swstat);
+ swstat = mmio_read_32((uintptr_t)&ctl->swstat);
+ VERBOSE("[0x%lx] swstat = 0x%x ",
+ (uintptr_t)&ctl->swstat, swstat);
VERBOSE("timer in ms 0x%x = start 0x%lx\r",
get_timer(0), start);
if (get_timer(start) > plat_get_syscnt_freq2()) {
@@ -391,8 +420,8 @@
}
} while ((swstat & DDRCTRL_SWSTAT_SW_DONE_ACK) == 0U);
- VERBOSE("[0x%x] swstat = 0x%x\n",
- (uint32_t)&ctl->swstat, swstat);
+ VERBOSE("[0x%lx] swstat = 0x%x\n",
+ (uintptr_t)&ctl->swstat, swstat);
}
/* Wait quasi dynamic register update */
@@ -406,11 +435,11 @@
start = get_timer(0);
for ( ; ; ) {
- stat = mmio_read_32((uint32_t)&priv->ctl->stat);
+ 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%x] stat = 0x%x\n",
- (uint32_t)&priv->ctl->stat, stat);
+ VERBOSE("[0x%lx] stat = 0x%x\n",
+ (uintptr_t)&priv->ctl->stat, stat);
VERBOSE("timer in ms 0x%x = start 0x%lx\r",
get_timer(0), start);
if (get_timer(start) > plat_get_syscnt_freq2()) {
@@ -441,8 +470,8 @@
}
}
- VERBOSE("[0x%x] stat = 0x%x\n",
- (uint32_t)&priv->ctl->stat, stat);
+ VERBOSE("[0x%lx] stat = 0x%x\n",
+ (uintptr_t)&priv->ctl->stat, stat);
}
/* Mode Register Writes (MRW or MRS) */
@@ -459,7 +488,7 @@
* No write should be performed to MRCTRL0 and MRCTRL1
* if MRSTAT.mr_wr_busy = 1.
*/
- while ((mmio_read_32((uint32_t)&priv->ctl->mrstat) &
+ while ((mmio_read_32((uintptr_t)&priv->ctl->mrstat) &
DDRCTRL_MRSTAT_MR_WR_BUSY) != 0U) {
;
}
@@ -472,14 +501,14 @@
DDRCTRL_MRCTRL0_MR_RANK_ALL |
(((uint32_t)addr << DDRCTRL_MRCTRL0_MR_ADDR_SHIFT) &
DDRCTRL_MRCTRL0_MR_ADDR_MASK);
- mmio_write_32((uint32_t)&priv->ctl->mrctrl0, mrctrl0);
- VERBOSE("[0x%x] mrctrl0 = 0x%x (0x%x)\n",
- (uint32_t)&priv->ctl->mrctrl0,
- mmio_read_32((uint32_t)&priv->ctl->mrctrl0), mrctrl0);
- mmio_write_32((uint32_t)&priv->ctl->mrctrl1, data);
- VERBOSE("[0x%x] mrctrl1 = 0x%x\n",
- (uint32_t)&priv->ctl->mrctrl1,
- mmio_read_32((uint32_t)&priv->ctl->mrctrl1));
+ 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
@@ -489,22 +518,22 @@
* initiated until it is deasserted.
*/
mrctrl0 |= DDRCTRL_MRCTRL0_MR_WR;
- mmio_write_32((uint32_t)&priv->ctl->mrctrl0, mrctrl0);
+ mmio_write_32((uintptr_t)&priv->ctl->mrctrl0, mrctrl0);
- while ((mmio_read_32((uint32_t)&priv->ctl->mrstat) &
+ while ((mmio_read_32((uintptr_t)&priv->ctl->mrstat) &
DDRCTRL_MRSTAT_MR_WR_BUSY) != 0U) {
;
}
- VERBOSE("[0x%x] mrctrl0 = 0x%x\n",
- (uint32_t)&priv->ctl->mrctrl0, mrctrl0);
+ 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 ddr_info *priv)
{
- uint32_t mr1 = mmio_read_32((uint32_t)&priv->phy->mr1);
- uint32_t mr2 = mmio_read_32((uint32_t)&priv->phy->mr2);
+ 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);
@@ -514,10 +543,10 @@
* 1. Set the DBG1.dis_hif = 1.
* This prevents further reads/writes being received on the HIF.
*/
- mmio_setbits_32((uint32_t)&priv->ctl->dbg1, DDRCTRL_DBG1_DIS_HIF);
- VERBOSE("[0x%x] dbg1 = 0x%x\n",
- (uint32_t)&priv->ctl->dbg1,
- mmio_read_32((uint32_t)&priv->ctl->dbg1));
+ 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
@@ -528,9 +557,9 @@
* DBGCAM.dbg_hpr_q_depth = 0.
*/
do {
- dbgcam = mmio_read_32((uint32_t)&priv->ctl->dbgcam);
- VERBOSE("[0x%x] dbgcam = 0x%x\n",
- (uint32_t)&priv->ctl->dbgcam, dbgcam);
+ 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));
@@ -574,11 +603,11 @@
* PWRCTL.selfref_sw = 1, and polling STAT.operating_mode to ensure
* the DDRC has entered self-refresh.
*/
- mmio_setbits_32((uint32_t)&priv->ctl->pwrctl,
+ mmio_setbits_32((uintptr_t)&priv->ctl->pwrctl,
DDRCTRL_PWRCTL_SELFREF_SW);
- VERBOSE("[0x%x] pwrctl = 0x%x\n",
- (uint32_t)&priv->ctl->pwrctl,
- mmio_read_32((uint32_t)&priv->ctl->pwrctl));
+ 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
@@ -594,10 +623,10 @@
*/
stm32mp1_start_sw_done(priv->ctl);
- mmio_setbits_32((uint32_t)&priv->ctl->mstr, DDRCTRL_MSTR_DLL_OFF_MODE);
- VERBOSE("[0x%x] mstr = 0x%x\n",
- (uint32_t)&priv->ctl->mstr,
- mmio_read_32((uint32_t)&priv->ctl->mstr));
+ 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));
stm32mp1_wait_sw_done_ack(priv->ctl);
@@ -611,26 +640,26 @@
/* Change Bypass Mode Frequency Range */
if (stm32mp1_clk_get_rate(DDRPHYC) < 100000000U) {
- mmio_clrbits_32((uint32_t)&priv->phy->dllgcr,
+ mmio_clrbits_32((uintptr_t)&priv->phy->dllgcr,
DDRPHYC_DLLGCR_BPS200);
} else {
- mmio_setbits_32((uint32_t)&priv->phy->dllgcr,
+ mmio_setbits_32((uintptr_t)&priv->phy->dllgcr,
DDRPHYC_DLLGCR_BPS200);
}
- mmio_setbits_32((uint32_t)&priv->phy->acdllcr, DDRPHYC_ACDLLCR_DLLDIS);
+ mmio_setbits_32((uintptr_t)&priv->phy->acdllcr, DDRPHYC_ACDLLCR_DLLDIS);
- mmio_setbits_32((uint32_t)&priv->phy->dx0dllcr,
+ mmio_setbits_32((uintptr_t)&priv->phy->dx0dllcr,
DDRPHYC_DXNDLLCR_DLLDIS);
- mmio_setbits_32((uint32_t)&priv->phy->dx1dllcr,
+ mmio_setbits_32((uintptr_t)&priv->phy->dx1dllcr,
DDRPHYC_DXNDLLCR_DLLDIS);
- mmio_setbits_32((uint32_t)&priv->phy->dx2dllcr,
+ mmio_setbits_32((uintptr_t)&priv->phy->dx2dllcr,
DDRPHYC_DXNDLLCR_DLLDIS);
- mmio_setbits_32((uint32_t)&priv->phy->dx3dllcr,
+ mmio_setbits_32((uintptr_t)&priv->phy->dx3dllcr,
DDRPHYC_DXNDLLCR_DLLDIS);
/* 12. Exit the self-refresh state by setting PWRCTL.selfref_sw = 0. */
- mmio_clrbits_32((uint32_t)&priv->ctl->pwrctl,
+ mmio_clrbits_32((uintptr_t)&priv->ctl->pwrctl,
DDRCTRL_PWRCTL_SELFREF_SW);
stm32mp1_wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_NORMAL);
@@ -646,20 +675,20 @@
*/
/* 15. Write DBG1.dis_hif = 0 to re-enable reads and writes. */
- mmio_clrbits_32((uint32_t)&priv->ctl->dbg1, DDRCTRL_DBG1_DIS_HIF);
- VERBOSE("[0x%x] dbg1 = 0x%x\n",
- (uint32_t)&priv->ctl->dbg1,
- mmio_read_32((uint32_t)&priv->ctl->dbg1));
+ 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 stm32mp1_ddrctl *ctl)
{
stm32mp1_start_sw_done(ctl);
/* Quasi-dynamic register update*/
- mmio_setbits_32((uint32_t)&ctl->rfshctl3,
+ mmio_setbits_32((uintptr_t)&ctl->rfshctl3,
DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH);
- mmio_clrbits_32((uint32_t)&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN);
- mmio_clrbits_32((uint32_t)&ctl->dfimisc,
+ mmio_clrbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN);
+ mmio_clrbits_32((uintptr_t)&ctl->dfimisc,
DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
stm32mp1_wait_sw_done_ack(ctl);
}
@@ -669,14 +698,14 @@
{
stm32mp1_start_sw_done(ctl);
if ((rfshctl3 & DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH) == 0U) {
- mmio_clrbits_32((uint32_t)&ctl->rfshctl3,
+ mmio_clrbits_32((uintptr_t)&ctl->rfshctl3,
DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH);
}
if ((pwrctl & DDRCTRL_PWRCTL_POWERDOWN_EN) != 0U) {
- mmio_setbits_32((uint32_t)&ctl->pwrctl,
+ mmio_setbits_32((uintptr_t)&ctl->pwrctl,
DDRCTRL_PWRCTL_POWERDOWN_EN);
}
- mmio_setbits_32((uint32_t)&ctl->dfimisc,
+ mmio_setbits_32((uintptr_t)&ctl->dfimisc,
DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
stm32mp1_wait_sw_done_ack(ctl);
}
@@ -694,12 +723,14 @@
struct stm32mp1_ddr_config *config)
{
uint32_t pir;
- int ret;
+ int ret = -EINVAL;
if ((config->c_reg.mstr & DDRCTRL_MSTR_DDR3) != 0U) {
ret = board_ddr_power_init(STM32MP_DDR3);
- } else {
+ } else if ((config->c_reg.mstr & DDRCTRL_MSTR_LPDDR2) != 0U) {
ret = board_ddr_power_init(STM32MP_LPDDR2);
+ } else {
+ ERROR("DDR type not supported\n");
}
if (ret != 0) {
@@ -707,7 +738,7 @@
}
VERBOSE("name = %s\n", config->info.name);
- VERBOSE("speed = %d MHz\n", config->info.speed);
+ VERBOSE("speed = %d kHz\n", config->info.speed);
VERBOSE("size = 0x%x\n", config->info.size);
/* DDR INIT SEQUENCE */
@@ -746,11 +777,11 @@
/* 1.5. initialize registers ddr_umctl2 */
/* Stop uMCTL2 before PHY is ready */
- mmio_clrbits_32((uint32_t)&priv->ctl->dfimisc,
+ mmio_clrbits_32((uintptr_t)&priv->ctl->dfimisc,
DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
- VERBOSE("[0x%x] dfimisc = 0x%x\n",
- (uint32_t)&priv->ctl->dfimisc,
- mmio_read_32((uint32_t)&priv->ctl->dfimisc));
+ VERBOSE("[0x%lx] dfimisc = 0x%x\n",
+ (uintptr_t)&priv->ctl->dfimisc,
+ mmio_read_32((uintptr_t)&priv->ctl->dfimisc));
set_reg(priv, REG_REG, &config->c_reg);
@@ -759,23 +790,23 @@
(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((uint32_t)&priv->ctl->mstr,
+ mmio_clrbits_32((uintptr_t)&priv->ctl->mstr,
DDRCTRL_MSTR_DLL_OFF_MODE);
- VERBOSE("[0x%x] mstr = 0x%x\n",
- (uint32_t)&priv->ctl->mstr,
- mmio_read_32((uint32_t)&priv->ctl->mstr));
+ VERBOSE("[0x%lx] mstr = 0x%x\n",
+ (uintptr_t)&priv->ctl->mstr,
+ mmio_read_32((uintptr_t)&priv->ctl->mstr));
}
set_reg(priv, REG_TIMING, &config->c_timing);
set_reg(priv, REG_MAP, &config->c_map);
/* Skip CTRL init, SDRAM init is done by PHY PUBL */
- mmio_clrsetbits_32((uint32_t)&priv->ctl->init0,
+ mmio_clrsetbits_32((uintptr_t)&priv->ctl->init0,
DDRCTRL_INIT0_SKIP_DRAM_INIT_MASK,
DDRCTRL_INIT0_SKIP_DRAM_INIT_NORMAL);
- VERBOSE("[0x%x] init0 = 0x%x\n",
- (uint32_t)&priv->ctl->init0,
- mmio_read_32((uint32_t)&priv->ctl->init0));
+ VERBOSE("[0x%lx] init0 = 0x%x\n",
+ (uintptr_t)&priv->ctl->init0,
+ mmio_read_32((uintptr_t)&priv->ctl->init0));
set_reg(priv, REG_PERF, &config->c_perf);
@@ -797,10 +828,10 @@
(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((uint32_t)&priv->phy->mr1, BIT(0));
- VERBOSE("[0x%x] mr1 = 0x%x\n",
- (uint32_t)&priv->phy->mr1,
- mmio_read_32((uint32_t)&priv->phy->mr1));
+ 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));
}
/*
@@ -830,11 +861,11 @@
*/
stm32mp1_start_sw_done(priv->ctl);
- mmio_setbits_32((uint32_t)&priv->ctl->dfimisc,
+ mmio_setbits_32((uintptr_t)&priv->ctl->dfimisc,
DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN);
- VERBOSE("[0x%x] dfimisc = 0x%x\n",
- (uint32_t)&priv->ctl->dfimisc,
- mmio_read_32((uint32_t)&priv->ctl->dfimisc));
+ VERBOSE("[0x%lx] dfimisc = 0x%x\n",
+ (uintptr_t)&priv->ctl->dfimisc,
+ mmio_read_32((uintptr_t)&priv->ctl->dfimisc));
stm32mp1_wait_sw_done_ack(priv->ctl);
@@ -884,14 +915,16 @@
config->c_reg.pwrctl);
/* Enable uMCTL2 AXI port 0 */
- mmio_setbits_32((uint32_t)&priv->ctl->pctrl_0, DDRCTRL_PCTRL_N_PORT_EN);
- VERBOSE("[0x%x] pctrl_0 = 0x%x\n",
- (uint32_t)&priv->ctl->pctrl_0,
- mmio_read_32((uint32_t)&priv->ctl->pctrl_0));
+ mmio_setbits_32((uintptr_t)&priv->ctl->pctrl_0,
+ DDRCTRL_PCTRL_N_PORT_EN);
+ VERBOSE("[0x%lx] pctrl_0 = 0x%x\n",
+ (uintptr_t)&priv->ctl->pctrl_0,
+ mmio_read_32((uintptr_t)&priv->ctl->pctrl_0));
/* Enable uMCTL2 AXI port 1 */
- mmio_setbits_32((uint32_t)&priv->ctl->pctrl_1, DDRCTRL_PCTRL_N_PORT_EN);
- VERBOSE("[0x%x] pctrl_1 = 0x%x\n",
- (uint32_t)&priv->ctl->pctrl_1,
- mmio_read_32((uint32_t)&priv->ctl->pctrl_1));
+ mmio_setbits_32((uintptr_t)&priv->ctl->pctrl_1,
+ DDRCTRL_PCTRL_N_PORT_EN);
+ VERBOSE("[0x%lx] pctrl_1 = 0x%x\n",
+ (uintptr_t)&priv->ctl->pctrl_1,
+ mmio_read_32((uintptr_t)&priv->ctl->pctrl_1));
}
diff --git a/drivers/st/ddr/stm32mp1_ram.c b/drivers/st/ddr/stm32mp1_ram.c
index 127b6c7..e65fbea 100644
--- a/drivers/st/ddr/stm32mp1_ram.c
+++ b/drivers/st/ddr/stm32mp1_ram.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
*/
@@ -25,7 +25,7 @@
static struct ddr_info ddr_priv_data;
-int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint16_t mem_speed)
+int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed)
{
unsigned long ddrphy_clk, ddr_clk, mem_speed_hz;
@@ -33,10 +33,10 @@
ddrphy_clk = stm32mp1_clk_get_rate(DDRPHYC);
- VERBOSE("DDR: mem_speed (%d MHz), RCC %ld MHz\n",
- mem_speed, ddrphy_clk / 1000U / 1000U);
+ VERBOSE("DDR: mem_speed (%d kHz), RCC %ld kHz\n",
+ mem_speed, ddrphy_clk / 1000U);
- mem_speed_hz = (uint32_t)mem_speed * 1000U * 1000U;
+ mem_speed_hz = mem_speed * 1000U;
/* Max 10% frequency delta */
if (ddrphy_clk > mem_speed_hz) {
@@ -44,9 +44,9 @@
} else {
ddr_clk = mem_speed_hz - ddrphy_clk;
}
- if (ddr_clk > mem_speed_hz) {
- ERROR("DDR expected freq %d MHz, current is %ld MHz\n",
- mem_speed, ddrphy_clk / 1000U / 1000U);
+ if (ddr_clk > (mem_speed_hz / 10)) {
+ ERROR("DDR expected freq %d kHz, current is %ld kHz\n",
+ mem_speed, ddrphy_clk / 1000U);
return -1;
}
return 0;
@@ -208,11 +208,16 @@
return -EINVAL;
}
- config.info.speed =
- (uint16_t)fdt_read_uint32_default(node, "st,mem-speed",
- STM32MP1_DDR_SPEED_DFLT);
- config.info.size = fdt_read_uint32_default(node, "st,mem-size",
- STM32MP1_DDR_SIZE_DFLT);
+ config.info.speed = fdt_read_uint32_default(node, "st,mem-speed", 0);
+ if (!config.info.speed) {
+ VERBOSE("%s: no st,mem-speed\n", __func__);
+ return -EINVAL;
+ }
+ config.info.size = fdt_read_uint32_default(node, "st,mem-size", 0);
+ if (!config.info.size) {
+ VERBOSE("%s: no st,mem-size\n", __func__);
+ return -EINVAL;
+ }
config.info.name = fdt_getprop(fdt, node, "st,mem-name", &len);
if (config.info.name == NULL) {
VERBOSE("%s: no st,mem-name\n", __func__);
@@ -222,7 +227,7 @@
for (idx = 0; idx < ARRAY_SIZE(param); idx++) {
ret = fdt_read_uint32_array(node, param[idx].name,
- (void *)((uint32_t)&config +
+ (void *)((uintptr_t)&config +
param[idx].offset),
param[idx].size);
@@ -261,8 +266,8 @@
VERBOSE("%s : ram size(%x, %x)\n", __func__,
(uint32_t)priv->info.base, (uint32_t)priv->info.size);
- dcsw_op_all(DC_OP_CISW);
write_sctlr(read_sctlr() & ~SCTLR_C_BIT);
+ dcsw_op_all(DC_OP_CISW);
uret = ddr_test_data_bus();
if (uret != 0U) {
diff --git a/drivers/st/gpio/stm32_gpio.c b/drivers/st/gpio/stm32_gpio.c
index 9591e37..d217c45 100644
--- a/drivers/st/gpio/stm32_gpio.c
+++ b/drivers/st/gpio/stm32_gpio.c
@@ -1,87 +1,276 @@
/*
- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <assert.h>
+#include <errno.h>
#include <stdbool.h>
+#include <libfdt.h>
+
+#include <platform_def.h>
+
#include <common/bl_common.h>
#include <common/debug.h>
#include <drivers/st/stm32_gpio.h>
+#include <drivers/st/stm32mp1_clk.h>
+#include <drivers/st/stm32mp1_clkfunc.h>
#include <lib/mmio.h>
+#include <lib/utils_def.h>
-static bool check_gpio(uint32_t bank, uint32_t pin)
+#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)
+
+/*******************************************************************************
+ * 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)
{
- if (pin > GPIO_PIN_MAX) {
- ERROR("%s: wrong pin number (%d)\n", __func__, pin);
- return false;
- }
+ int pinctrl_subnode;
+ uint32_t bank_offset = stm32_get_gpio_bank_offset(bank);
- if ((bank > GPIO_BANK_K) && (bank != GPIO_BANK_Z)) {
- ERROR("%s: wrong GPIO bank number (%d)\n", __func__, bank);
- return false;
+ 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 true;
+ return 0;
}
-void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed,
- uint32_t pull, uint32_t alternate)
+/*******************************************************************************
+ * 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)
{
- volatile uint32_t bank_address;
+ 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;
- if (!check_gpio(bank, pin)) {
- return;
+ cuint = fdt_getprop(fdt, node, "pinmux", &len);
+ if (cuint == NULL) {
+ return -FDT_ERR_NOTFOUND;
}
- if (bank == GPIO_BANK_Z) {
- bank_address = STM32_GPIOZ_BANK;
+ 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 {
- bank_address = STM32_GPIOA_BANK +
- (bank * STM32_GPIO_BANK_OFFSET);
+ 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);
+ 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) {
+ mode |= GPIO_OPEN_DRAIN;
+ }
+
+ 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, speed, pull, 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 = 0;
+ uint32_t i;
+ uint8_t status = fdt_get_status(node);
+ void *fdt;
+
+ if (fdt_get_address(&fdt) == 0) {
+ return -ENOENT;
+ }
+
+ 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;
+
- mmio_clrbits_32(bank_address + GPIO_MODE_OFFSET,
+ 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;
+}
+
+void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed,
+ uint32_t pull, 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);
+
+ stm32mp1_clk_enable(clock);
+
+ mmio_clrbits_32(base + GPIO_MODE_OFFSET,
((uint32_t)GPIO_MODE_MASK << (pin << 1)));
- mmio_setbits_32(bank_address + GPIO_MODE_OFFSET,
+ mmio_setbits_32(base + GPIO_MODE_OFFSET,
(mode & ~GPIO_OPEN_DRAIN) << (pin << 1));
if ((mode & GPIO_OPEN_DRAIN) != 0U) {
- mmio_setbits_32(bank_address + GPIO_TYPE_OFFSET,
- BIT(pin));
+ mmio_setbits_32(base + GPIO_TYPE_OFFSET, BIT(pin));
+ } else {
+ mmio_clrbits_32(base + GPIO_TYPE_OFFSET, BIT(pin));
}
- mmio_clrbits_32(bank_address + GPIO_SPEED_OFFSET,
+ mmio_clrbits_32(base + GPIO_SPEED_OFFSET,
((uint32_t)GPIO_SPEED_MASK << (pin << 1)));
- mmio_setbits_32(bank_address + GPIO_SPEED_OFFSET, speed << (pin << 1));
+ mmio_setbits_32(base + GPIO_SPEED_OFFSET, speed << (pin << 1));
- mmio_clrbits_32(bank_address + GPIO_PUPD_OFFSET,
+ mmio_clrbits_32(base + GPIO_PUPD_OFFSET,
((uint32_t)GPIO_PULL_MASK << (pin << 1)));
- mmio_setbits_32(bank_address + GPIO_PUPD_OFFSET, pull << (pin << 1));
+ mmio_setbits_32(base + GPIO_PUPD_OFFSET, pull << (pin << 1));
if (pin < GPIO_ALT_LOWER_LIMIT) {
- mmio_clrbits_32(bank_address + GPIO_AFRL_OFFSET,
+ mmio_clrbits_32(base + GPIO_AFRL_OFFSET,
((uint32_t)GPIO_ALTERNATE_MASK << (pin << 2)));
- mmio_setbits_32(bank_address + GPIO_AFRL_OFFSET,
+ mmio_setbits_32(base + GPIO_AFRL_OFFSET,
alternate << (pin << 2));
} else {
- mmio_clrbits_32(bank_address + GPIO_AFRH_OFFSET,
+ mmio_clrbits_32(base + GPIO_AFRH_OFFSET,
((uint32_t)GPIO_ALTERNATE_MASK <<
((pin - GPIO_ALT_LOWER_LIMIT) << 2)));
- mmio_setbits_32(bank_address + GPIO_AFRH_OFFSET,
+ mmio_setbits_32(base + GPIO_AFRH_OFFSET,
alternate << ((pin - GPIO_ALT_LOWER_LIMIT) <<
2));
}
VERBOSE("GPIO %u mode set to 0x%x\n", bank,
- mmio_read_32(bank_address + GPIO_MODE_OFFSET));
+ mmio_read_32(base + GPIO_MODE_OFFSET));
VERBOSE("GPIO %u speed set to 0x%x\n", bank,
- mmio_read_32(bank_address + GPIO_SPEED_OFFSET));
+ mmio_read_32(base + GPIO_SPEED_OFFSET));
VERBOSE("GPIO %u mode pull to 0x%x\n", bank,
- mmio_read_32(bank_address + GPIO_PUPD_OFFSET));
+ mmio_read_32(base + GPIO_PUPD_OFFSET));
VERBOSE("GPIO %u mode alternate low to 0x%x\n", bank,
- mmio_read_32(bank_address + GPIO_AFRL_OFFSET));
+ mmio_read_32(base + GPIO_AFRL_OFFSET));
VERBOSE("GPIO %u mode alternate high to 0x%x\n", bank,
- mmio_read_32(bank_address + GPIO_AFRH_OFFSET));
+ mmio_read_32(base + GPIO_AFRH_OFFSET));
+
+ stm32mp1_clk_disable((unsigned long)clock);
+}
+
+void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure)
+{
+ uintptr_t base = stm32_get_gpio_bank_base(bank);
+ int clock = stm32_get_gpio_bank_clock(bank);
+
+ assert(pin <= GPIO_PIN_MAX);
+
+ stm32mp1_clk_enable((unsigned long)clock);
+
+ if (secure) {
+ mmio_setbits_32(base + GPIO_SECR_OFFSET, BIT(pin));
+ } else {
+ mmio_clrbits_32(base + GPIO_SECR_OFFSET, BIT(pin));
+ }
+
+ stm32mp1_clk_disable((unsigned long)clock);
}
diff --git a/drivers/st/pmic/stm32_i2c.c b/drivers/st/i2c/stm32_i2c.c
similarity index 99%
rename from drivers/st/pmic/stm32_i2c.c
rename to drivers/st/i2c/stm32_i2c.c
index f861ba2..2be7afe 100644
--- a/drivers/st/pmic/stm32_i2c.c
+++ b/drivers/st/i2c/stm32_i2c.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
diff --git a/drivers/st/io/io_stm32image.c b/drivers/st/io/io_stm32image.c
index 0164a2d..dc2977d 100644
--- a/drivers/st/io/io_stm32image.c
+++ b/drivers/st/io/io_stm32image.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -94,6 +94,8 @@
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 =
@@ -193,21 +195,29 @@
result = io_read(backend_handle, (uintptr_t)header,
MAX_LBA_SIZE, (size_t *)&bytes_read);
if (result != 0) {
- ERROR("%s: io_read (%i)\n", __func__, result);
- break;
+ 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)) {
- WARN("%s: partition %s wrong header\n",
- __func__, current_part->name);
+ 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("Out of memory\n");
+ WARN("%s : partition %s not found\n",
+ __func__, current_part->name);
result = -ENOMEM;
break;
}
@@ -221,9 +231,13 @@
return result;
}
- *length = header->image_length;
+ if (header->image_length < stm32image_dev.lba_size) {
+ *length = stm32image_dev.lba_size;
+ } else {
+ *length = header->image_length;
+ }
- INFO("STM32 Image size : %i\n", *length);
+ INFO("STM32 Image size : %lu\n", (unsigned long)*length);
return 0;
}
@@ -266,11 +280,10 @@
static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer,
size_t length, size_t *length_read)
{
- int result = 0, offset, local_length = 0;
+ int result = 0;
uint8_t *local_buffer = (uint8_t *)buffer;
boot_api_image_header_t *header =
(boot_api_image_header_t *)first_lba_buffer;
- uintptr_t backend_handle;
assert(entity != NULL);
assert(buffer != 0U);
@@ -279,8 +292,17 @@
*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 */
@@ -342,8 +364,8 @@
if (result != 0) {
ERROR("%s: io_read (%i)\n", __func__, result);
*length_read = 0;
- io_close(backend_handle);
- break;
+ header->magic = 0;
+ continue;
}
result = check_header(header, buffer);
@@ -351,8 +373,6 @@
ERROR("Header check failed\n");
*length_read = 0;
header->magic = 0;
- io_close(backend_handle);
- break;
}
io_close(backend_handle);
diff --git a/drivers/st/mmc/stm32_sdmmc2.c b/drivers/st/mmc/stm32_sdmmc2.c
index 05f5ae1..57812d8 100644
--- a/drivers/st/mmc/stm32_sdmmc2.c
+++ b/drivers/st/mmc/stm32_sdmmc2.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -17,6 +17,7 @@
#include <common/debug.h>
#include <drivers/delay_timer.h>
#include <drivers/mmc.h>
+#include <drivers/st/stm32_gpio.h>
#include <drivers/st/stm32_sdmmc2.h>
#include <drivers/st/stm32mp1_clk.h>
#include <drivers/st/stm32mp1_rcc.h>
@@ -470,12 +471,11 @@
}
/* Prepare CMD 16*/
- mmio_write_32(base + SDMMC_DTIMER, UINT32_MAX);
+ mmio_write_32(base + SDMMC_DTIMER, 0);
mmio_write_32(base + SDMMC_DLENR, 0);
- mmio_clrsetbits_32(base + SDMMC_DCTRLR,
- SDMMC_DCTRLR_CLEAR_MASK, SDMMC_DCTRLR_DTDIR);
+ mmio_write_32(base + SDMMC_DCTRLR, 0);
zeromem(&cmd, sizeof(struct mmc_cmd));
@@ -643,7 +643,7 @@
return -FDT_ERR_NOTFOUND;
}
- if (fdt_check_status(sdmmc_node) == 0) {
+ if (fdt_get_status(sdmmc_node) == DT_DISABLED) {
return -FDT_ERR_NOTFOUND;
}
@@ -667,15 +667,15 @@
cuint++;
sdmmc2_params.reset_id = fdt32_to_cpu(*cuint);
- if ((fdt_getprop(fdt, sdmmc_node, "st,pin-ckin", NULL)) != NULL) {
+ 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,dirpol", NULL)) != NULL) {
+ if ((fdt_getprop(fdt, sdmmc_node, "st,sig-dir", NULL)) != NULL) {
sdmmc2_params.dirpol = SDMMC_POWER_DIRPOL;
}
- if ((fdt_getprop(fdt, sdmmc_node, "st,negedge", NULL)) != NULL) {
+ if ((fdt_getprop(fdt, sdmmc_node, "st,neg-edge", NULL)) != NULL) {
sdmmc2_params.negedge = SDMMC_CLKCR_NEGEDGE;
}
diff --git a/drivers/st/pmic/stm32mp1_pmic.c b/drivers/st/pmic/stm32mp_pmic.c
similarity index 69%
rename from drivers/st/pmic/stm32mp1_pmic.c
rename to drivers/st/pmic/stm32mp_pmic.c
index c5bdfc0..6beabc1 100644
--- a/drivers/st/pmic/stm32mp1_pmic.c
+++ b/drivers/st/pmic/stm32mp_pmic.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -13,10 +13,10 @@
#include <common/debug.h>
#include <drivers/delay_timer.h>
+#include <drivers/st/stm32mp_pmic.h>
#include <drivers/st/stm32_gpio.h>
#include <drivers/st/stm32mp1_clk.h>
-#include <drivers/st/stm32mp1_pmic.h>
-#include <drivers/st/stpmu1.h>
+#include <drivers/st/stpmic1.h>
#include <lib/mmio.h>
#include <lib/utils_def.h>
@@ -27,23 +27,23 @@
#define MASK_RESET_BUCK3 BIT(2)
-#define STPMU1_LDO12356_OUTPUT_MASK (uint8_t)(GENMASK(6, 2))
-#define STPMU1_LDO12356_OUTPUT_SHIFT 2
-#define STPMU1_LDO3_MODE (uint8_t)(BIT(7))
-#define STPMU1_LDO3_DDR_SEL 31U
-#define STPMU1_LDO3_1800000 (9U << STPMU1_LDO12356_OUTPUT_SHIFT)
+#define STPMIC1_LDO12356_OUTPUT_MASK (uint8_t)(GENMASK(6, 2))
+#define STPMIC1_LDO12356_OUTPUT_SHIFT 2
+#define STPMIC1_LDO3_MODE (uint8_t)(BIT(7))
+#define STPMIC1_LDO3_DDR_SEL 31U
+#define STPMIC1_LDO3_1800000 (9U << STPMIC1_LDO12356_OUTPUT_SHIFT)
-#define STPMU1_BUCK_OUTPUT_SHIFT 2
-#define STPMU1_BUCK3_1V8 (39U << STPMU1_BUCK_OUTPUT_SHIFT)
+#define STPMIC1_BUCK_OUTPUT_SHIFT 2
+#define STPMIC1_BUCK3_1V8 (39U << STPMIC1_BUCK_OUTPUT_SHIFT)
-#define STPMU1_DEFAULT_START_UP_DELAY_MS 1
+#define STPMIC1_DEFAULT_START_UP_DELAY_MS 1
static struct i2c_handle_s i2c_handle;
static uint32_t pmic_i2c_addr;
static int dt_get_pmic_node(void *fdt)
{
- return fdt_node_offset_by_compatible(fdt, -1, "st,stpmu1");
+ return fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1");
}
bool dt_check_pmic(void)
@@ -61,7 +61,7 @@
return false;
}
- return fdt_check_status(node);
+ return fdt_get_status(node);
}
static int dt_pmic_i2c_config(struct dt_node_info *i2c_info)
@@ -138,16 +138,16 @@
voltage = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U);
node_name = fdt_get_name(fdt, regulator_node, NULL);
- if (stpmu1_is_regulator_enabled(node_name) == 0U) {
+ if (stpmic1_is_regulator_enabled(node_name) == 0U) {
int status;
- status = stpmu1_regulator_voltage_set(node_name,
- voltage);
+ status = stpmic1_regulator_voltage_set(node_name,
+ voltage);
if (status != 0) {
return status;
}
- status = stpmu1_regulator_enable(node_name);
+ status = stpmic1_regulator_enable(node_name);
if (status != 0) {
return status;
}
@@ -204,7 +204,7 @@
panic();
}
- stpmu1_bind_i2c(&i2c_handle, (uint16_t)pmic_i2c_addr);
+ stpmic1_bind_i2c(&i2c_handle, (uint16_t)pmic_i2c_addr);
}
void initialize_pmic(void)
@@ -214,7 +214,7 @@
initialize_pmic_i2c();
- status = stpmu1_register_read(VERSION_STATUS_REG, &read_val);
+ status = stpmic1_register_read(VERSION_STATUS_REG, &read_val);
if (status != 0) {
panic();
}
@@ -222,7 +222,7 @@
INFO("PMIC version = 0x%x\n", read_val);
/* Keep VDD on during the reset cycle */
- status = stpmu1_register_update(MASK_RESET_BUCK_REG,
+ status = stpmic1_register_update(MASK_RESET_BUCK_REG,
MASK_RESET_BUCK3,
MASK_RESET_BUCK3);
if (status != 0) {
@@ -239,45 +239,46 @@
switch (ddr_type) {
case STM32MP_DDR3:
/* Set LDO3 to sync mode */
- status = stpmu1_register_read(LDO3_CONTROL_REG, &read_val);
+ status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val);
if (status != 0) {
return status;
}
- read_val &= ~STPMU1_LDO3_MODE;
- read_val &= ~STPMU1_LDO12356_OUTPUT_MASK;
- read_val |= STPMU1_LDO3_DDR_SEL << STPMU1_LDO12356_OUTPUT_SHIFT;
+ read_val &= ~STPMIC1_LDO3_MODE;
+ read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK;
+ read_val |= STPMIC1_LDO3_DDR_SEL <<
+ STPMIC1_LDO12356_OUTPUT_SHIFT;
- status = stpmu1_register_write(LDO3_CONTROL_REG, read_val);
+ status = stpmic1_register_write(LDO3_CONTROL_REG, read_val);
if (status != 0) {
return status;
}
- status = stpmu1_regulator_voltage_set("buck2", 1350);
+ status = stpmic1_regulator_voltage_set("buck2", 1350);
if (status != 0) {
return status;
}
- status = stpmu1_regulator_enable("buck2");
+ status = stpmic1_regulator_enable("buck2");
if (status != 0) {
return status;
}
- mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
+ mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
- status = stpmu1_regulator_enable("vref_ddr");
+ status = stpmic1_regulator_enable("vref_ddr");
if (status != 0) {
return status;
}
- mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
+ mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
- status = stpmu1_regulator_enable("ldo3");
+ status = stpmic1_regulator_enable("ldo3");
if (status != 0) {
return status;
}
- mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
+ mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
break;
case STM32MP_LPDDR2:
@@ -286,57 +287,57 @@
* Set LDO3 to bypass mode if BUCK3 = 1.8V
* Set LDO3 to normal mode if BUCK3 != 1.8V
*/
- status = stpmu1_register_read(BUCK3_CONTROL_REG, &read_val);
+ status = stpmic1_register_read(BUCK3_CONTROL_REG, &read_val);
if (status != 0) {
return status;
}
- if ((read_val & STPMU1_BUCK3_1V8) == STPMU1_BUCK3_1V8) {
+ if ((read_val & STPMIC1_BUCK3_1V8) == STPMIC1_BUCK3_1V8) {
buck3_at_1v8 = true;
}
- status = stpmu1_register_read(LDO3_CONTROL_REG, &read_val);
+ status = stpmic1_register_read(LDO3_CONTROL_REG, &read_val);
if (status != 0) {
return status;
}
- read_val &= ~STPMU1_LDO3_MODE;
- read_val &= ~STPMU1_LDO12356_OUTPUT_MASK;
- read_val |= STPMU1_LDO3_1800000;
+ read_val &= ~STPMIC1_LDO3_MODE;
+ read_val &= ~STPMIC1_LDO12356_OUTPUT_MASK;
+ read_val |= STPMIC1_LDO3_1800000;
if (buck3_at_1v8) {
- read_val |= STPMU1_LDO3_MODE;
+ read_val |= STPMIC1_LDO3_MODE;
}
- status = stpmu1_register_write(LDO3_CONTROL_REG, read_val);
+ status = stpmic1_register_write(LDO3_CONTROL_REG, read_val);
if (status != 0) {
return status;
}
- status = stpmu1_regulator_voltage_set("buck2", 1200);
+ status = stpmic1_regulator_voltage_set("buck2", 1200);
if (status != 0) {
return status;
}
- status = stpmu1_regulator_enable("ldo3");
+ status = stpmic1_regulator_enable("ldo3");
if (status != 0) {
return status;
}
- mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
+ mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
- status = stpmu1_regulator_enable("buck2");
+ status = stpmic1_regulator_enable("buck2");
if (status != 0) {
return status;
}
- mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
+ mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
- status = stpmu1_regulator_enable("vref_ddr");
+ status = stpmic1_regulator_enable("vref_ddr");
if (status != 0) {
return status;
}
- mdelay(STPMU1_DEFAULT_START_UP_DELAY_MS);
+ mdelay(STPMIC1_DEFAULT_START_UP_DELAY_MS);
break;
default:
diff --git a/drivers/st/pmic/stpmic1.c b/drivers/st/pmic/stpmic1.c
new file mode 100644
index 0000000..465996d
--- /dev/null
+++ b/drivers/st/pmic/stpmic1.c
@@ -0,0 +1,762 @@
+/*
+ * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <string.h>
+
+#include <common/debug.h>
+#include <drivers/st/stpmic1.h>
+#include <plat/common/platform.h>
+
+struct regul_struct {
+ const char *dt_node_name;
+ const uint16_t *voltage_table;
+ uint8_t voltage_table_size;
+ uint8_t control_reg;
+ uint8_t low_power_reg;
+ uint8_t pull_down_reg;
+ uint8_t pull_down;
+ uint8_t mask_reset_reg;
+ uint8_t mask_reset;
+};
+
+static struct i2c_handle_s *pmic_i2c_handle;
+static uint16_t pmic_i2c_addr;
+
+/* 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,
+ 500,
+ 0xFFFF, /* VREFDDR */
+};
+
+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,
+};
+
+/* 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,
+ .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,
+ },
+ {
+ .dt_node_name = "buck2",
+ .voltage_table = buck2_voltage_table,
+ .voltage_table_size = ARRAY_SIZE(buck2_voltage_table),
+ .control_reg = BUCK2_CONTROL_REG,
+ .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,
+ },
+ {
+ .dt_node_name = "buck3",
+ .voltage_table = buck3_voltage_table,
+ .voltage_table_size = ARRAY_SIZE(buck3_voltage_table),
+ .control_reg = BUCK3_CONTROL_REG,
+ .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,
+ },
+ {
+ .dt_node_name = "buck4",
+ .voltage_table = buck4_voltage_table,
+ .voltage_table_size = ARRAY_SIZE(buck4_voltage_table),
+ .control_reg = BUCK4_CONTROL_REG,
+ .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,
+ },
+ {
+ .dt_node_name = "ldo1",
+ .voltage_table = ldo1_voltage_table,
+ .voltage_table_size = ARRAY_SIZE(ldo1_voltage_table),
+ .control_reg = LDO1_CONTROL_REG,
+ .low_power_reg = LDO1_PWRCTRL_REG,
+ .mask_reset_reg = MASK_RESET_LDO_REG,
+ .mask_reset = LDO1_MASK_RESET,
+ },
+ {
+ .dt_node_name = "ldo2",
+ .voltage_table = ldo2_voltage_table,
+ .voltage_table_size = ARRAY_SIZE(ldo2_voltage_table),
+ .control_reg = LDO2_CONTROL_REG,
+ .low_power_reg = LDO2_PWRCTRL_REG,
+ .mask_reset_reg = MASK_RESET_LDO_REG,
+ .mask_reset = LDO2_MASK_RESET,
+ },
+ {
+ .dt_node_name = "ldo3",
+ .voltage_table = ldo3_voltage_table,
+ .voltage_table_size = ARRAY_SIZE(ldo3_voltage_table),
+ .control_reg = LDO3_CONTROL_REG,
+ .low_power_reg = LDO3_PWRCTRL_REG,
+ .mask_reset_reg = MASK_RESET_LDO_REG,
+ .mask_reset = LDO3_MASK_RESET,
+ },
+ {
+ .dt_node_name = "ldo4",
+ .voltage_table = ldo4_voltage_table,
+ .voltage_table_size = ARRAY_SIZE(ldo4_voltage_table),
+ .control_reg = LDO4_CONTROL_REG,
+ .low_power_reg = LDO4_PWRCTRL_REG,
+ .mask_reset_reg = MASK_RESET_LDO_REG,
+ .mask_reset = LDO4_MASK_RESET,
+ },
+ {
+ .dt_node_name = "ldo5",
+ .voltage_table = ldo5_voltage_table,
+ .voltage_table_size = ARRAY_SIZE(ldo5_voltage_table),
+ .control_reg = LDO5_CONTROL_REG,
+ .low_power_reg = LDO5_PWRCTRL_REG,
+ .mask_reset_reg = MASK_RESET_LDO_REG,
+ .mask_reset = LDO5_MASK_RESET,
+ },
+ {
+ .dt_node_name = "ldo6",
+ .voltage_table = ldo6_voltage_table,
+ .voltage_table_size = ARRAY_SIZE(ldo6_voltage_table),
+ .control_reg = LDO6_CONTROL_REG,
+ .low_power_reg = LDO6_PWRCTRL_REG,
+ .mask_reset_reg = MASK_RESET_LDO_REG,
+ .mask_reset = LDO6_MASK_RESET,
+ },
+ {
+ .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,
+ .low_power_reg = VREF_DDR_PWRCTRL_REG,
+ .mask_reset_reg = MASK_RESET_LDO_REG,
+ .mask_reset = VREF_DDR_MASK_RESET,
+ },
+};
+
+#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, BIT(0), BIT(0));
+}
+
+int stpmic1_regulator_disable(const char *name)
+{
+ const struct regul_struct *regul = get_regulator_data(name);
+
+ return stpmic1_register_update(regul->control_reg, 0, BIT(0));
+}
+
+uint8_t 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 & 0x1U);
+}
+
+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;
+
+ /* Voltage can be set for buck<N> or ldo<N> (except ldo4) regulators */
+ if (strncmp(name, "buck", 4) == 0) {
+ mask = BUCK_VOLTAGE_MASK;
+ } else if ((strncmp(name, "ldo", 3) == 0) &&
+ (strncmp(name, "ldo4", 4) != 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);
+
+ return stpmic1_register_update(regul->mask_reset_reg,
+ BIT(regul->mask_reset),
+ LDO_BUCK_RESET_MASK <<
+ regul->mask_reset);
+}
+
+int stpmic1_regulator_voltage_get(const char *name)
+{
+ const struct regul_struct *regul = get_regulator_data(name);
+ uint8_t value;
+ uint8_t mask;
+
+ /* Voltage can be set for buck<N> or ldo<N> (except ldo4) regulators */
+ if (strncmp(name, "buck", 4) == 0) {
+ mask = BUCK_VOLTAGE_MASK;
+ } else if ((strncmp(name, "ldo", 3) == 0) &&
+ (strncmp(name, "ldo4", 4) != 0)) {
+ mask = LDO_VOLTAGE_MASK;
+ } else {
+ return 0;
+ }
+
+ if (stpmic1_register_read(regul->control_reg, &value))
+ return -1;
+
+ value = (value & mask) >> LDO_BUCK_VOLTAGE_SHIFT;
+
+ if (value > regul->voltage_table_size)
+ return -1;
+
+ 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, 100000);
+}
+
+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, 100000);
+
+#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 -1;
+ }
+ }
+#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)
+{
+ int rc;
+ uint8_t read_val;
+
+ rc = stpmic1_register_read(VERSION_STATUS_REG, &read_val);
+ if (rc) {
+ return -1;
+ }
+
+ *version = (unsigned long)read_val;
+
+ return 0;
+}
diff --git a/drivers/st/pmic/stpmu1.c b/drivers/st/pmic/stpmu1.c
deleted file mode 100644
index 9c36bf6..0000000
--- a/drivers/st/pmic/stpmu1.c
+++ /dev/null
@@ -1,601 +0,0 @@
-/*
- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
-
-#include <string.h>
-
-#include <common/debug.h>
-#include <drivers/st/stpmu1.h>
-#include <plat/common/platform.h>
-
-struct regul_struct {
- const char *dt_node_name;
- const uint16_t *voltage_table;
- uint8_t voltage_table_size;
- uint8_t control_reg;
- uint8_t low_power_reg;
-};
-
-static struct i2c_handle_s *stpmu_i2c_handle;
-static uint16_t stpmu_i2c_addr;
-
-/* Voltage tables in mV */
-static const uint16_t buck1_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,
- 1325,
- 1350,
- 1350,
-};
-
-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,
- 0xFFFF, /* VREFDDR */
-};
-
-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,
-};
-
-/* 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,
- .low_power_reg = BUCK1_PWRCTRL_REG,
- },
- {
- .dt_node_name = "buck2",
- .voltage_table = buck2_voltage_table,
- .voltage_table_size = ARRAY_SIZE(buck2_voltage_table),
- .control_reg = BUCK2_CONTROL_REG,
- .low_power_reg = BUCK2_PWRCTRL_REG,
- },
- {
- .dt_node_name = "buck3",
- .voltage_table = buck3_voltage_table,
- .voltage_table_size = ARRAY_SIZE(buck3_voltage_table),
- .control_reg = BUCK3_CONTROL_REG,
- .low_power_reg = BUCK3_PWRCTRL_REG,
- },
- {
- .dt_node_name = "buck4",
- .voltage_table = buck4_voltage_table,
- .voltage_table_size = ARRAY_SIZE(buck4_voltage_table),
- .control_reg = BUCK4_CONTROL_REG,
- .low_power_reg = BUCK4_PWRCTRL_REG,
- },
- {
- .dt_node_name = "ldo1",
- .voltage_table = ldo1_voltage_table,
- .voltage_table_size = ARRAY_SIZE(ldo1_voltage_table),
- .control_reg = LDO1_CONTROL_REG,
- .low_power_reg = LDO1_PWRCTRL_REG,
- },
- {
- .dt_node_name = "ldo2",
- .voltage_table = ldo2_voltage_table,
- .voltage_table_size = ARRAY_SIZE(ldo2_voltage_table),
- .control_reg = LDO2_CONTROL_REG,
- .low_power_reg = LDO2_PWRCTRL_REG,
- },
- {
- .dt_node_name = "ldo3",
- .voltage_table = ldo3_voltage_table,
- .voltage_table_size = ARRAY_SIZE(ldo3_voltage_table),
- .control_reg = LDO3_CONTROL_REG,
- .low_power_reg = LDO3_PWRCTRL_REG,
- },
- {
- .dt_node_name = "ldo4",
- .voltage_table = ldo4_voltage_table,
- .voltage_table_size = ARRAY_SIZE(ldo4_voltage_table),
- .control_reg = LDO4_CONTROL_REG,
- .low_power_reg = LDO4_PWRCTRL_REG,
- },
- {
- .dt_node_name = "ldo5",
- .voltage_table = ldo5_voltage_table,
- .voltage_table_size = ARRAY_SIZE(ldo5_voltage_table),
- .control_reg = LDO5_CONTROL_REG,
- .low_power_reg = LDO5_PWRCTRL_REG,
- },
- {
- .dt_node_name = "ldo6",
- .voltage_table = ldo6_voltage_table,
- .voltage_table_size = ARRAY_SIZE(ldo6_voltage_table),
- .control_reg = LDO6_CONTROL_REG,
- .low_power_reg = LDO6_PWRCTRL_REG,
- },
- {
- .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,
- .low_power_reg = VREF_DDR_PWRCTRL_REG,
- },
-};
-
-#define MAX_REGUL ARRAY_SIZE(regulators_table)
-
-static const struct regul_struct *stpmu1_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 stpmu1_voltage_find_index(const char *name,
- uint16_t millivolts)
-{
- const struct regul_struct *regul = stpmu1_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 stpmu1_switch_off(void)
-{
- return stpmu1_register_update(MAIN_CONTROL_REG, 1,
- SOFTWARE_SWITCH_OFF_ENABLED);
-}
-
-int stpmu1_regulator_enable(const char *name)
-{
- const struct regul_struct *regul = stpmu1_get_regulator_data(name);
-
- return stpmu1_register_update(regul->control_reg, BIT(0), BIT(0));
-}
-
-int stpmu1_regulator_disable(const char *name)
-{
- const struct regul_struct *regul = stpmu1_get_regulator_data(name);
-
- return stpmu1_register_update(regul->control_reg, 0, BIT(0));
-}
-
-uint8_t stpmu1_is_regulator_enabled(const char *name)
-{
- uint8_t val;
- const struct regul_struct *regul = stpmu1_get_regulator_data(name);
-
- if (stpmu1_register_read(regul->control_reg, &val) != 0) {
- panic();
- }
-
- return (val & 0x1U);
-}
-
-int stpmu1_regulator_voltage_set(const char *name, uint16_t millivolts)
-{
- uint8_t voltage_index = stpmu1_voltage_find_index(name, millivolts);
- const struct regul_struct *regul = stpmu1_get_regulator_data(name);
-
- return stpmu1_register_update(regul->control_reg, voltage_index << 2,
- 0xFC);
-}
-
-int stpmu1_register_read(uint8_t register_id, uint8_t *value)
-{
- return stm32_i2c_mem_read(stpmu_i2c_handle, stpmu_i2c_addr,
- (uint16_t)register_id, I2C_MEMADD_SIZE_8BIT,
- value, 1, 100000);
-}
-
-int stpmu1_register_write(uint8_t register_id, uint8_t value)
-{
- int status;
-
- status = stm32_i2c_mem_write(stpmu_i2c_handle, stpmu_i2c_addr,
- (uint16_t)register_id,
- I2C_MEMADD_SIZE_8BIT, &value, 1, 100000);
-
- if (status != 0) {
- return status;
- }
-
- if ((register_id != WATCHDOG_CONTROL_REG) && (register_id <= 0x40U)) {
- uint8_t readval;
-
- status = stpmu1_register_read(register_id, &readval);
- if (status != 0) {
- return status;
- }
-
- if (readval != value) {
- return -1;
- }
- }
-
- return 0;
-}
-
-int stpmu1_register_update(uint8_t register_id, uint8_t value, uint8_t mask)
-{
- int status;
- uint8_t val;
-
- status = stpmu1_register_read(register_id, &val);
- if (status != 0) {
- return status;
- }
-
- /* Clear bits to update */
- val &= ~mask;
-
- /* Update appropriate bits*/
- val |= (value & mask);
-
- /* Send new value on I2C Bus */
- return stpmu1_register_write(register_id, val);
-}
-
-void stpmu1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr)
-{
- stpmu_i2c_handle = i2c_handle;
- stpmu_i2c_addr = i2c_addr;
-}
diff --git a/fdts/stm32mp15-ddr.dtsi b/fdts/stm32mp15-ddr.dtsi
index be4e2c3..1a5c51c 100644
--- a/fdts/stm32mp15-ddr.dtsi
+++ b/fdts/stm32mp15-ddr.dtsi
@@ -5,7 +5,7 @@
/ {
soc {
- ddr: ddr@0x5A003000{
+ ddr: ddr@5A003000{
compatible = "st,stm32mp1-ddr";
diff --git a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi
index 58a4cdc..82e7104 100644
--- a/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi
+++ b/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi
@@ -3,7 +3,7 @@
* Copyright (C) 2018, STMicroelectronics - All Rights Reserved
*/
-/* STM32MP157C ED1 and ED2 BOARD configuration
+/* STM32MP157C ED1 BOARD configuration
* 2x DDR3L 4Gb each, 16-bit, 533MHz, Single Die Package in flyby topology.
* Reference used NT5CC256M16DP-DI from NANYA
*
@@ -15,10 +15,11 @@
* timing mode optimized
* Scheduling/QoS options : type = 2
* address mapping : RBC
+ * Tc > + 85C : N
*/
-#define DDR_MEM_NAME "DDR3-1066 bin G 2x4Gb 533MHz v1.39"
-#define DDR_MEM_SPEED 533
+#define DDR_MEM_NAME "DDR3-1066/888 bin G 2x4Gb 533MHz v1.41"
+#define DDR_MEM_SPEED 533000
#define DDR_MEM_SIZE 0x40000000
#define DDR_MSTR 0x00040401
@@ -62,7 +63,7 @@
#define DDR_ADDRMAP11 0x00000000
#define DDR_ODTCFG 0x06000600
#define DDR_ODTMAP 0x00000001
-#define DDR_SCHED 0x00001201
+#define DDR_SCHED 0x00000C01
#define DDR_SCHED1 0x00000000
#define DDR_PERFHPR1 0x01000001
#define DDR_PERFLPR1 0x08000200
@@ -74,15 +75,15 @@
#define DDR_PCCFG 0x00000010
#define DDR_PCFGR_0 0x00010000
#define DDR_PCFGW_0 0x00000000
-#define DDR_PCFGQOS0_0 0x02100B03
+#define DDR_PCFGQOS0_0 0x02100C03
#define DDR_PCFGQOS1_0 0x00800100
-#define DDR_PCFGWQOS0_0 0x01100B03
+#define DDR_PCFGWQOS0_0 0x01100C03
#define DDR_PCFGWQOS1_0 0x01000200
#define DDR_PCFGR_1 0x00010000
#define DDR_PCFGW_1 0x00000000
-#define DDR_PCFGQOS0_1 0x02100B03
-#define DDR_PCFGQOS1_1 0x00800000
-#define DDR_PCFGWQOS0_1 0x01100B03
+#define DDR_PCFGQOS0_1 0x02100C03
+#define DDR_PCFGQOS1_1 0x00800040
+#define DDR_PCFGWQOS0_1 0x01100C03
#define DDR_PCFGWQOS1_1 0x01000200
#define DDR_PGCR 0x01442E02
#define DDR_PTR0 0x0022AA5B
diff --git a/fdts/stm32mp157-pinctrl.dtsi b/fdts/stm32mp157-pinctrl.dtsi
index 21bd34e..9dcd7b5 100644
--- a/fdts/stm32mp157-pinctrl.dtsi
+++ b/fdts/stm32mp157-pinctrl.dtsi
@@ -3,13 +3,14 @@
* Copyright (C) STMicroelectronics 2017 - All Rights Reserved
* Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
*/
-
#include <dt-bindings/pinctrl/stm32-pinfunc.h>
+
/ {
soc {
- pinctrl: pin-controller {
+ pinctrl: pin-controller@50002000 {
#address-cells = <1>;
#size-cells = <1>;
+ compatible = "st,stm32mp157-pinctrl";
ranges = <0 0x50002000 0xa400>;
pins-are-numbered;
@@ -134,54 +135,76 @@
status = "disabled";
};
- uart4_pins_a: uart4@0 {
+ qspi_bk1_pins_a: qspi-bk1-0 {
pins1 {
- pinmux = <STM32_PINMUX('G', 11, AF6)>; /* UART4_TX */
+ pinmux = <STM32_PINMUX('F', 8, AF10)>, /* QSPI_BK1_IO0 */
+ <STM32_PINMUX('F', 9, AF10)>, /* QSPI_BK1_IO1 */
+ <STM32_PINMUX('F', 7, AF9)>, /* QSPI_BK1_IO2 */
+ <STM32_PINMUX('F', 6, AF9)>; /* QSPI_BK1_IO3 */
bias-disable;
drive-push-pull;
- slew-rate = <0>;
+ slew-rate = <1>;
};
pins2 {
- pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
- bias-disable;
+ pinmux = <STM32_PINMUX('B', 6, AF10)>; /* QSPI_BK1_NCS */
+ bias-pull-up;
+ drive-push-pull;
+ slew-rate = <1>;
};
};
- usart3_pins_a: usart3@0 {
+ qspi_bk2_pins_a: qspi-bk2-0 {
pins1 {
- pinmux = <STM32_PINMUX('B', 10, AF7)>, /* USART3_TX */
- <STM32_PINMUX('G', 8, AF8)>; /* USART3_RTS */
+ pinmux = <STM32_PINMUX('H', 2, AF9)>, /* QSPI_BK2_IO0 */
+ <STM32_PINMUX('H', 3, AF9)>, /* QSPI_BK2_IO1 */
+ <STM32_PINMUX('G', 10, AF11)>, /* QSPI_BK2_IO2 */
+ <STM32_PINMUX('G', 7, AF11)>; /* QSPI_BK2_IO3 */
bias-disable;
drive-push-pull;
- slew-rate = <0>;
+ slew-rate = <1>;
};
pins2 {
- pinmux = <STM32_PINMUX('B', 12, AF8)>, /* USART3_RX */
- <STM32_PINMUX('I', 10, AF8)>; /* USART3_CTS_NSS */
- bias-disable;
+ pinmux = <STM32_PINMUX('C', 0, AF10)>; /* QSPI_BK2_NCS */
+ bias-pull-up;
+ drive-push-pull;
+ slew-rate = <1>;
};
};
- sdmmc1_b4_pins_a: sdmmc1-b4@0 {
+ qspi_clk_pins_a: qspi-clk-0 {
pins {
+ pinmux = <STM32_PINMUX('F', 10, AF9)>; /* QSPI_CLK */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <3>;
+ };
+ };
+
+ sdmmc1_b4_pins_a: sdmmc1-b4-0 {
+ pins1 {
pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */
<STM32_PINMUX('C', 9, AF12)>, /* SDMMC1_D1 */
<STM32_PINMUX('C', 10, AF12)>, /* SDMMC1_D2 */
<STM32_PINMUX('C', 11, AF12)>, /* SDMMC1_D3 */
- <STM32_PINMUX('C', 12, AF12)>, /* SDMMC1_CK */
<STM32_PINMUX('D', 2, AF12)>; /* SDMMC1_CMD */
- slew-rate = <3>;
+ slew-rate = <1>;
drive-push-pull;
bias-disable;
};
+ pins2 {
+ pinmux = <STM32_PINMUX('C', 12, AF12)>; /* SDMMC1_CK */
+ slew-rate = <2>;
+ drive-push-pull;
+ bias-disable;
+ };
};
- sdmmc1_dir_pins_a: sdmmc1-dir@0 {
+ sdmmc1_dir_pins_a: sdmmc1-dir-0 {
pins1 {
pinmux = <STM32_PINMUX('F', 2, AF11)>, /* SDMMC1_D0DIR */
<STM32_PINMUX('C', 7, AF8)>, /* SDMMC1_D123DIR */
<STM32_PINMUX('B', 9, AF11)>; /* SDMMC1_CDIR */
- slew-rate = <3>;
+ slew-rate = <1>;
drive-push-pull;
bias-pull-up;
};
@@ -191,36 +214,85 @@
};
};
- sdmmc2_b4_pins_a: sdmmc2-b4@0 {
- pins {
+ sdmmc1_dir_pins_b: sdmmc1-dir-1 {
+ pins1 {
+ pinmux = <STM32_PINMUX('E', 12, AF8)>, /* SDMMC1_D0DIR */
+ <STM32_PINMUX('E', 14, AF11)>, /* SDMMC1_D123DIR */
+ <STM32_PINMUX('B', 9, AF11)>; /* SDMMC1_CDIR */
+ slew-rate = <3>;
+ drive-push-pull;
+ bias-pull-up;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('E', 4, AF8)>; /* SDMMC1_CKIN */
+ bias-pull-up;
+ };
+ };
+
+ sdmmc2_b4_pins_a: sdmmc2-b4-0 {
+ pins1 {
pinmux = <STM32_PINMUX('B', 14, AF9)>, /* SDMMC2_D0 */
<STM32_PINMUX('B', 15, AF9)>, /* SDMMC2_D1 */
<STM32_PINMUX('B', 3, AF9)>, /* SDMMC2_D2 */
<STM32_PINMUX('B', 4, AF9)>, /* SDMMC2_D3 */
- <STM32_PINMUX('E', 3, AF9)>, /* SDMMC2_CK */
<STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */
- slew-rate = <3>;
+ slew-rate = <1>;
+ drive-push-pull;
+ bias-pull-up;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('E', 3, AF9)>; /* SDMMC2_CK */
+ slew-rate = <2>;
drive-push-pull;
bias-pull-up;
};
};
- sdmmc2_d47_pins_a: sdmmc2-d47@0 {
+ sdmmc2_d47_pins_a: sdmmc2-d47-0 {
pins {
pinmux = <STM32_PINMUX('A', 8, AF9)>, /* SDMMC2_D4 */
<STM32_PINMUX('A', 9, AF10)>, /* SDMMC2_D5 */
<STM32_PINMUX('E', 5, AF9)>, /* SDMMC2_D6 */
<STM32_PINMUX('D', 3, AF9)>; /* SDMMC2_D7 */
- slew-rate = <3>;
+ slew-rate = <1>;
drive-push-pull;
bias-pull-up;
};
};
+
+ uart4_pins_a: uart4-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('G', 11, AF6)>; /* UART4_TX */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <0>;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('B', 2, AF8)>; /* UART4_RX */
+ bias-disable;
+ };
+ };
+
+ usart3_pins_a: usart3-0 {
+ pins1 {
+ pinmux = <STM32_PINMUX('B', 10, AF7)>, /* USART3_TX */
+ <STM32_PINMUX('G', 8, AF8)>; /* USART3_RTS */
+ bias-disable;
+ drive-push-pull;
+ slew-rate = <0>;
+ };
+ pins2 {
+ pinmux = <STM32_PINMUX('B', 12, AF8)>, /* USART3_RX */
+ <STM32_PINMUX('I', 10, AF8)>; /* USART3_CTS_NSS */
+ bias-disable;
+ };
+ };
};
- pinctrl_z: pin-controller-z {
+ pinctrl_z: pin-controller-z@54004000 {
#address-cells = <1>;
#size-cells = <1>;
+ compatible = "st,stm32mp157-z-pinctrl";
ranges = <0 0x54004000 0x400>;
pins-are-numbered;
@@ -236,7 +308,7 @@
status = "disabled";
};
- i2c4_pins_a: i2c4@0 {
+ i2c4_pins_a: i2c4-0 {
pins {
pinmux = <STM32_PINMUX('Z', 4, AF6)>, /* I2C4_SCL */
<STM32_PINMUX('Z', 5, AF6)>; /* I2C4_SDA */
diff --git a/fdts/stm32mp157c-ed1.dts b/fdts/stm32mp157c-ed1.dts
index e3dabe8..a97e805 100644
--- a/fdts/stm32mp157c-ed1.dts
+++ b/fdts/stm32mp157c-ed1.dts
@@ -3,20 +3,26 @@
* Copyright (C) STMicroelectronics 2017 - All Rights Reserved
* Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
*/
-
/dts-v1/;
#include "stm32mp157c.dtsi"
#include "stm32mp157caa-pinctrl.dtsi"
/ {
- model = "STMicroelectronics STM32MP157C-ED1 pmic eval daughter";
+ model = "STMicroelectronics STM32MP157C eval daughter";
compatible = "st,stm32mp157c-ed1", "st,stm32mp157";
chosen {
- bootargs = "earlyprintk console=ttyS3,115200 root=/dev/ram";
- stdout-path = "serial3:115200n8";
+ stdout-path = "serial0:115200n8";
};
+
+ aliases {
+ serial0 = &uart4;
+ };
+};
+
+&clk_hse {
+ st,digbypass;
};
&i2c4 {
@@ -26,62 +32,113 @@
i2c-scl-falling-time-ns = <20>;
status = "okay";
- pmic: stpmu1@33 {
- compatible = "st,stpmu1";
+ 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>;
+ st,main-control-register = <0x04>;
+ st,vin-control-register = <0xc0>;
+ st,usb-control-register = <0x30>;
regulators {
- compatible = "st,stpmu1-regulators";
+ compatible = "st,stpmic1-regulators";
+
+ ldo1-supply = <&v3v3>;
+ ldo2-supply = <&v3v3>;
+ ldo3-supply = <&vdd_ddr>;
+ ldo5-supply = <&v3v3>;
+ ldo6-supply = <&v3v3>;
+
+ vddcore: buck1 {
+ regulator-name = "vddcore";
+ regulator-min-microvolt = <800000>;
+ 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-boot-on;
+ regulator-always-on;
regulator-over-current-protection;
- regulator-initial-mode = <8>;
+ regulator-initial-mode = <0>;
+ };
+
+ vdda: ldo1 {
+ regulator-name = "vdda";
+ regulator-min-microvolt = <2900000>;
+ regulator-max-microvolt = <2900000>;
+ };
- regulator-state-standby {
- regulator-suspend-microvolt = <3300000>;
- regulator-unchanged-in-suspend;
- regulator-mode = <8>;
- };
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- regulator-state-disk {
- regulator-off-in-suspend;
- };
+ 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;
+ };
- regulator-state-standby {
- regulator-suspend-microvolt = <2900000>;
- regulator-unchanged-in-suspend;
- };
- regulator-state-mem {
- regulator-off-in-suspend;
- };
- regulator-state-disk {
- regulator-off-in-suspend;
- };
+ 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;
};
};
};
};
&iwdg2 {
- instance = <2>;
timeout-sec = <32>;
status = "okay";
};
@@ -90,14 +147,19 @@
status = "okay";
};
+&rtc {
+ status = "okay";
+};
+
&sdmmc1 {
pinctrl-names = "default";
pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>;
broken-cd;
- st,dirpol;
- st,negedge;
- st,pin-ckin;
+ 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;
@@ -112,16 +174,17 @@
non-removable;
no-sd;
no-sdio;
- st,dirpol;
- st,negedge;
+ st,neg-edge;
bus-width = <8>;
+ vmmc-supply = <&v3v3>;
+ vqmmc-supply = <&v3v3>;
+ mmc-ddr-3_3v;
status = "okay";
};
&uart4 {
pinctrl-names = "default";
pinctrl-0 = <&uart4_pins_a>;
- resets = <&rcc UART4_R>;
status = "okay";
};
@@ -157,6 +220,7 @@
/* CLOCK init */
&rcc {
+ secure-status = "disabled";
st,clksrc = <
CLK_MPU_PLL1P
CLK_AXI_PLL2P
@@ -186,7 +250,7 @@
CLK_FMC_ACLK
CLK_QSPI_ACLK
CLK_ETH_DISABLED
- CLK_SDMMC12_PLL3R
+ CLK_SDMMC12_PLL4P
CLK_DSI_DSIPLL
CLK_STGEN_HSE
CLK_USBPHY_HSE
@@ -195,7 +259,7 @@
CLK_SPI45_HSI
CLK_SPI6_HSI
CLK_I2C46_HSI
- CLK_SDMMC3_PLL3R
+ CLK_SDMMC3_PLL4P
CLK_USBO_USBPHY
CLK_ADC_CKPER
CLK_CEC_LSE
@@ -206,17 +270,17 @@
CLK_UART35_HSI
CLK_UART6_HSI
CLK_UART78_HSI
- CLK_SPDIF_PLL3Q
+ CLK_SPDIF_PLL4P
CLK_FDCAN_PLL4Q
CLK_SAI1_PLL3Q
CLK_SAI2_PLL3Q
CLK_SAI3_PLL3Q
CLK_SAI4_PLL3Q
- CLK_RNG1_CSI
- CLK_RNG2_CSI
+ CLK_RNG1_LSI
+ CLK_RNG2_LSI
CLK_LPTIM1_PCLK1
CLK_LPTIM23_PCLK3
- CLK_LPTIM45_PCLK3
+ CLK_LPTIM45_LSE
>;
/* VCO = 1300.0 MHz => P = 650 (CPU) */
@@ -231,15 +295,15 @@
frac = < 0x1400 >;
};
- /* VCO = 786.4 MHz => P = 197, Q = 49, R = 98 */
+ /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */
pll3: st,pll@2 {
- cfg = < 2 97 3 15 7 PQR(1,1,1) >;
- frac = < 0x9ba >;
+ cfg = < 1 33 1 16 36 PQR(1,1,1) >;
+ frac = < 0x1a04 >;
};
- /* VCO = 508.0 MHz => P = 56, Q = 56, R = 56 */
+ /* VCO = 594.0 MHz => P = 99, Q = 74, R = 74 */
pll4: st,pll@3 {
- cfg = < 5 126 8 8 8 PQR(1,1,1) >;
+ cfg = < 3 98 5 7 7 PQR(1,1,1) >;
};
};
diff --git a/fdts/stm32mp157c-ev1.dts b/fdts/stm32mp157c-ev1.dts
index 98a9d35..cfde8ed 100644
--- a/fdts/stm32mp157c-ev1.dts
+++ b/fdts/stm32mp157c-ev1.dts
@@ -3,23 +3,65 @@
* Copyright (C) STMicroelectronics 2017 - All Rights Reserved
* Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
*/
-
/dts-v1/;
+
#include "stm32mp157c-ed1.dts"
/ {
- model = "STMicroelectronics STM32MP157C-EV1 pmic eval daughter on eval mother";
+ model = "STMicroelectronics STM32MP157C eval daughter on eval mother";
compatible = "st,stm32mp157c-ev1", "st,stm32mp157c-ed1", "st,stm32mp157";
chosen {
- bootargs = "earlyprintk console=ttyS3,115200 root=/dev/ram";
- stdout-path = "serial3:115200n8";
+ stdout-path = "serial0:115200n8";
+ };
+
+ aliases {
+ serial1 = &usart3;
+ };
+};
+
+&fmc {
+ status = "okay";
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ nand: 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 &qspi_bk2_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>;
+ };
+
+ flash1: mx66l51235l@1 {
+ compatible = "jedec,spi-nor";
+ reg = <1>;
+ spi-rx-bus-width = <4>;
+ spi-max-frequency = <108000000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ };
+};
+
&usart3 {
pinctrl-names = "default";
pinctrl-0 = <&usart3_pins_a>;
- resets = <&rcc USART3_R>;
status = "disabled";
};
diff --git a/fdts/stm32mp157c.dtsi b/fdts/stm32mp157c.dtsi
index 8b13c0e..0ec7ecb 100644
--- a/fdts/stm32mp157c.dtsi
+++ b/fdts/stm32mp157c.dtsi
@@ -3,7 +3,7 @@
* Copyright (C) STMicroelectronics 2017 - All Rights Reserved
* Author: Ludovic Barre <ludovic.barre@st.com> for STMicroelectronics.
*/
-
+#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
#include <dt-bindings/reset/stm32mp1-resets.h>
@@ -11,15 +11,12 @@
#address-cells = <1>;
#size-cells = <1>;
- aliases {
- serial0 = &usart1;
- serial1 = &usart2;
- serial2 = &usart3;
- serial3 = &uart4;
- serial4 = &uart5;
- serial5 = &usart6;
- serial6 = &uart7;
- serial7 = &uart8;
+ intc: interrupt-controller@a0021000 {
+ compatible = "arm,cortex-a7-gic";
+ #interrupt-cells = <3>;
+ interrupt-controller;
+ reg = <0xa0021000 0x1000>,
+ <0xa0022000 0x2000>;
};
clocks {
@@ -56,7 +53,7 @@
clk_i2s_ckin: i2s_ckin {
#clock-cells = <0>;
compatible = "fixed-clock";
- clock-frequency = <64000000>;
+ clock-frequency = <0>;
};
clk_dsi_phy: ck_dsi_phy {
@@ -64,31 +61,28 @@
compatible = "fixed-clock";
clock-frequency = <0>;
};
-
- clk_usbo_48m: ck_usbo_48m {
- #clock-cells = <0>;
- compatible = "fixed-clock";
- clock-frequency = <48000000>;
- };
};
soc {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
+ interrupt-parent = <&intc>;
ranges;
usart2: serial@4000e000 {
- compatible = "st,stm32h7-usart";
+ compatible = "st,stm32h7-uart";
reg = <0x4000e000 0x400>;
clocks = <&rcc USART2_K>;
+ resets = <&rcc USART2_R>;
status = "disabled";
};
usart3: serial@4000f000 {
- compatible = "st,stm32h7-usart";
+ compatible = "st,stm32h7-uart";
reg = <0x4000f000 0x400>;
clocks = <&rcc USART3_K>;
+ resets = <&rcc USART3_R>;
status = "disabled";
};
@@ -96,6 +90,7 @@
compatible = "st,stm32h7-uart";
reg = <0x40010000 0x400>;
clocks = <&rcc UART4_K>;
+ resets = <&rcc UART4_R>;
status = "disabled";
};
@@ -103,6 +98,7 @@
compatible = "st,stm32h7-uart";
reg = <0x40011000 0x400>;
clocks = <&rcc UART5_K>;
+ resets = <&rcc UART5_R>;
status = "disabled";
};
@@ -111,6 +107,7 @@
compatible = "st,stm32h7-uart";
reg = <0x40018000 0x400>;
clocks = <&rcc UART7_K>;
+ resets = <&rcc UART7_R>;
status = "disabled";
};
@@ -118,21 +115,23 @@
compatible = "st,stm32h7-uart";
reg = <0x40019000 0x400>;
clocks = <&rcc UART8_K>;
+ resets = <&rcc UART8_R>;
status = "disabled";
};
usart6: serial@44003000 {
- compatible = "st,stm32h7-usart";
+ compatible = "st,stm32h7-uart";
reg = <0x44003000 0x400>;
clocks = <&rcc USART6_K>;
+ resets = <&rcc USART6_R>;
status = "disabled";
};
sdmmc3: sdmmc@48004000 {
compatible = "st,stm32-sdmmc2";
reg = <0x48004000 0x400>, <0x48005000 0x400>;
- reg-names = "sdmmc", "delay";
clocks = <&rcc SDMMC3_K>;
+ clock-names = "apb_pclk";
resets = <&rcc SDMMC3_R>;
cap-sd-highspeed;
cap-mmc-highspeed;
@@ -141,19 +140,36 @@
};
rcc: rcc@50000000 {
- compatible = "syscon", "st,stm32mp1-rcc";
+ compatible = "st,stm32mp1-rcc", "syscon";
+ reg = <0x50000000 0x1000>;
#clock-cells = <1>;
#reset-cells = <1>;
- reg = <0x50000000 0x1000>;
+ interrupts = <GIC_SPI 5 IRQ_TYPE_LEVEL_HIGH>;
};
- rcc_reboot: rcc-reboot@50000000 {
- compatible = "syscon-reboot";
- regmap = <&rcc>;
- offset = <0x404>;
- mask = <0x1>;
+ pwr: pwr@50001000 {
+ compatible = "st,stm32mp1-pwr", "syscon", "simple-mfd";
+ reg = <0x50001000 0x400>;
};
+ 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>;
+ st,irq-number = <6>;
+ };
+ };
+
rng1: rng@54003000 {
compatible = "st,stm32-rng";
reg = <0x54003000 0x400>;
@@ -162,13 +178,15 @@
status = "disabled";
};
- fmc_nand: fmc_nand@58002000 {
- compatible = "st,stm32mp1-fmc";
+ fmc: nand-controller@58002000 {
+ compatible = "st,stm32mp15-fmc2";
reg = <0x58002000 0x1000>,
- <0x80000000 0x40000>,
- <0x81000000 0x40000>,
- <0x88000000 0x40000>,
- <0x89000000 0x40000>;
+ <0x80000000 0x1000>,
+ <0x88010000 0x1000>,
+ <0x88020000 0x1000>,
+ <0x81000000 0x1000>,
+ <0x89010000 0x1000>,
+ <0x89020000 0x1000>;
clocks = <&rcc FMC_K>;
resets = <&rcc FMC_R>;
status = "disabled";
@@ -177,15 +195,17 @@
qspi: qspi@58003000 {
compatible = "st,stm32f469-qspi";
reg = <0x58003000 0x1000>, <0x70000000 0x10000000>;
+ reg-names = "qspi", "qspi_mm";
clocks = <&rcc QSPI_K>;
+ resets = <&rcc QSPI_R>;
status = "disabled";
};
sdmmc1: sdmmc@58005000 {
compatible = "st,stm32-sdmmc2";
reg = <0x58005000 0x1000>, <0x58006000 0x1000>;
- reg-names = "sdmmc", "delay";
clocks = <&rcc SDMMC1_K>;
+ clock-names = "apb_pclk";
resets = <&rcc SDMMC1_R>;
cap-sd-highspeed;
cap-mmc-highspeed;
@@ -196,8 +216,8 @@
sdmmc2: sdmmc@58007000 {
compatible = "st,stm32-sdmmc2";
reg = <0x58007000 0x1000>, <0x58008000 0x1000>;
- reg-names = "sdmmc", "delay";
clocks = <&rcc SDMMC2_K>;
+ clock-names = "apb_pclk";
resets = <&rcc SDMMC2_R>;
cap-sd-highspeed;
cap-mmc-highspeed;
@@ -205,7 +225,7 @@
status = "disabled";
};
- iwdg2: iwdg@5a002000 {
+ iwdg2: watchdog@5a002000 {
compatible = "st,stm32mp1-iwdg";
reg = <0x5a002000 0x400>;
clocks = <&rcc IWDG2>, <&rcc CK_LSI>;
@@ -214,15 +234,34 @@
};
usart1: serial@5c000000 {
- compatible = "st,stm32h7-usart";
+ compatible = "st,stm32h7-uart";
reg = <0x5c000000 0x400>;
+ interrupt-names = "event", "wakeup";
+ interrupts-extended = <&intc GIC_SPI 37 IRQ_TYPE_LEVEL_HIGH>,
+ <&exti 26 1>;
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 = <GIC_SPI 86 IRQ_TYPE_LEVEL_HIGH>;
+ clocks = <&rcc SPI6_K>;
+ resets = <&rcc SPI6_R>;
+ status = "disabled";
+ };
+
i2c4: i2c@5c002000 {
compatible = "st,stm32f7-i2c";
reg = <0x5c002000 0x400>;
+ interrupt-names = "event", "error", "wakeup";
+ interrupts-extended = <&intc GIC_SPI 95 IRQ_TYPE_LEVEL_HIGH>,
+ <&intc GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>,
+ <&exti 24 1>;
clocks = <&rcc I2C4_K>;
resets = <&rcc I2C4_R>;
#address-cells = <1>;
@@ -235,6 +274,36 @@
reg = <0x5c004000 0x400>;
clocks = <&rcc RTCAPB>, <&rcc RTC>;
clock-names = "pclk", "rtc_ck";
+ interrupts-extended = <&intc GIC_SPI 3 IRQ_TYPE_LEVEL_HIGH>,
+ <&exti 19 1>;
+ status = "disabled";
+ };
+
+ bsec: nvmem@5c005000 {
+ compatible = "st,stm32mp15-bsec";
+ reg = <0x5c005000 0x400>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ts_cal1: calib@5c {
+ reg = <0x5c 0x2>;
+ };
+ ts_cal2: calib@5e {
+ reg = <0x5e 0x2>;
+ };
+ };
+
+ i2c6: i2c@5c009000 {
+ compatible = "st,stm32f7-i2c";
+ reg = <0x5c009000 0x400>;
+ interrupt-names = "event", "error", "wakeup";
+ interrupts-extended = <&intc GIC_SPI 135 IRQ_TYPE_LEVEL_HIGH>,
+ <&intc GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>,
+ <&exti 54 1>;
+ clocks = <&rcc I2C6_K>;
+ resets = <&rcc I2C6_R>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
};
};
};
diff --git a/fdts/stm32mp157caa-pinctrl.dtsi b/fdts/stm32mp157caa-pinctrl.dtsi
index 774561a..9b9cd08 100644
--- a/fdts/stm32mp157caa-pinctrl.dtsi
+++ b/fdts/stm32mp157caa-pinctrl.dtsi
@@ -7,8 +7,8 @@
#include "stm32mp157-pinctrl.dtsi"
/ {
soc {
- pinctrl: pin-controller {
- compatible = "st,stm32mp157caa-pinctrl";
+ pinctrl: pin-controller@50002000 {
+ st,package = <STM32MP157CAA>;
gpioa: gpio@50002000 {
status = "okay";
@@ -77,8 +77,8 @@
};
};
- pinctrl_z: pin-controller-z {
- compatible = "st,stm32mp157caa-z-pinctrl";
+ pinctrl_z: pin-controller-z@54004000 {
+ st,package = <STM32MP157CAA>;
gpioz: gpio@54004000 {
status = "okay";
diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h
index d3f0df7..4e459bb 100644
--- a/include/arch/aarch64/arch_helpers.h
+++ b/include/arch/aarch64/arch_helpers.h
@@ -185,6 +185,7 @@
DEFINE_SYSREG_READ_FUNC(id_aa64isar1_el1)
DEFINE_SYSREG_READ_FUNC(id_aa64pfr0_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)
diff --git a/include/drivers/arm/gicv3.h b/include/drivers/arm/gicv3.h
index 2382697..72221ac 100644
--- a/include/drivers/arm/gicv3.h
+++ b/include/drivers/arm/gicv3.h
@@ -84,6 +84,7 @@
#define GICR_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_WAKER U(0x14)
#define GICR_PROPBASER U(0x70)
diff --git a/include/drivers/st/bsec.h b/include/drivers/st/bsec.h
new file mode 100644
index 0000000..2171550
--- /dev/null
+++ b/include/drivers/st/bsec.h
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef BSEC_H
+#define BSEC_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <lib/utils_def.h>
+
+/*
+ * IP configuration
+ */
+#define BSEC_OTP_MASK GENMASK(4, 0)
+#define BSEC_OTP_BANK_SHIFT 5
+#define BSEC_TIMEOUT_VALUE 0xFFFF
+
+#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)
+
+/*
+ * 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_WRITE_FAIL 0xFFFFFFF9U
+#define BSEC_SHADOW_FAIL 0xFFFFFFF8U
+#define BSEC_TIMEOUT 0xFFFFFFF7U
+
+/*
+ * BSEC REGISTER OFFSET (base relative)
+ */
+#define BSEC_OTP_CONF_OFF 0x000U
+#define BSEC_OTP_CTRL_OFF 0x004U
+#define BSEC_OTP_WRDATA_OFF 0x008U
+#define BSEC_OTP_STATUS_OFF 0x00CU
+#define BSEC_OTP_LOCK_OFF 0x010U
+#define BSEC_DEN_OFF 0x014U
+#define BSEC_DISTURBED_OFF 0x01CU
+#define BSEC_DISTURBED1_OFF 0x020U
+#define BSEC_DISTURBED2_OFF 0x024U
+#define BSEC_ERROR_OFF 0x034U
+#define BSEC_ERROR1_OFF 0x038U
+#define BSEC_ERROR2_OFF 0x03CU
+#define BSEC_WRLOCK_OFF 0x04CU /* Safmem permanent lock */
+#define BSEC_WRLOCK1_OFF 0x050U
+#define BSEC_WRLOCK2_OFF 0x054U
+#define BSEC_SPLOCK_OFF 0x064U /* Program safmem sticky lock */
+#define BSEC_SPLOCK1_OFF 0x068U
+#define BSEC_SPLOCK2_OFF 0x06CU
+#define BSEC_SWLOCK_OFF 0x07CU /* Write in OTP sticky lock */
+#define BSEC_SWLOCK1_OFF 0x080U
+#define BSEC_SWLOCK2_OFF 0x084U
+#define BSEC_SRLOCK_OFF 0x094U /* Shadowing sticky lock */
+#define BSEC_SRLOCK1_OFF 0x098U
+#define BSEC_SRLOCK2_OFF 0x09CU
+#define BSEC_JTAG_IN_OFF 0x0ACU
+#define BSEC_JTAG_OUT_OFF 0x0B0U
+#define BSEC_SCRATCH_OFF 0x0B4U
+#define BSEC_OTP_DATA_OFF 0x200U
+#define BSEC_IPHW_CFG_OFF 0xFF0U
+#define BSEC_IPVR_OFF 0xFF4U
+#define BSEC_IP_ID_OFF 0xFF8U
+#define BSEC_IP_MAGIC_ID_OFF 0xFFCU
+
+/*
+ * 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 0x000U
+#define BSEC_WRITE 0x100U
+#define BSEC_LOCK 0x200U
+
+/*
+ * 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_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)
+
+/* OTP MODE*/
+#define BSEC_MODE_OPEN1 0x00
+#define BSEC_MODE_SECURED 0x01
+#define BSEC_MODE_OPEN2 0x02
+#define BSEC_MODE_INVALID 0x04
+
+/* 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)
+
+/*
+ * OTP Lock services definition
+ * Value must corresponding to the bit number in the register
+ */
+#define BSEC_LOCK_UPPER_OTP 0x00
+#define BSEC_LOCK_DEBUG 0x02
+#define BSEC_LOCK_PROGRAM 0x03
+
+/* 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 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 den_lock; /* Debug enable sticky lock
+ * 1 debug enable 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);
+
+uint32_t bsec_write_debug_conf(uint32_t val);
+uint32_t bsec_read_debug_conf(void);
+uint32_t bsec_write_feature_conf(uint32_t val);
+uint32_t bsec_read_feature_conf(uint32_t *val);
+
+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);
+
+bool bsec_write_sr_lock(uint32_t otp, uint32_t value);
+bool bsec_read_sr_lock(uint32_t otp);
+bool bsec_write_sw_lock(uint32_t otp, uint32_t value);
+bool bsec_read_sw_lock(uint32_t otp);
+bool bsec_write_sp_lock(uint32_t otp, uint32_t value);
+bool bsec_read_sp_lock(uint32_t otp);
+bool bsec_wr_lock(uint32_t otp);
+uint32_t bsec_otp_lock(uint32_t service, uint32_t value);
+
+bool bsec_mode_is_closed_device(void);
+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/include/drivers/st/stm32_gpio.h b/include/drivers/st/stm32_gpio.h
index acd95ec..4320eaf 100644
--- a/include/drivers/st/stm32_gpio.h
+++ b/include/drivers/st/stm32_gpio.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -9,10 +9,6 @@
#include <lib/utils_def.h>
-#define STM32_GPIOA_BANK U(0x50002000)
-#define STM32_GPIOZ_BANK U(0x54004000)
-#define STM32_GPIO_BANK_OFFSET U(0x1000)
-
#define GPIO_MODE_OFFSET U(0x00)
#define GPIO_TYPE_OFFSET U(0x04)
#define GPIO_SPEED_OFFSET U(0x08)
@@ -20,56 +16,14 @@
#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_BANK_A U(0x00)
-#define GPIO_BANK_B U(0x01)
-#define GPIO_BANK_C U(0x02)
-#define GPIO_BANK_D U(0x03)
-#define GPIO_BANK_E U(0x04)
-#define GPIO_BANK_F U(0x05)
-#define GPIO_BANK_G U(0x06)
-#define GPIO_BANK_H U(0x07)
-#define GPIO_BANK_I U(0x08)
-#define GPIO_BANK_J U(0x09)
-#define GPIO_BANK_K U(0x0A)
-#define GPIO_BANK_Z U(0x19)
+#define GPIO_PIN_(_x) U(_x)
+#define GPIO_PIN_MAX GPIO_PIN_(15)
-#define GPIO_PIN_0 U(0x00)
-#define GPIO_PIN_1 U(0x01)
-#define GPIO_PIN_2 U(0x02)
-#define GPIO_PIN_3 U(0x03)
-#define GPIO_PIN_4 U(0x04)
-#define GPIO_PIN_5 U(0x05)
-#define GPIO_PIN_6 U(0x06)
-#define GPIO_PIN_7 U(0x07)
-#define GPIO_PIN_8 U(0x08)
-#define GPIO_PIN_9 U(0x09)
-#define GPIO_PIN_10 U(0x0A)
-#define GPIO_PIN_11 U(0x0B)
-#define GPIO_PIN_12 U(0x0C)
-#define GPIO_PIN_13 U(0x0D)
-#define GPIO_PIN_14 U(0x0E)
-#define GPIO_PIN_15 U(0x0F)
-#define GPIO_PIN_MAX GPIO_PIN_15
-
-#define GPIO_ALTERNATE_0 0x00
-#define GPIO_ALTERNATE_1 0x01
-#define GPIO_ALTERNATE_2 0x02
-#define GPIO_ALTERNATE_3 0x03
-#define GPIO_ALTERNATE_4 0x04
-#define GPIO_ALTERNATE_5 0x05
-#define GPIO_ALTERNATE_6 0x06
-#define GPIO_ALTERNATE_7 0x07
-#define GPIO_ALTERNATE_8 0x08
-#define GPIO_ALTERNATE_9 0x09
-#define GPIO_ALTERNATE_10 0x0A
-#define GPIO_ALTERNATE_11 0x0B
-#define GPIO_ALTERNATE_12 0x0C
-#define GPIO_ALTERNATE_13 0x0D
-#define GPIO_ALTERNATE_14 0x0E
-#define GPIO_ALTERNATE_15 0x0F
+#define GPIO_ALTERNATE_(_x) U(_x)
#define GPIO_ALTERNATE_MASK U(0x0F)
#define GPIO_MODE_INPUT 0x00
@@ -82,8 +36,8 @@
#define GPIO_SPEED_LOW 0x00
#define GPIO_SPEED_MEDIUM 0x01
-#define GPIO_SPEED_FAST 0x02
-#define GPIO_SPEED_HIGH 0x03
+#define GPIO_SPEED_HIGH 0x02
+#define GPIO_SPEED_VERY_HIGH 0x03
#define GPIO_SPEED_MASK U(0x03)
#define GPIO_NO_PULL 0x00
@@ -94,8 +48,10 @@
#ifndef __ASSEMBLY__
#include <stdint.h>
+int dt_set_pinctrl_config(int node);
void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t speed,
- uint32_t pull, uint32_t alternate);
+ uint32_t pull, uint32_t alternate, uint8_t status);
+void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure);
#endif /*__ASSEMBLY__*/
#endif /* STM32_GPIO_H */
diff --git a/include/drivers/st/stm32mp1_ddr.h b/include/drivers/st/stm32mp1_ddr.h
index 363e302..4ab37d6 100644
--- a/include/drivers/st/stm32mp1_ddr.h
+++ b/include/drivers/st/stm32mp1_ddr.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2018, STMicroelectronics - All Rights Reserved
+ * Copyright (C) 2018-2019, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
*/
@@ -153,7 +153,7 @@
struct stm32mp1_ddr_info {
const char *name;
- uint16_t speed; /* in MHZ */
+ uint32_t speed; /* in kHZ */
uint32_t size; /* Memory size in byte = col * row * width */
};
@@ -168,7 +168,7 @@
struct stm32mp1_ddrphy_cal p_cal;
};
-int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint16_t mem_speed);
+int stm32mp1_ddr_clk_enable(struct ddr_info *priv, uint32_t mem_speed);
void stm32mp1_ddr_init(struct ddr_info *priv,
struct stm32mp1_ddr_config *config);
#endif /* STM32MP1_DDR_H */
diff --git a/include/drivers/st/stm32mp1_ddr_regs.h b/include/drivers/st/stm32mp1_ddr_regs.h
index bfcd5e2..342239a 100644
--- a/include/drivers/st/stm32mp1_ddr_regs.h
+++ b/include/drivers/st/stm32mp1_ddr_regs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
*/
@@ -247,11 +247,14 @@
#define DDRCTRL_DBGSTAT 0x310
#define DDRCTRL_SWCTL 0x320
#define DDRCTRL_SWSTAT 0x324
+#define DDRCTRL_PSTAT 0x3FC
#define DDRCTRL_PCTRL_0 0x490
#define DDRCTRL_PCTRL_1 0x540
/* 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_DATA_BUS_WIDTH_MASK GENMASK(13, 12)
#define DDRCTRL_MSTR_DATA_BUS_WIDTH_FULL 0
#define DDRCTRL_MSTR_DATA_BUS_WIDTH_HALF BIT(12)
@@ -269,7 +272,7 @@
/* Only one rank supported */
#define DDRCTRL_MRCTRL0_MR_RANK_SHIFT 4
#define DDRCTRL_MRCTRL0_MR_RANK_ALL \
- (0x1U << DDRCTRL_MRCTRL0_MR_RANK_SHIFT)
+ 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)
@@ -367,6 +370,7 @@
#define DDRPHYC_DLLGCR_BPS200 BIT(23)
+#define DDRPHYC_ACDLLCR_DLLSRST BIT(30)
#define DDRPHYC_ACDLLCR_DLLDIS BIT(31)
#define DDRPHYC_PTR0_TDLLSRST_OFFSET 0
diff --git a/include/drivers/st/stm32mp1_rcc.h b/include/drivers/st/stm32mp1_rcc.h
index fd406c5..2f29e84 100644
--- a/include/drivers/st/stm32mp1_rcc.h
+++ b/include/drivers/st/stm32mp1_rcc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2015-2019, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -68,6 +68,14 @@
#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)
@@ -78,6 +86,14 @@
#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)
@@ -162,6 +178,22 @@
#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)
@@ -178,10 +210,31 @@
#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)
+#define RCC_OFFSET_MASK GENMASK(11, 0)
+
/* Values for RCC_TZCR register */
#define RCC_TZCR_TZEN BIT(0)
@@ -221,6 +274,9 @@
#define RCC_MPUDIV_MASK GENMASK(2, 0)
#define RCC_AXIDIV_MASK GENMASK(2, 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)
@@ -228,6 +284,7 @@
#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)
@@ -243,6 +300,7 @@
/* Used for all RCC_PLL<n>CR 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)
@@ -281,8 +339,12 @@
/* 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)
@@ -319,6 +381,16 @@
/* Fields of RCC_HSICFGR register */
#define RCC_HSICFGR_HSIDIV_MASK GENMASK(1, 0)
+#define RCC_HSICFGR_HSITRIM_SHIFT 8
+#define RCC_HSICFGR_HSITRIM_MASK GENMASK(14, 8)
+#define RCC_HSICFGR_HSICAL_SHIFT 16
+#define RCC_HSICFGR_HSICAL_MASK GENMASK(27, 16)
+
+/* Fields of RCC_CSICFGR register */
+#define RCC_CSICFGR_CSITRIM_SHIFT 8
+#define RCC_CSICFGR_CSITRIM_MASK GENMASK(12, 8)
+#define RCC_CSICFGR_CSICAL_SHIFT 16
+#define RCC_CSICFGR_CSICAL_MASK GENMASK(23, 16)
/* Used for RCC_MCO related operations */
#define RCC_MCOCFG_MCOON BIT(12)
@@ -330,22 +402,36 @@
#define RCC_DBGCFGR_DBGCKEN BIT(8)
/* RCC register fields for reset reasons */
-#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_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_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)
/* Global Reset Register */
#define RCC_MP_GRSTCSETR_MPSYSRST BIT(0)
+#define RCC_MP_GRSTCSETR_MPUP0RST BIT(4)
+#define RCC_MP_GRSTCSETR_MPUP1RST BIT(5)
/* Clock Source Interrupt Flag Register */
#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_WKUPF BIT(20)
/* Stop Request Set Register */
@@ -362,7 +448,29 @@
/* Values of RCC_MP_APB1ENSETR register */
#define RCC_MP_APB1ENSETR_UART4EN BIT(16)
+/* Values of RCC_MP_APB5ENSETR register */
+#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_IWDG1APBEN BIT(15)
+
/* Values of RCC_MP_AHB4ENSETR register */
#define RCC_MP_AHB4ENSETR_GPIOGEN BIT(6)
+#define RCC_MP_AHB4ENSETR_GPIOHEN BIT(7)
+
+/* Values of RCC_MP_AHB5ENSETR register */
+#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)
+
+/* Values of RCC_MP_IWDGFZSETR register */
+#define RCC_MP_IWDGFZSETR_IWDG1 BIT(0)
+#define RCC_MP_IWDGFZSETR_IWDG2 BIT(1)
+
+/* Values of RCC_PWRLPDLYCR register */
+#define RCC_PWRLPDLYCR_PWRLP_DLY_MASK GENMASK(21, 0)
#endif /* STM32MP1_RCC_H */
diff --git a/include/drivers/st/stm32mp1_pmic.h b/include/drivers/st/stm32mp_pmic.h
similarity index 67%
rename from include/drivers/st/stm32mp1_pmic.h
rename to include/drivers/st/stm32mp_pmic.h
index 75f8e61..700039b 100644
--- a/include/drivers/st/stm32mp1_pmic.h
+++ b/include/drivers/st/stm32mp_pmic.h
@@ -1,11 +1,11 @@
/*
- * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2017-2019, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
-#ifndef STM32MP1_PMIC_H
-#define STM32MP1_PMIC_H
+#ifndef STM32MP_PMIC_H
+#define STM32MP_PMIC_H
#include <stdbool.h>
@@ -17,4 +17,4 @@
void initialize_pmic(void);
int pmic_ddr_power_init(enum ddr_type ddr_type);
-#endif /* STM32MP1_PMIC_H */
+#endif /* STM32MP_PMIC_H */
diff --git a/include/drivers/st/stpmu1.h b/include/drivers/st/stpmic1.h
similarity index 70%
rename from include/drivers/st/stpmu1.h
rename to include/drivers/st/stpmic1.h
index e75d9a6..f7e293b 100644
--- a/include/drivers/st/stpmu1.h
+++ b/include/drivers/st/stpmic1.h
@@ -1,11 +1,11 @@
/*
- * Copyright (c) 2016-2018, STMicroelectronics - All Rights Reserved
+ * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
-#ifndef STPMU1_H
-#define STPMU1_H
+#ifndef STPMIC1_H
+#define STPMIC1_H
#include <drivers/st/stm32_i2c.h>
#include <lib/utils_def.h>
@@ -84,18 +84,40 @@
#define ITSOURCE2_REG 0xB1U
#define ITSOURCE3_REG 0xB2U
#define ITSOURCE4_REG 0xB3U
+
+/* Registers masks */
#define LDO_VOLTAGE_MASK 0x7CU
#define BUCK_VOLTAGE_MASK 0xFCU
#define LDO_BUCK_VOLTAGE_SHIFT 2
-#define LDO_ENABLE_MASK 0x01U
-#define BUCK_ENABLE_MASK 0x01U
-#define BUCK_HPLP_ENABLE_MASK 0x02U
-#define LDO_HPLP_ENABLE_MASK 0x02U
+#define LDO_BUCK_ENABLE_MASK 0x01U
+#define LDO_BUCK_HPLP_ENABLE_MASK 0x02U
#define LDO_BUCK_HPLP_SHIFT 1
#define LDO_BUCK_RANK_MASK 0x01U
#define LDO_BUCK_RESET_MASK 0x01U
#define LDO_BUCK_PULL_DOWN_MASK 0x03U
+/* 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
+
+/* 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
+
/* Main PMIC Control Register (MAIN_CONTROL_REG) */
#define ICC_EVENT_ENABLED BIT(4)
#define PWRCTRL_POLARITY_HIGH BIT(3)
@@ -127,14 +149,21 @@
#define SWIN_SWOUT_ENABLED BIT(2)
#define USBSW_OTG_SWITCH_ENABLED BIT(1)
-int stpmu1_switch_off(void);
-int stpmu1_register_read(uint8_t register_id, uint8_t *value);
-int stpmu1_register_write(uint8_t register_id, uint8_t value);
-int stpmu1_register_update(uint8_t register_id, uint8_t value, uint8_t mask);
-int stpmu1_regulator_enable(const char *name);
-int stpmu1_regulator_disable(const char *name);
-uint8_t stpmu1_is_regulator_enabled(const char *name);
-int stpmu1_regulator_voltage_set(const char *name, uint16_t millivolts);
-void stpmu1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr);
+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);
+uint8_t stpmic1_is_regulator_enabled(const char *name);
+int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts);
+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);
+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 /* STPMU1_H */
+#endif /* STPMIC1_H */
diff --git a/include/dt-bindings/interrupt-controller/arm-gic.h b/include/dt-bindings/interrupt-controller/arm-gic.h
new file mode 100644
index 0000000..aa9158c
--- /dev/null
+++ b/include/dt-bindings/interrupt-controller/arm-gic.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */
+/*
+ * This header provides constants for the ARM GIC.
+ */
+
+#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H
+#define _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H
+
+/* interrupt specifier cell 0 */
+
+#define GIC_SPI 0
+#define GIC_PPI 1
+
+#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/include/dt-bindings/pinctrl/stm32-pinfunc.h b/include/dt-bindings/pinctrl/stm32-pinfunc.h
index e2f1f1b..7f6e4b9 100644
--- a/include/dt-bindings/pinctrl/stm32-pinfunc.h
+++ b/include/dt-bindings/pinctrl/stm32-pinfunc.h
@@ -32,4 +32,10 @@
#define STM32_PINMUX(port, line, mode) (((PIN_NO(port, line)) << 8) | (mode))
+/* package information */
+#define STM32MP157CAA 0x1
+#define STM32MP157CAB 0x2
+#define STM32MP157CAC 0x4
+#define STM32MP157CAD 0x8
+
#endif /* _DT_BINDINGS_STM32_PINFUNC_H */
diff --git a/include/plat/arm/common/arm_spm_def.h b/include/plat/arm/common/arm_spm_def.h
index 997e156..16c806b 100644
--- a/include/plat/arm/common/arm_spm_def.h
+++ b/include/plat/arm/common/arm_spm_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -32,7 +32,7 @@
#define PLAT_SPM_HEAP_BASE (PLAT_SP_PACKAGE_BASE + PLAT_SP_PACKAGE_SIZE)
#define PLAT_SPM_HEAP_SIZE (BL32_LIMIT - BL32_BASE - PLAT_SP_PACKAGE_SIZE)
-#if SPM_DEPRECATED
+#if SPM_MM
/*
* If BL31 is placed in DRAM, place the Secure Partition in DRAM right after the
@@ -121,7 +121,7 @@
/* Total number of memory regions with distinct properties */
#define ARM_SP_IMAGE_NUM_MEM_REGIONS 6
-#endif /* SPM_DEPRECATED */
+#endif /* SPM_MM */
/* Cookies passed to the Secure Partition at boot. Not used by ARM platforms. */
#define PLAT_SPM_COOKIE_0 ULL(0)
diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h
index d1c03be..b5edc74 100644
--- a/include/plat/arm/common/plat_arm.h
+++ b/include/plat/arm/common/plat_arm.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -38,7 +38,7 @@
* - Region 1 with secure access only;
* - the remaining DRAM regions access from the given Non-Secure masters.
******************************************************************************/
-#if ENABLE_SPM && SPM_DEPRECATED
+#if ENABLE_SPM && SPM_MM
#define ARM_TZC_REGIONS_DEF \
{ARM_AP_TZC_DRAM1_BASE, ARM_EL3_TZC_DRAM1_END, \
TZC_REGION_S_RDWR, 0}, \
diff --git a/include/services/mm_svc.h b/include/services/mm_svc.h
index c81e904..c111326 100644
--- a/include/services/mm_svc.h
+++ b/include/services/mm_svc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,7 +7,7 @@
#ifndef MM_SVC_H
#define MM_SVC_H
-#if SPM_DEPRECATED
+#if SPM_MM
#include <lib/utils_def.h>
@@ -30,6 +30,6 @@
#define MM_COMMUNICATE_AARCH64 U(0xC4000041)
#define MM_COMMUNICATE_AARCH32 U(0x84000041)
-#endif /* SPM_DEPRECATED */
+#endif /* SPM_MM */
#endif /* MM_SVC_H */
diff --git a/include/services/secure_partition.h b/include/services/secure_partition.h
index 47f6368..0510f80 100644
--- a/include/services/secure_partition.h
+++ b/include/services/secure_partition.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,7 +7,7 @@
#ifndef SECURE_PARTITION_H
#define SECURE_PARTITION_H
-#if SPM_DEPRECATED
+#if SPM_MM
#include <stdint.h>
@@ -49,6 +49,6 @@
secure_partition_mp_info_t *mp_info;
} secure_partition_boot_info_t;
-#endif /* SPM_DEPRECATED */
+#endif /* SPM_MM */
#endif /* SECURE_PARTITION_H */
diff --git a/include/services/spm_svc.h b/include/services/spm_svc.h
index fcb409b..57912e8 100644
--- a/include/services/spm_svc.h
+++ b/include/services/spm_svc.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -7,7 +7,7 @@
#ifndef SPM_SVC_H
#define SPM_SVC_H
-#if SPM_DEPRECATED
+#if SPM_MM
#include <lib/utils_def.h>
@@ -61,7 +61,7 @@
#define SPM_DENIED -3
#define SPM_NO_MEMORY -5
-#endif /* SPM_DEPRECATED */
+#endif /* SPM_MM */
#ifndef __ASSEMBLY__
@@ -69,7 +69,7 @@
int32_t spm_setup(void);
-#if SPM_DEPRECATED
+#if SPM_MM
uint64_t spm_smc_handler(uint32_t smc_fid,
uint64_t x1,
@@ -83,7 +83,7 @@
/* Helper to enter a Secure Partition */
uint64_t spm_sp_call(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3);
-#endif /* SPM_DEPRECATED */
+#endif /* SPM_MM */
#endif /* __ASSEMBLY__ */
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index a55e729..8ef1bb9 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -162,8 +162,8 @@
# For including the Secure Partition Manager
ENABLE_SPM := 0
-# Use the deprecated SPM based on MM
-SPM_DEPRECATED := 1
+# Use the SPM based on MM
+SPM_MM := 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.
diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c
index 4da807a..fdf82f4 100644
--- a/plat/arm/board/fvp/fvp_common.c
+++ b/plat/arm/board/fvp/fvp_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -95,10 +95,10 @@
ARM_MAP_BL1_RW,
#endif
#endif /* TRUSTED_BOARD_BOOT */
-#if ENABLE_SPM && SPM_DEPRECATED
+#if ENABLE_SPM && SPM_MM
ARM_SP_IMAGE_MMAP,
#endif
-#if ENABLE_SPM && !SPM_DEPRECATED
+#if ENABLE_SPM && !SPM_MM
PLAT_MAP_SP_PACKAGE_MEM_RW,
#endif
#if ARM_BL31_IN_DRAM
@@ -126,16 +126,16 @@
MAP_DEVICE0,
MAP_DEVICE1,
ARM_V2M_MAP_MEM_PROTECT,
-#if ENABLE_SPM && SPM_DEPRECATED
+#if ENABLE_SPM && SPM_MM
ARM_SPM_BUF_EL3_MMAP,
#endif
-#if ENABLE_SPM && !SPM_DEPRECATED
+#if ENABLE_SPM && !SPM_MM
PLAT_MAP_SP_PACKAGE_MEM_RO,
#endif
{0}
};
-#if ENABLE_SPM && defined(IMAGE_BL31) && SPM_DEPRECATED
+#if ENABLE_SPM && 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, \
@@ -189,7 +189,7 @@
}
#endif
-#if ENABLE_SPM && defined(IMAGE_BL31) && SPM_DEPRECATED
+#if ENABLE_SPM && defined(IMAGE_BL31) && SPM_MM
/*
* Boot information passed to a secure partition during initialisation. Linear
* indices in MP information will be filled at runtime.
diff --git a/plat/arm/board/fvp/include/platform_def.h b/plat/arm/board/fvp/include/platform_def.h
index 31f06a9..8c0daf1 100644
--- a/plat/arm/board/fvp/include/platform_def.h
+++ b/plat/arm/board/fvp/include/platform_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -13,7 +13,7 @@
# define PLAT_XLAT_TABLES_DYNAMIC 1
# endif
#else
-# if defined(IMAGE_BL31) && (RESET_TO_BL31 || (ENABLE_SPM && !SPM_DEPRECATED))
+# if defined(IMAGE_BL31) && (RESET_TO_BL31 || (ENABLE_SPM && !SPM_MM))
# define PLAT_XLAT_TABLES_DYNAMIC 1
# endif
#endif /* AARCH32 */
@@ -125,7 +125,7 @@
* calculated using the current BL31 PROGBITS debug size plus the sizes of
* BL2 and BL1-RW
*/
-#if ENABLE_SPM && !SPM_DEPRECATED
+#if ENABLE_SPM && !SPM_MM
#define PLAT_ARM_MAX_BL31_SIZE UL(0x60000)
#else
#define PLAT_ARM_MAX_BL31_SIZE UL(0x3B000)
diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk
index a8ac286..9ad7bd7 100644
--- a/plat/arm/common/arm_common.mk
+++ b/plat/arm/common/arm_common.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -240,7 +240,7 @@
endif
# SPM uses libfdt in Arm platforms
-ifeq (${SPM_DEPRECATED},0)
+ifeq (${SPM_MM},0)
ifeq (${ENABLE_SPM},1)
BL31_SOURCES += common/fdt_wrappers.c \
plat/common/plat_spm_rd.c \
diff --git a/plat/imx/imx7/warp7/include/platform_def.h b/plat/imx/imx7/warp7/include/platform_def.h
index a931c80..d58382f 100644
--- a/plat/imx/imx7/warp7/include/platform_def.h
+++ b/plat/imx/imx7/warp7/include/platform_def.h
@@ -106,6 +106,12 @@
#define WARP7_DTB_BASE (DRAM_BASE + 0x03000000)
#define WARP7_DTB_LIMIT (WARP7_DTB_BASE + WARP7_DTB_SIZE)
+/* Define the absolute location of DTB Overlay 0x83100000 - 0x83101000 */
+#define WARP7_DTB_OVERLAY_SIZE 0x00001000
+#define WARP7_DTB_OVERLAY_BASE WARP7_DTB_LIMIT
+#define WARP7_DTB_OVERLAY_LIMIT (WARP7_DTB_OVERLAY_BASE + \
+ WARP7_DTB_OVERLAY_SIZE)
+
/*
* BL2 specific defines.
*
@@ -142,6 +148,8 @@
* | DDR | BL33/U-BOOT
* 0x87800000 +-----------------+
* | DDR | Unallocated
+ * 0x83101000 +-----------------+
+ * | DDR | DTB Overlay
* 0x83100000 +-----------------+
* | DDR | DTB
* 0x83000000 +-----------------+
diff --git a/plat/imx/imx7/warp7/platform.mk b/plat/imx/imx7/warp7/platform.mk
index a771865..f7bd4ae 100644
--- a/plat/imx/imx7/warp7/platform.mk
+++ b/plat/imx/imx7/warp7/platform.mk
@@ -62,6 +62,43 @@
plat/imx/imx7/warp7/warp7_image_load.c \
${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.c
+
+BL2_SOURCES += ${AUTH_SOURCES} \
+ plat/common/tbbr/plat_tbbr.c \
+ plat/imx/imx7/warp7/warp7_trusted_boot.c \
+ plat/imx/imx7/warp7/warp7_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/warp7_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
+
# Build config flags
# ------------------
@@ -86,6 +123,21 @@
PLAT_WARP7_UART :=1
$(eval $(call add_define,PLAT_WARP7_UART))
+# 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
# -------------------
diff --git a/plat/imx/imx7/warp7/warp7_bl2_el3_setup.c b/plat/imx/imx7/warp7/warp7_bl2_el3_setup.c
index 032ed7b..08baf19 100644
--- a/plat/imx/imx7/warp7/warp7_bl2_el3_setup.c
+++ b/plat/imx/imx7/warp7/warp7_bl2_el3_setup.c
@@ -290,12 +290,13 @@
imx_wdog_init();
/* Print out the expected memory map */
- VERBOSE("\tOPTEE 0x%08x-0x%08x\n", WARP7_OPTEE_BASE, WARP7_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", WARP7_FIP_BASE, WARP7_FIP_LIMIT);
- VERBOSE("\tDTB 0x%08x-0x%08x\n", WARP7_DTB_BASE, WARP7_DTB_LIMIT);
- VERBOSE("\tUBOOT/BL33 0x%08x-0x%08x\n", WARP7_UBOOT_BASE, WARP7_UBOOT_LIMIT);
+ VERBOSE("\tOPTEE 0x%08x-0x%08x\n", WARP7_OPTEE_BASE, WARP7_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", WARP7_FIP_BASE, WARP7_FIP_LIMIT);
+ VERBOSE("\tDTB-OVERLAY 0x%08x-0x%08x\n", WARP7_DTB_OVERLAY_BASE, WARP7_DTB_OVERLAY_LIMIT);
+ VERBOSE("\tDTB 0x%08x-0x%08x\n", WARP7_DTB_BASE, WARP7_DTB_LIMIT);
+ VERBOSE("\tUBOOT/BL33 0x%08x-0x%08x\n", WARP7_UBOOT_BASE, WARP7_UBOOT_LIMIT);
}
/*
diff --git a/plat/imx/imx7/warp7/warp7_bl2_mem_params_desc.c b/plat/imx/imx7/warp7/warp7_bl2_mem_params_desc.c
index a29e141..c670d42 100644
--- a/plat/imx/imx7/warp7/warp7_bl2_mem_params_desc.c
+++ b/plat/imx/imx7/warp7/warp7_bl2_mem_params_desc.c
@@ -28,16 +28,6 @@
.next_handoff_image_id = BL33_IMAGE_ID,
},
{
- .image_id = HW_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, 0),
- .image_info.image_base = WARP7_DTB_BASE,
- .image_info.image_max_size = WARP7_DTB_SIZE,
- .next_handoff_image_id = INVALID_IMAGE_ID,
- },
- {
.image_id = BL32_EXTRA1_IMAGE_ID,
SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, VERSION_2,
diff --git a/plat/imx/imx7/warp7/warp7_io_storage.c b/plat/imx/imx7/warp7/warp7_io_storage.c
index b9cace0..fcfb503 100644
--- a/plat/imx/imx7/warp7/warp7_io_storage.c
+++ b/plat/imx/imx7/warp7/warp7_io_storage.c
@@ -60,10 +60,6 @@
.uuid = UUID_SECURE_PAYLOAD_BL32,
};
-static const io_uuid_spec_t hw_config_uuid_spec = {
- .uuid = UUID_HW_CONFIG,
-};
-
static const io_uuid_spec_t bl32_extra1_uuid_spec = {
.uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1,
};
@@ -76,6 +72,32 @@
.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 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 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;
@@ -112,16 +134,43 @@
(uintptr_t)&bl32_extra2_uuid_spec,
open_fip
},
- [HW_CONFIG_ID] = {
+ [BL33_IMAGE_ID] = {
&fip_dev_handle,
- (uintptr_t)&hw_config_uuid_spec,
+ (uintptr_t)&bl33_uuid_spec,
open_fip
},
- [BL33_IMAGE_ID] = {
+#if TRUSTED_BOARD_BOOT
+ [TRUSTED_BOOT_FW_CERT_ID] = {
&fip_dev_handle,
- (uintptr_t)&bl33_uuid_spec,
+ (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
+ },
+ [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
+ },
+ [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)
diff --git a/plat/imx/imx7/warp7/warp7_rotpk.S b/plat/imx/imx7/warp7/warp7_rotpk.S
new file mode 100644
index 0000000..f74b6d25b
--- /dev/null
+++ b/plat/imx/imx7/warp7/warp7_rotpk.S
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+ .global warp7_rotpk_hash
+ .global warp7_rotpk_hash_end
+warp7_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
+warp7_rotpk_hash_end:
diff --git a/plat/imx/imx7/warp7/warp7_trusted_boot.c b/plat/imx/imx7/warp7/warp7_trusted_boot.c
new file mode 100644
index 0000000..8157cd5
--- /dev/null
+++ b/plat/imx/imx7/warp7/warp7_trusted_boot.c
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <plat/common/platform.h>
+
+extern char warp7_rotpk_hash[], warp7_rotpk_hash_end[];
+
+int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len,
+ unsigned int *flags)
+{
+ *key_ptr = warp7_rotpk_hash;
+ *key_len = warp7_rotpk_hash_end - warp7_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;
+}
diff --git a/plat/imx/imx8m/imx8mq/platform.mk b/plat/imx/imx8m/imx8mq/platform.mk
index 0255268..2681e57 100644
--- a/plat/imx/imx8m/imx8mq/platform.mk
+++ b/plat/imx/imx8m/imx8mq/platform.mk
@@ -34,3 +34,7 @@
RESET_TO_BL31 := 1
A53_DISABLE_NON_TEMPORAL_HINT := 0
MULTI_CONSOLE_API := 1
+
+ERRATA_A53_835769 := 1
+ERRATA_A53_843419 := 1
+ERRATA_A53_855873 := 1
diff --git a/plat/imx/imx8qm/platform.mk b/plat/imx/imx8qm/platform.mk
index 9113d33..ed6108d 100644
--- a/plat/imx/imx8qm/platform.mk
+++ b/plat/imx/imx8qm/platform.mk
@@ -38,3 +38,7 @@
A53_DISABLE_NON_TEMPORAL_HINT := 0
MULTI_CONSOLE_API := 1
ERRATA_A72_859971 := 1
+
+ERRATA_A53_835769 := 1
+ERRATA_A53_843419 := 1
+ERRATA_A53_855873 := 1
diff --git a/plat/nvidia/tegra/common/aarch64/tegra_helpers.S b/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
index 2bf9a22..b47be6d 100644
--- a/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
+++ b/plat/nvidia/tegra/common/aarch64/tegra_helpers.S
@@ -18,16 +18,21 @@
/*******************************************************************************
* 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)
+#define ACTLR_EL3_L2ACTLR_BIT (U(1) << 6)
+#define ACTLR_EL3_L2ECTLR_BIT (U(1) << 5)
+#define ACTLR_EL3_L2CTLR_BIT (U(1) << 4)
+#define ACTLR_EL3_CPUECTLR_BIT (U(1) << 1)
+#define ACTLR_EL3_CPUACTLR_BIT (U(1) << 0)
+#define ACTLR_EL3_ENABLE_ALL_MASK (ACTLR_EL3_L2ACTLR_BIT | \
+ ACTLR_EL3_L2ECTLR_BIT | \
+ ACTLR_EL3_L2CTLR_BIT | \
+ ACTLR_EL3_CPUECTLR_BIT | \
+ ACTLR_EL3_CPUACTLR_BIT)
#define ACTLR_EL3_ENABLE_ALL_ACCESS (ACTLR_EL3_L2ACTLR_BIT | \
- ACTLR_EL3_L2ECTLR_BIT | \
- ACTLR_EL3_L2CTLR_BIT | \
- ACTLR_EL3_CPUECTLR_BIT | \
- ACTLR_EL3_CPUACTLR_BIT)
+ ACTLR_EL3_L2ECTLR_BIT | \
+ ACTLR_EL3_L2CTLR_BIT | \
+ ACTLR_EL3_CPUECTLR_BIT | \
+ ACTLR_EL3_CPUACTLR_BIT)
/* Global functions */
.globl plat_is_my_cpu_primary
@@ -87,8 +92,17 @@
* Enable L2 and CPU ECTLR RW access from non-secure world
* -------------------------------------------------------
*/
- mov x0, #ACTLR_EL3_ENABLE_ALL_ACCESS
+ mrs x0, actlr_el3
+ mov x1, #ACTLR_EL3_ENABLE_ALL_MASK
+ bic x0, x0, x1
+ mov x1, #ACTLR_EL3_ENABLE_ALL_ACCESS
+ orr x0, x0, x1
msr actlr_el3, x0
+ mrs x0, actlr_el2
+ mov x1, #ACTLR_EL3_ENABLE_ALL_MASK
+ bic x0, x0, x1
+ mov x1, #ACTLR_EL3_ENABLE_ALL_ACCESS
+ orr x0, x0, x1
msr actlr_el2, x0
isb
@@ -130,17 +144,20 @@
ret
endfunc plat_is_my_cpu_primary
- /* -----------------------------------------------------
+ /* ----------------------------------------------------------
* unsigned int plat_my_core_pos(void);
*
- * result: CorePos = CoreId + (ClusterId << 2)
- * -----------------------------------------------------
+ * result: CorePos = CoreId + (ClusterId * cpus per cluster)
+ * ----------------------------------------------------------
*/
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
+ lsr x0, x0, #MPIDR_AFFINITY_BITS
+ mov x2, #PLATFORM_MAX_CPUS_PER_CLUSTER
+ mul x0, x0, x2
+ add x0, x1, x0
ret
endfunc plat_my_core_pos
@@ -162,14 +179,17 @@
/* -----------------------------------------------------
* int platform_get_core_pos(int mpidr);
*
- * With this function: CorePos = (ClusterId * 4) +
- * CoreId
+ * result: CorePos = (ClusterId * cpus per cluster) +
+ * CoreId
* -----------------------------------------------------
*/
func platform_get_core_pos
and x1, x0, #MPIDR_CPU_MASK
and x0, x0, #MPIDR_CLUSTER_MASK
- add x0, x1, x0, LSR #6
+ lsr x0, x0, #MPIDR_AFFINITY_BITS
+ mov x2, #PLATFORM_MAX_CPUS_PER_CLUSTER
+ mul x0, x0, x2
+ add x0, x1, x0
ret
endfunc platform_get_core_pos
@@ -400,31 +420,6 @@
mov x0, #1
msr oslar_el1, x0
- cpu_init_common
-
- /* ---------------------------------------------------------------------
- * The initial state of the Architectural feature trap register
- * (CPTR_EL3) is unknown and it must be set to a known state. All
- * feature traps are disabled. Some bits in this register are marked as
- * Reserved and should not be modified.
- *
- * CPTR_EL3.TCPAC: This causes a direct access to the CPACR_EL1 from EL1
- * or the CPTR_EL2 from EL2 to trap to EL3 unless it is trapped at EL2.
- * CPTR_EL3.TTA: This causes access to the Trace functionality to trap
- * to EL3 when executed from EL0, EL1, EL2, or EL3. If system register
- * access to trace functionality is not supported, this bit is RES0.
- * CPTR_EL3.TFP: This causes instructions that access the registers
- * associated with Floating Point and Advanced SIMD execution to trap
- * to EL3 when executed from any exception level, unless trapped to EL1
- * or EL2.
- * ---------------------------------------------------------------------
- */
- mrs x1, cptr_el3
- bic w1, w1, #TCPAC_BIT
- bic w1, w1, #TTA_BIT
- bic w1, w1, #TFP_BIT
- msr cptr_el3, x1
-
/* --------------------------------------------------
* Get secure world's entry point and jump to it
* --------------------------------------------------
diff --git a/plat/nvidia/tegra/common/drivers/bpmp/bpmp.c b/plat/nvidia/tegra/common/drivers/bpmp/bpmp.c
index 96e3667..1c5d2e1 100644
--- a/plat/nvidia/tegra/common/drivers/bpmp/bpmp.c
+++ b/plat/nvidia/tegra/common/drivers/bpmp/bpmp.c
@@ -16,7 +16,7 @@
#include <string.h>
#include <tegra_def.h>
-#define BPMP_TIMEOUT_10US 10
+#define BPMP_TIMEOUT 2
static uint32_t channel_base[NR_CHANNELS];
static uint32_t bpmp_init_state = BPMP_INIT_PENDING;
@@ -58,15 +58,15 @@
if (bpmp_init_state == BPMP_INIT_COMPLETE) {
/* loop until BPMP is free */
- for (timeout = 0; timeout < BPMP_TIMEOUT_10US; timeout++) {
+ for (timeout = 0; timeout < BPMP_TIMEOUT; timeout++) {
if (master_free(ch) == true) {
break;
}
- udelay(1);
+ mdelay(1);
}
- if (timeout != BPMP_TIMEOUT_10US) {
+ if (timeout != BPMP_TIMEOUT) {
/* generate the command struct */
p->code = mrq;
@@ -76,18 +76,18 @@
/* signal command ready to the BPMP */
signal_slave(ch);
mmio_write_32(TEGRA_PRI_ICTLR_BASE + CPU_IEP_FIR_SET,
- (1UL << INT_SHR_SEM_OUTBOX_FULL));
+ (1U << INT_SHR_SEM_OUTBOX_FULL));
/* loop until the command is executed */
- for (timeout = 0; timeout < BPMP_TIMEOUT_10US; timeout++) {
+ for (timeout = 0; timeout < BPMP_TIMEOUT; timeout++) {
if (master_acked(ch) == true) {
break;
}
- udelay(1);
+ mdelay(1);
}
- if (timeout != BPMP_TIMEOUT_10US) {
+ if (timeout != BPMP_TIMEOUT) {
/* get the command response */
(void)memcpy(ib_data, (const void *)p->data,
@@ -106,8 +106,8 @@
ret = -EINVAL;
}
- if (timeout == BPMP_TIMEOUT_10US) {
- ERROR("Timed out waiting for bpmp's response");
+ if (timeout == BPMP_TIMEOUT) {
+ ERROR("Timed out waiting for bpmp's response\n");
}
return ret;
@@ -125,7 +125,7 @@
val = mmio_read_32(TEGRA_RES_SEMA_BASE + STA_OFFSET);
if (val != SIGN_OF_LIFE) {
ERROR("BPMP precessor not available\n");
- ret = -ENOTSUP;
+ return -ENOTSUP;
}
/* check if clock for the atomics block is enabled */
@@ -154,12 +154,11 @@
channel_base[ch] = mmio_read_32(base);
/* increment result register offset */
- base += 4UL;
+ base += 4U;
}
/* mark state as "initialized" */
- if (ret == 0)
- bpmp_init_state = BPMP_INIT_COMPLETE;
+ 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));
diff --git a/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.c b/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.c
new file mode 100644
index 0000000..7faa2f0
--- /dev/null
+++ b/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <bpmp_ipc.h>
+#include <debug.h>
+#include <delay_timer.h>
+#include <errno.h>
+#include <mmio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <tegra_def.h>
+#include <utils_def.h>
+
+#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();
+ const 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__);
+ ret = -EINVAL;
+ }
+
+ if (ret == 0) {
+
+ /* 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);
+
+ /* signal the slave */
+ tegra_bpmp_signal_slave();
+
+ /* wait for slave to ack */
+ ret = tegra_bpmp_wait_for_slave_ack();
+ if (ret != 0) {
+ ERROR("failed waiting for the slave to ack\n");
+ }
+
+ /* retrieve the response frame */
+ if ((size_in <= IVC_DATA_SZ_BYTES) && (p_in != NULL) &&
+ (ret == 0)) {
+
+ f_in = tegra_bpmp_get_cur_in_frame();
+ if (f_in != NULL) {
+ ERROR("Failed to get next input frame!\n");
+ } else {
+ (void)memcpy(p_in, p_fdata, (size_t)size_in);
+ }
+ }
+
+ if (ret == 0) {
+ ret = tegra_bpmp_free_master();
+ if (ret != 0) {
+ ERROR("Failed to free master\n");
+ }
+ }
+ }
+
+ 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;
+
+ /* 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__);
+
+ msg_size = tegra_ivc_align(IVC_CMD_SZ_BYTES);
+ frame_size = (uint32_t)tegra_ivc_total_queue_size(msg_size);
+ if (frame_size > TEGRA_BPMP_IPC_CH_MAP_SIZE) {
+ ERROR("%s: carveout size is not sufficient\n", __func__);
+ return -EINVAL;
+ }
+
+ error = tegra_ivc_init(&ivc_ccplex_bpmp_channel,
+ (uint32_t)TEGRA_BPMP_IPC_RX_PHYS_BASE,
+ (uint32_t)TEGRA_BPMP_IPC_TX_PHYS_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;
+}
diff --git a/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.h b/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.h
new file mode 100644
index 0000000..689f8bb
--- /dev/null
+++ b/plat/nvidia/tegra/common/drivers/bpmp_ipc/intf.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef INTF_H
+#define 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 code to issue a module reset command to BPMP
+ */
+#define MRQ_RESET U(20)
+
+/**
+ * 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;
+};
+
+#endif /* INTF_H */
diff --git a/plat/nvidia/tegra/common/drivers/bpmp_ipc/ivc.c b/plat/nvidia/tegra/common/drivers/bpmp_ipc/ivc.c
new file mode 100644
index 0000000..4212eca
--- /dev/null
+++ b/plat/nvidia/tegra/common/drivers/bpmp_ipc/ivc.c
@@ -0,0 +1,653 @@
+/*
+ * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch_helpers.h>
+#include <assert.h>
+#include <debug.h>
+#include <errno.h>
+#include <stddef.h>
+#include <string.h>
+
+#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 <none>
+ * 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 <none>
+ * EST ACK <none>
+ * 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/plat/nvidia/tegra/common/drivers/bpmp_ipc/ivc.h b/plat/nvidia/tegra/common/drivers/bpmp_ipc/ivc.h
new file mode 100644
index 0000000..f34d6cf
--- /dev/null
+++ b/plat/nvidia/tegra/common/drivers/bpmp_ipc/ivc.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef IVC_H
+#define IVC_H
+
+#include <stdint.h>
+#include <stddef.h>
+#include <utils_def.h>
+
+#define IVC_ALIGN U(64)
+#define IVC_CHHDR_TX_FIELDS U(16)
+#define IVC_CHHDR_RX_FIELDS U(16)
+
+struct ivc;
+struct ivc_channel_header;
+
+/* callback handler for notify on receiving a response */
+typedef void (* ivc_notify_function)(const struct ivc *);
+
+struct ivc {
+ struct ivc_channel_header *rx_channel;
+ struct ivc_channel_header *tx_channel;
+ uint32_t w_pos;
+ uint32_t r_pos;
+ ivc_notify_function notify;
+ uint32_t nframes;
+ uint32_t frame_size;
+};
+
+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 /* IVC_H */
diff --git a/plat/nvidia/tegra/common/drivers/gpcdma/gpcdma.c b/plat/nvidia/tegra/common/drivers/gpcdma/gpcdma.c
new file mode 100644
index 0000000..64e84ac
--- /dev/null
+++ b/plat/nvidia/tegra/common/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 <arch_helpers.h>
+#include <common/debug.h>
+#include <delay_timer.h>
+#include <errno.h>
+#include <gpcdma.h>
+#include <mmio.h>
+#include <platform_def.h>
+#include <stdbool.h>
+#include <tegra_def.h>
+#include <utils_def.h>
+
+/* 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/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v1.c b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v1.c
index 58f49d0..92fa273 100644
--- a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v1.c
+++ b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v1.c
@@ -109,13 +109,16 @@
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.
*/
- mmap_add_dynamic_region(non_overlap_area_start, /* PA */
+ 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); /* 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);
@@ -206,3 +209,16 @@
/* 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/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c
index de431b7..a3ef5e1 100644
--- a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c
+++ b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c
@@ -25,316 +25,15 @@
static uint64_t video_mem_base;
static uint64_t video_mem_size_mb;
-static void tegra_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 |
-#if ENABLE_AFI_DEVICE
- MC_CLIENT_HOTRESET_CTRL0_AFI_FLUSH_ENB |
-#endif
- 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
- */
-#if ENABLE_AFI_DEVICE
- mc_set_tsa_passthrough(AFIW);
-#endif
- 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 &
-#if ENABLE_AFI_DEVICE
- mc_set_pcfifo_unordered_boot_so_mss(1, AFIW) &
-#endif
- 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
-}
+/*
+ * The following platform setup functions are weakly defined. They
+ * provide typical implementations that will be overridden by a SoC.
+ */
+#pragma weak plat_memctrl_tzdram_setup
-static void tegra_memctrl_set_overrides(void)
+void plat_memctrl_tzdram_setup(uint64_t phys_base, uint64_t size_in_bytes)
{
- tegra_mc_settings_t *plat_mc_settings = tegra_get_mc_settings();
- const mc_txn_override_cfg_t *mc_txn_override_cfgs;
- uint32_t num_txn_override_cfgs;
- uint32_t i, val;
-
- /* Get the settings from the platform */
- assert(plat_mc_settings);
- mc_txn_override_cfgs = plat_mc_settings->txn_override_cfg;
- num_txn_override_cfgs = plat_mc_settings->num_txn_override_cfgs;
-
- /*
- * 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() == 1)))) {
-
- /*
- * GPU and NVENC settings for Tegra186 simulation and
- * Silicon rev. A01
- */
- val = tegra_mc_read_32(MC_TXN_OVERRIDE_CONFIG_GPUSWR);
- val &= ~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 &= ~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 &= ~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 < num_txn_override_cfgs; i++) {
- val = tegra_mc_read_32(mc_txn_override_cfgs[i].offset);
- val &= ~MC_TXN_OVERRIDE_CGID_TAG_MASK;
- tegra_mc_write_32(mc_txn_override_cfgs[i].offset,
- val | mc_txn_override_cfgs[i].cgid_tag);
- }
- }
+ ; /* do nothing */
}
/*
@@ -347,17 +46,16 @@
uint32_t num_streamid_override_regs;
const mc_streamid_security_cfg_t *mc_streamid_sec_cfgs;
uint32_t num_streamid_sec_cfgs;
- tegra_mc_settings_t *plat_mc_settings = tegra_get_mc_settings();
+ const tegra_mc_settings_t *plat_mc_settings = tegra_get_mc_settings();
uint32_t i;
INFO("Tegra Memory Controller (v2)\n");
-#if ENABLE_SMMU_DEVICE
/* Program the SMMU pagesize */
tegra_smmu_init();
-#endif
+
/* Get the settings from the platform */
- assert(plat_mc_settings);
+ assert(plat_mc_settings != NULL);
mc_streamid_override_regs = plat_mc_settings->streamid_override_cfg;
num_streamid_override_regs = plat_mc_settings->num_streamid_override_cfgs;
mc_streamid_sec_cfgs = plat_mc_settings->streamid_security_cfg;
@@ -398,10 +96,14 @@
* boots with MSS having all control, but ROC provides a performance
* boost as compared to MSS.
*/
- tegra_memctrl_reconfig_mss_clients();
+ if (plat_mc_settings->reconfig_mss_clients != NULL) {
+ plat_mc_settings->reconfig_mss_clients();
+ }
/* Program overrides for MC transactions */
- tegra_memctrl_set_overrides();
+ if (plat_mc_settings->set_txn_overrides != NULL) {
+ plat_mc_settings->set_txn_overrides();
+ }
}
/*
@@ -409,19 +111,27 @@
*/
void tegra_memctrl_restore_settings(void)
{
+ const tegra_mc_settings_t *plat_mc_settings = tegra_get_mc_settings();
+
+ assert(plat_mc_settings != NULL);
+
/*
* Re-configure MSS to allow ROC to deal with ordering of the
* Memory Controller traffic. This is needed as the Memory Controller
* resets during System Suspend with MSS having all control, but ROC
* provides a performance boost as compared to MSS.
*/
- tegra_memctrl_reconfig_mss_clients();
+ if (plat_mc_settings->reconfig_mss_clients != NULL) {
+ plat_mc_settings->reconfig_mss_clients();
+ }
/* Program overrides for MC transactions */
- tegra_memctrl_set_overrides();
+ if (plat_mc_settings->set_txn_overrides != NULL) {
+ plat_mc_settings->set_txn_overrides();
+ }
/* video memory carveout region */
- if (video_mem_base) {
+ if (video_mem_base != 0ULL) {
tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO,
(uint32_t)video_mem_base);
tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI,
@@ -445,34 +155,9 @@
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, (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 enabled,
- * We need setup TZDRAM before CPU to access TZ Carveout,
- * otherwise CPU will fetch non-decrypted data.
- * So save TZDRAM setting for retore by SC7 resume FW.
- */
-
- mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV55_LO,
- tegra_mc_read_32(MC_SECURITY_CFG0_0));
- mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV55_HI,
- tegra_mc_read_32(MC_SECURITY_CFG3_0));
- mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV54_HI,
- tegra_mc_read_32(MC_SECURITY_CFG1_0));
-
- /*
- * MCE propagates the security configuration values across the
- * CCPLEX.
+ * Perform platform specific steps.
*/
- mce_update_gsc_tzdram();
+ plat_memctrl_tzdram_setup(phys_base, size_in_bytes);
}
/*
@@ -494,13 +179,22 @@
* Reset the access configuration registers to restrict access
* to the TZRAM aperture
*/
- for (index = MC_TZRAM_CLIENT_ACCESS_CFG0;
+ for (index = MC_TZRAM_CLIENT_ACCESS0_CFG0;
index < ((uint32_t)MC_TZRAM_CARVEOUT_CFG + (uint32_t)MC_GSC_CONFIG_REGS_SIZE);
index += 4U) {
tegra_mc_write_32(index, 0);
}
/*
+ * Enable CPU access configuration registers to access the TZRAM aperture
+ */
+ if (!tegra_chipid_is_t186()) {
+ val = tegra_mc_read_32(MC_TZRAM_CLIENT_ACCESS1_CFG0);
+ val |= TZRAM_ALLOW_MPCORER | TZRAM_ALLOW_MPCOREW;
+ tegra_mc_write_32(MC_TZRAM_CLIENT_ACCESS1_CFG0, val);
+ }
+
+ /*
* Set the TZRAM base. TZRAM base must be 4k aligned, at least.
*/
assert((phys_base & (uint64_t)0xFFF) == 0U);
@@ -525,8 +219,11 @@
* at all.
*/
val = tegra_mc_read_32(MC_TZRAM_CARVEOUT_CFG);
- val &= ~MC_GSC_ENABLE_TZ_LOCK_BIT;
+ val &= (uint32_t)~MC_GSC_ENABLE_TZ_LOCK_BIT;
val |= MC_GSC_LOCK_CFG_SETTINGS_BIT;
+ if (!tegra_chipid_is_t186()) {
+ val |= MC_GSC_ENABLE_CPU_SECURE_BIT;
+ }
tegra_mc_write_32(MC_TZRAM_CARVEOUT_CFG, val);
/*
@@ -600,18 +297,21 @@
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.
*/
- mmap_add_dynamic_region(non_overlap_area_start, /* PA */
+ 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); /* attrs */
+ assert(ret == 0);
zero_normalmem((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,
+ (void)mmap_remove_dynamic_region(non_overlap_area_start,
non_overlap_area_size);
}
@@ -658,17 +358,19 @@
*/
INFO("Cleaning previous Video Memory Carveout\n");
- if (phys_base > vmem_end_old || video_mem_base > vmem_end_new) {
+ if ((phys_base > vmem_end_old) || (video_mem_base > vmem_end_new)) {
tegra_clear_videomem(video_mem_base,
- (uint64_t)video_mem_size_mb << 20);
+ (uint32_t)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);
+ tegra_clear_videomem(video_mem_base,
+ (uint32_t)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);
+ tegra_clear_videomem(vmem_end_new,
+ (uint32_t)non_overlap_area_size);
}
}
@@ -700,3 +402,8 @@
{
; /* do nothing */
}
+
+void tegra_memctrl_clear_pending_interrupts(void)
+{
+ ; /* do nothing */
+}
diff --git a/plat/nvidia/tegra/common/drivers/smmu/smmu.c b/plat/nvidia/tegra/common/drivers/smmu/smmu.c
index 610f32f..8c1b899 100644
--- a/plat/nvidia/tegra/common/drivers/smmu/smmu.c
+++ b/plat/nvidia/tegra/common/drivers/smmu/smmu.c
@@ -19,47 +19,55 @@
/* SMMU IDs currently supported by the driver */
enum {
- TEGRA_SMMU0,
+ TEGRA_SMMU0 = 0U,
TEGRA_SMMU1,
TEGRA_SMMU2
};
static 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)
- return mmio_read_32(TEGRA_SMMU0_BASE + off);
+ 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)
- return mmio_read_32(TEGRA_SMMU1_BASE + off);
+ 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)
- return mmio_read_32(TEGRA_SMMU2_BASE + off);
+ if (smmu_id == TEGRA_SMMU2) {
+ ret = mmio_read_32(TEGRA_SMMU2_BASE + (uint64_t)off);
+ }
#endif
- return 0;
+ return ret;
}
static 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 + off, val);
+ 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 + off, val);
+ 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 + off, val);
+ if (smmu_id == TEGRA_SMMU2) {
+ mmio_write_32(TEGRA_SMMU2_BASE + (uint64_t)off, val);
+ }
#endif
}
@@ -70,52 +78,55 @@
{
uint32_t i, num_entries = 0;
smmu_regs_t *smmu_ctx_regs;
- plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
+ 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;
uint32_t reg_id1, pgshift, cb_size;
/* sanity check SMMU settings c*/
reg_id1 = mmio_read_32((TEGRA_SMMU0_BASE + SMMU_GNSR0_IDR1));
- pgshift = (reg_id1 & ID1_PAGESIZE) ? 16 : 12;
- cb_size = (2 << pgshift) * \
- (1 << (((reg_id1 >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + 1));
+ pgshift = ((reg_id1 & ID1_PAGESIZE) != 0U) ? 16U : 12U;
+ cb_size = ((uint32_t)2 << pgshift) * \
+ ((uint32_t)1 << (((reg_id1 >> ID1_NUMPAGENDXB_SHIFT) & ID1_NUMPAGENDXB_MASK) + 1U));
assert(!((pgshift != PGSHIFT) || (cb_size != CB_SIZE)));
assert((smmu_ctx_addr >= tzdram_base) && (smmu_ctx_addr <= tzdram_end));
/* get SMMU context table */
smmu_ctx_regs = plat_get_smmu_ctx();
- assert(smmu_ctx_regs);
+ assert(smmu_ctx_regs != NULL);
/*
* smmu_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 (smmu_ctx_regs[num_entries].val != 0xFFFFFFFFU) {
+ while ((smmu_ctx_regs[num_entries].reg != 0xFFFFFFFFU)) {
num_entries++;
}
/* panic if the sizes do not match */
- if (num_entries != smmu_ctx_regs[0].val)
+ if (num_entries != smmu_ctx_regs[0].val) {
+ ERROR("SMMU context size mismatch!");
panic();
+ }
/* save SMMU register values */
- for (i = 1; i < num_entries; i++)
+ for (i = 1U; i < num_entries; i++) {
smmu_ctx_regs[i].val = mmio_read_32(smmu_ctx_regs[i].reg);
+ }
/* increment by 1 to take care of the last entry */
num_entries++;
/* Save SMMU config settings */
- memcpy16((void *)(uintptr_t)smmu_ctx_addr, (void *)smmu_ctx_regs,
- (sizeof(smmu_regs_t) * num_entries));
+ (void)memcpy16((uint8_t *)smmu_ctx_addr, (uint8_t *)smmu_ctx_regs,
+ (sizeof(smmu_regs_t) * num_entries));
/* save the SMMU table address */
- mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV11_LO,
+ mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_SMMU_TABLE_ADDR_LO,
(uint32_t)smmu_ctx_addr);
- mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV11_HI,
+ mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_SMMU_TABLE_ADDR_HI,
(uint32_t)(smmu_ctx_addr >> 32));
}
@@ -128,17 +139,18 @@
void tegra_smmu_init(void)
{
uint32_t val, cb_idx, smmu_id, ctx_base;
+ uint32_t smmu_counter = plat_get_num_smmu_devices();
- for (smmu_id = 0; smmu_id < NUM_SMMU_DEVICES; smmu_id++) {
+ for (smmu_id = 0U; smmu_id < smmu_counter; 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 &= ~SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
+ 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 &= ~SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
+ 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 */
@@ -147,19 +159,19 @@
for (cb_idx = 0; 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 &= ~SMMU_CBn_ACTLR_CPRE_BIT;
+ 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 |= SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
+ 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 |= SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
+ val |= (uint32_t)SMMU_ACR_CACHE_LOCK_ENABLE_BIT;
tegra_smmu_write_32(smmu_id, SMMU_GSR0_SECURE_ACR, val);
}
}
diff --git a/plat/nvidia/tegra/common/drivers/spe/shared_console.S b/plat/nvidia/tegra/common/drivers/spe/shared_console.S
new file mode 100644
index 0000000..a9f0334
--- /dev/null
+++ b/plat/nvidia/tegra/common/drivers/spe/shared_console.S
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+#include <asm_macros.S>
+
+#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_WRITE (CONSOLE_RING_DOORBELL | CONSOLE_FLUSH_DATA_TO_PORT)
+
+ /*
+ * 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_core_init
+ .globl console_core_putc
+ .globl console_core_getc
+ .globl console_core_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: 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
+ * -----------------------------------------------
+ */
+func console_core_init
+ /* Check the input base address */
+ cbz x0, core_init_fail
+ mov w0, #1
+ ret
+core_init_fail:
+ mov w0, wzr
+ ret
+endfunc console_core_init
+
+ /* --------------------------------------------------------
+ * 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 : 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
+
+ /* wait until spe is ready */
+1: ldr w2, [x1]
+ and w2, w2, #CONSOLE_IS_BUSY
+ cbnz w2, 1b
+
+ /* spe is ready */
+ mov w2, w0
+ and w2, w2, #0xFF
+ mov w3, #(CONSOLE_WRITE | (1 << CONSOLE_NUM_BYTES_SHIFT))
+ orr w2, w2, w3
+ str w2, [x1]
+
+ ret
+putc_error:
+ mov w0, #-1
+ ret
+endfunc console_core_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 : x0 - console base address
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func console_core_getc
+ mov w0, #-1
+ ret
+endfunc console_core_getc
+
+ /* ---------------------------------------------
+ * int 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 : return -1 on error else return 0.
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func console_core_flush
+ cbz x0, flush_error
+
+ /* flush console */
+ mov w1, #CONSOLE_WRITE
+ str w1, [x0]
+ mov w0, #0
+ ret
+flush_error:
+ mov w0, #-1
+ ret
+endfunc console_core_flush
diff --git a/plat/nvidia/tegra/common/lib/debug/profiler.c b/plat/nvidia/tegra/common/lib/debug/profiler.c
new file mode 100644
index 0000000..d4c3f95
--- /dev/null
+++ b/plat/nvidia/tegra/common/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 <arch.h>
+#include <arch_helpers.h>
+#include <assert.h>
+#include <mmio.h>
+#include <profiler.h>
+#include <stdbool.h>
+#include <string.h>
+#include <utils_def.h>
+#include <xlat_tables_v2.h>
+
+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/plat/nvidia/tegra/common/tegra_bl31_setup.c b/plat/nvidia/tegra/common/tegra_bl31_setup.c
index 0806307..908e4f2 100644
--- a/plat/nvidia/tegra/common/tegra_bl31_setup.c
+++ b/plat/nvidia/tegra/common/tegra_bl31_setup.c
@@ -26,6 +26,7 @@
#include <plat/common/platform.h>
#include <memctrl.h>
+#include <profiler.h>
#include <tegra_def.h>
#include <tegra_platform.h>
#include <tegra_private.h>
@@ -40,20 +41,19 @@
* of trusted SRAM
******************************************************************************/
-IMPORT_SYM(unsigned long, __RW_START__, BL31_RW_START);
-IMPORT_SYM(unsigned long, __RW_END__, BL31_RW_END);
-IMPORT_SYM(unsigned long, __RODATA_START__, BL31_RODATA_BASE);
-IMPORT_SYM(unsigned long, __RODATA_END__, BL31_RODATA_END);
-IMPORT_SYM(unsigned long, __TEXT_START__, TEXT_START);
-IMPORT_SYM(unsigned long, __TEXT_END__, TEXT_END);
+IMPORT_SYM(uint64_t, __RW_START__, BL31_RW_START);
+IMPORT_SYM(uint64_t, __RW_END__, BL31_RW_END);
+IMPORT_SYM(uint64_t, __RODATA_START__, BL31_RODATA_BASE);
+IMPORT_SYM(uint64_t, __RODATA_END__, BL31_RODATA_END);
+IMPORT_SYM(uint64_t, __TEXT_START__, TEXT_START);
+IMPORT_SYM(uint64_t, __TEXT_END__, TEXT_END);
extern uint64_t tegra_bl31_phys_base;
extern uint64_t tegra_console_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 = (uint64_t)TZDRAM_SIZE
+ .tzdram_size = TZDRAM_SIZE
};
static unsigned long bl32_mem_size;
static unsigned long bl32_boot_params;
@@ -70,6 +70,7 @@
#pragma weak plat_early_platform_setup
#pragma weak plat_get_bl31_params
#pragma weak plat_get_bl31_plat_params
+#pragma weak plat_late_platform_setup
void plat_early_platform_setup(void)
{
@@ -86,6 +87,11 @@
return NULL;
}
+void plat_late_platform_setup(void)
+{
+ ; /* do nothing */
+}
+
/*******************************************************************************
* 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
@@ -93,14 +99,16 @@
******************************************************************************/
entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
{
- if (type == NON_SECURE)
- return &bl33_image_ep_info;
+ entry_point_info_t *ep = NULL;
/* return BL32 entry point info if it is valid */
- if (type == SECURE && bl32_image_ep_info.pc)
- return &bl32_image_ep_info;
+ 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 NULL;
+ return ep;
}
/*******************************************************************************
@@ -124,6 +132,7 @@
image_info_t bl32_img_info = { {0} };
uint64_t tzdram_start, tzdram_end, bl32_start, bl32_end;
uint32_t console_clock;
+ int32_t ret;
/*
* For RESET_TO_BL31 systems, BL31 is the first bootloader to run so
@@ -131,20 +140,22 @@
* might use custom ways to get arguments, so provide handlers which
* they can override.
*/
- if (arg_from_bl2 == NULL)
+ if (arg_from_bl2 == NULL) {
arg_from_bl2 = plat_get_bl31_params();
- if (plat_params == NULL)
+ }
+ 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);
- assert(arg_from_bl2->bl33_ep_info);
+ 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) {
+ if (arg_from_bl2->bl32_ep_info != NULL) {
bl32_image_ep_info = *arg_from_bl2->bl32_ep_info;
bl32_mem_size = arg_from_bl2->bl32_ep_info->args.arg0;
bl32_boot_params = arg_from_bl2->bl32_ep_info->args.arg2;
@@ -153,7 +164,7 @@
/*
* Parse platform specific parameters - TZDRAM aperture base and size
*/
- assert(plat_params);
+ 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;
@@ -163,14 +174,15 @@
* It is very important that we run either from TZDRAM or TZSRAM base.
* Add an explicit check here.
*/
- if ((plat_bl31_params_from_bl2.tzdram_base != BL31_BASE) &&
- (TEGRA_TZRAM_BASE != BL31_BASE))
+ if ((plat_bl31_params_from_bl2.tzdram_base != (uint64_t)BL31_BASE) &&
+ (TEGRA_TZRAM_BASE != BL31_BASE)) {
panic();
+ }
/*
* Reference clock used by the FPGAs is a lot slower.
*/
- if (tegra_platform_is_fpga() == 1U) {
+ if (tegra_platform_is_fpga()) {
console_clock = TEGRA_BOOT_UART_CLK_13_MHZ;
} else {
console_clock = TEGRA_BOOT_UART_CLK_408_MHZ;
@@ -182,31 +194,60 @@
*/
tegra_console_base = plat_get_console_from_id(plat_params->uart_id);
- if (tegra_console_base != (uint64_t)0) {
+ if (tegra_console_base != 0U) {
/*
* Configure the UART port to be used as the console
*/
- console_init(tegra_console_base, console_clock,
+ (void)console_init(tegra_console_base, console_clock,
TEGRA_CONSOLE_BAUDRATE);
}
/*
+ * The previous bootloader passes the base address of the shared memory
+ * location to store the boot profiler logs. Sanity check the
+ * address and initilise the profiler library, if it looks ok.
+ */
+ if (plat_params->boot_profiler_shmem_base != 0ULL) {
+
+ 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();
+
/*
* Do initial security configuration to allow DRAM/device access.
*/
tegra_memctrl_tzdram_setup(plat_bl31_params_from_bl2.tzdram_base,
- plat_bl31_params_from_bl2.tzdram_size);
+ (uint32_t)plat_bl31_params_from_bl2.tzdram_size);
/*
* The previous bootloader might not have placed the BL32 image
* inside the TZDRAM. We check the BL32 image info to find out
* the base/PC values and relocate the image if necessary.
*/
- if (arg_from_bl2->bl32_image_info) {
+ if (arg_from_bl2->bl32_image_info != NULL) {
bl32_img_info = *arg_from_bl2->bl32_image_info;
@@ -223,11 +264,11 @@
assert(bl32_image_ep_info.pc < tzdram_end);
/* relocate BL32 */
- if (bl32_start >= tzdram_end || bl32_end <= tzdram_start) {
+ if ((bl32_start >= tzdram_end) || (bl32_end <= tzdram_start)) {
INFO("Relocate BL32 to TZDRAM\n");
- memcpy16((void *)(uintptr_t)bl32_image_ep_info.pc,
+ (void)memcpy16((void *)(uintptr_t)bl32_image_ep_info.pc,
(void *)(uintptr_t)bl32_start,
bl32_img_info.image_size);
@@ -237,8 +278,10 @@
}
}
- /* 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)
@@ -256,6 +299,9 @@
if (args->arg4 != 0U) {
args->arg2 = args->arg4;
}
+
+ /* Profiler Carveout Base */
+ args->arg3 = args->arg5;
}
#endif
@@ -264,7 +310,10 @@
******************************************************************************/
void bl31_platform_setup(void)
{
- uint32_t tmp_reg;
+ /*
+ * Add timestamp for platform setup entry.
+ */
+ boot_profiler_add_record("[TF] plat setup entry");
/* Initialize the gic cpu and distributor interfaces */
plat_gic_setup();
@@ -285,9 +334,17 @@
*/
tegra_memctrl_tzram_setup(TEGRA_TZRAM_BASE, TEGRA_TZRAM_SIZE);
- /* Set the next EL to be AArch64 */
- tmp_reg = SCR_RES1_BITS | SCR_RW_BIT;
- write_scr(tmp_reg);
+ /*
+ * 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");
}
@@ -298,6 +355,15 @@
void bl31_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
@@ -307,6 +373,12 @@
* disabled before we jump to the non-secure world.
*/
tegra_memctrl_disable_ahb_redirection();
+
+ /*
+ * Add final timestamp before exiting BL31.
+ */
+ boot_profiler_add_record("[TF] bl31 exit");
+ boot_profiler_deinit();
}
/*******************************************************************************
@@ -315,17 +387,22 @@
******************************************************************************/
void bl31_plat_arch_setup(void)
{
- unsigned long rw_start = BL31_RW_START;
- unsigned long rw_size = BL31_RW_END - BL31_RW_START;
- unsigned long rodata_start = BL31_RODATA_BASE;
- unsigned long rodata_size = BL31_RODATA_END - BL31_RODATA_BASE;
- unsigned long code_base = TEXT_START;
- unsigned long code_size = TEXT_END - TEXT_START;
+ uint64_t rw_start = BL31_RW_START;
+ uint64_t rw_size = BL31_RW_END - BL31_RW_START;
+ uint64_t rodata_start = BL31_RODATA_BASE;
+ uint64_t rodata_size = BL31_RODATA_END - BL31_RODATA_BASE;
+ uint64_t code_base = TEXT_START;
+ uint64_t code_size = TEXT_END - TEXT_START;
const mmap_region_t *plat_mmio_map = NULL;
#if USE_COHERENT_MEM
- unsigned long coh_start, coh_size;
+ uint32_t coh_start, coh_size;
#endif
- plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
+ const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
+
+ /*
+ * Add timestamp for arch setup entry.
+ */
+ boot_profiler_add_record("[TF] arch setup entry");
/* add memory regions */
mmap_add_region(rw_start, rw_start,
@@ -352,21 +429,22 @@
mmap_add_region(coh_start, coh_start,
coh_size,
- MT_DEVICE | MT_RW | MT_SECURE);
+ (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE);
#endif
/* map on-chip free running uS timer */
- mmap_add_region(page_align((uint64_t)TEGRA_TMRUS_BASE, 0),
- page_align((uint64_t)TEGRA_TMRUS_BASE, 0),
- (uint64_t)TEGRA_TMRUS_SIZE,
- MT_DEVICE | MT_RO | MT_SECURE);
+ mmap_add_region(page_align(TEGRA_TMRUS_BASE, 0),
+ page_align(TEGRA_TMRUS_BASE, 0),
+ TEGRA_TMRUS_SIZE,
+ (uint8_t)MT_DEVICE | (uint8_t)MT_RO | (uint8_t)MT_SECURE);
/* add MMIO space */
plat_mmio_map = plat_get_mmio_map();
- if (plat_mmio_map)
+ if (plat_mmio_map != NULL) {
mmap_add(plat_mmio_map);
- else
+ } else {
WARN("MMIO map not available\n");
+ }
/* set up translation tables */
init_xlat_tables();
@@ -374,33 +452,41 @@
/* 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
******************************************************************************/
-int bl31_check_ns_address(uint64_t base, uint64_t size_in_bytes)
+int32_t bl31_check_ns_address(uint64_t base, uint64_t size_in_bytes)
{
- uint64_t end = base + size_in_bytes;
+ uint64_t end = base + size_in_bytes - U(1);
+ int32_t ret = 0;
/*
* Check if the NS DRAM address is valid
*/
- if ((base < TEGRA_DRAM_BASE) || (end > TEGRA_DRAM_END)) {
+ if ((base < TEGRA_DRAM_BASE) || (base >= TEGRA_DRAM_END) ||
+ (end > TEGRA_DRAM_END)) {
+
ERROR("NS address is out-of-bounds!\n");
- return -EFAULT;
+ ret = -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 < TZDRAM_END) && (end > tegra_bl31_phys_base)) {
+ if ((base < (uint64_t)TZDRAM_END) && (end > tegra_bl31_phys_base)) {
ERROR("NS address overlaps TZDRAM!\n");
- return -ENOTSUP;
+ ret = -ENOTSUP;
}
/* valid NS address */
- return 0;
+ return ret;
}
diff --git a/plat/nvidia/tegra/common/tegra_common.mk b/plat/nvidia/tegra/common/tegra_common.mk
index 6a0854e..d9eec4d 100644
--- a/plat/nvidia/tegra/common/tegra_common.mk
+++ b/plat/nvidia/tegra/common/tegra_common.mk
@@ -5,6 +5,7 @@
#
PLAT_INCLUDES := -Iplat/nvidia/tegra/include/drivers \
+ -Iplat/nvidia/tegra/include/lib \
-Iplat/nvidia/tegra/include \
-Iplat/nvidia/tegra/include/${TARGET_SOC}
@@ -21,10 +22,10 @@
BL31_SOURCES += drivers/console/aarch64/console.S \
drivers/delay_timer/delay_timer.c \
- drivers/ti/uart/aarch64/16550_console.S \
${TEGRA_GICv2_SOURCES} \
${COMMON_DIR}/aarch64/tegra_helpers.S \
${COMMON_DIR}/drivers/pmc/pmc.c \
+ ${COMMON_DIR}/lib/debug/profiler.c \
${COMMON_DIR}/tegra_bl31_setup.c \
${COMMON_DIR}/tegra_delay_timer.c \
${COMMON_DIR}/tegra_fiq_glue.c \
diff --git a/plat/nvidia/tegra/common/tegra_fiq_glue.c b/plat/nvidia/tegra/common/tegra_fiq_glue.c
index 9a43f76..cab2e5e 100644
--- a/plat/nvidia/tegra/common/tegra_fiq_glue.c
+++ b/plat/nvidia/tegra/common/tegra_fiq_glue.c
@@ -65,7 +65,7 @@
* Set the new ELR to continue execution in the NS world using the
* FIQ handler registered earlier.
*/
- assert(ns_fiq_handler_addr);
+ assert(ns_fiq_handler_addr != 0ULL);
write_ctx_reg((el3state_ctx), (uint32_t)(CTX_ELR_EL3), (ns_fiq_handler_addr));
/*
diff --git a/plat/nvidia/tegra/common/tegra_platform.c b/plat/nvidia/tegra/common/tegra_platform.c
index 72da126..c1e4209 100644
--- a/plat/nvidia/tegra/common/tegra_platform.c
+++ b/plat/nvidia/tegra/common/tegra_platform.c
@@ -15,7 +15,7 @@
* Tegra platforms
******************************************************************************/
typedef enum tegra_platform {
- TEGRA_PLATFORM_SILICON = 0,
+ TEGRA_PLATFORM_SILICON = 0U,
TEGRA_PLATFORM_QT,
TEGRA_PLATFORM_FPGA,
TEGRA_PLATFORM_EMULATION,
@@ -83,7 +83,7 @@
{
uint32_t chip_id = ((tegra_get_chipid() >> CHIP_ID_SHIFT) & CHIP_ID_MASK);
- return (chip_id == (uint32_t)TEGRA_CHIPID_TEGRA13);
+ return (chip_id == TEGRA_CHIPID_TEGRA13);
}
bool tegra_chipid_is_t186(void)
@@ -97,12 +97,12 @@
{
uint32_t chip_id = (tegra_get_chipid() >> CHIP_ID_SHIFT) & CHIP_ID_MASK;
- return (chip_id == (uint32_t)TEGRA_CHIPID_TEGRA21);
+ return (chip_id == TEGRA_CHIPID_TEGRA21);
}
bool tegra_chipid_is_t210_b01(void)
{
- return (tegra_chipid_is_t210() && (tegra_get_chipid_major() == 0x2UL));
+ return (tegra_chipid_is_t210() && (tegra_get_chipid_major() == 0x2U));
}
/*
diff --git a/plat/nvidia/tegra/common/tegra_pm.c b/plat/nvidia/tegra/common/tegra_pm.c
index ce44983..2805272 100644
--- a/plat/nvidia/tegra/common/tegra_pm.c
+++ b/plat/nvidia/tegra/common/tegra_pm.c
@@ -50,37 +50,42 @@
#pragma weak tegra_soc_prepare_system_off
#pragma weak tegra_soc_get_target_pwr_state
-int tegra_soc_pwr_domain_suspend_pwrdown_early(const psci_power_state_t *target_state)
+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_suspend(const psci_power_state_t *target_state)
+int32_t tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
{
+ (void)target_state;
return PSCI_E_NOT_SUPPORTED;
}
-int tegra_soc_pwr_domain_on(u_register_t mpidr)
+int32_t tegra_soc_pwr_domain_on(u_register_t mpidr)
{
+ (void)mpidr;
return PSCI_E_SUCCESS;
}
-int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
+int32_t tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
{
+ (void)target_state;
return PSCI_E_SUCCESS;
}
-int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
+int32_t tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state)
{
+ (void)target_state;
return PSCI_E_SUCCESS;
}
-int tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state)
+int32_t tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state)
{
+ (void)target_state;
return PSCI_E_SUCCESS;
}
-int tegra_soc_prepare_system_reset(void)
+int32_t tegra_soc_prepare_system_reset(void)
{
return PSCI_E_SUCCESS;
}
@@ -91,19 +96,26 @@
panic();
}
-plat_local_state_t tegra_soc_get_target_pwr_state(unsigned int lvl,
+plat_local_state_t tegra_soc_get_target_pwr_state(uint32_t lvl,
const plat_local_state_t *states,
- unsigned int ncpu)
+ uint32_t ncpu)
{
plat_local_state_t target = PLAT_MAX_OFF_STATE, temp;
+ uint32_t num_cpu = ncpu;
+ const plat_local_state_t *local_state = states;
- assert(ncpu);
+ (void)lvl;
+
+ assert(ncpu != 0U);
do {
- temp = *states++;
- if ((temp < target))
+ temp = *local_state;
+ if ((temp < target)) {
target = temp;
- } while (--ncpu);
+ }
+ --num_cpu;
+ local_state++;
+ } while (num_cpu != 0U);
return target;
}
@@ -117,8 +129,9 @@
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++)
+ for (uint32_t i = MPIDR_AFFLVL0; i <= PLAT_MAX_PWR_LVL; i++) {
req_state->pwr_domain_state[i] = PSTATE_ID_SOC_POWERDN;
+ }
}
/*******************************************************************************
@@ -126,6 +139,8 @@
******************************************************************************/
void tegra_cpu_standby(plat_local_state_t cpu_state)
{
+ (void)cpu_state;
+
/*
* Enter standby state
* dsb is good practice before using wfi to enter low power states
@@ -138,7 +153,7 @@
* Handler called when an affinity instance is about to be turned on. The
* level and mpidr determine the affinity instance.
******************************************************************************/
-int tegra_pwr_domain_on(u_register_t mpidr)
+int32_t tegra_pwr_domain_on(u_register_t mpidr)
{
return tegra_soc_pwr_domain_on(mpidr);
}
@@ -149,7 +164,7 @@
******************************************************************************/
void tegra_pwr_domain_off(const psci_power_state_t *target_state)
{
- tegra_soc_pwr_domain_off(target_state);
+ (void)tegra_soc_pwr_domain_off(target_state);
}
/*******************************************************************************
@@ -169,12 +184,13 @@
******************************************************************************/
void tegra_pwr_domain_suspend(const psci_power_state_t *target_state)
{
- tegra_soc_pwr_domain_suspend(target_state);
+ (void)tegra_soc_pwr_domain_suspend(target_state);
/* Disable console if we are entering deep sleep. */
if (target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] ==
- PSTATE_ID_SOC_POWERDN)
- console_uninit();
+ PSTATE_ID_SOC_POWERDN) {
+ (void)console_uninit();
+ }
/* disable GICC */
tegra_gic_cpuif_deactivate();
@@ -191,7 +207,7 @@
uint64_t rmr_el3 = 0;
/* call the chip's power down handler */
- tegra_soc_pwr_domain_power_down_wfi(target_state);
+ (void)tegra_soc_pwr_domain_power_down_wfi(target_state);
/*
* If we are in fake system suspend mode, ensure we start doing
@@ -222,7 +238,7 @@
******************************************************************************/
void tegra_pwr_domain_on_finish(const psci_power_state_t *target_state)
{
- plat_params_from_bl2_t *plat_params;
+ const plat_params_from_bl2_t *plat_params;
uint32_t console_clock;
/*
@@ -239,15 +255,15 @@
/*
* Reference clock used by the FPGAs is a lot slower.
*/
- if (tegra_platform_is_fpga() == 1U) {
+ if (tegra_platform_is_fpga()) {
console_clock = TEGRA_BOOT_UART_CLK_13_MHZ;
} else {
console_clock = TEGRA_BOOT_UART_CLK_408_MHZ;
}
/* Initialize the runtime console */
- if (tegra_console_base != (uint64_t)0) {
- console_init(tegra_console_base, console_clock,
+ if (tegra_console_base != 0ULL) {
+ (void)console_init(tegra_console_base, console_clock,
TEGRA_CONSOLE_BAUDRATE);
}
@@ -262,7 +278,7 @@
*/
plat_params = bl31_get_plat_params();
tegra_memctrl_tzdram_setup(plat_params->tzdram_base,
- plat_params->tzdram_size);
+ (uint32_t)plat_params->tzdram_size);
/*
* Set up the TZRAM memory aperture to allow only secure world
@@ -274,7 +290,7 @@
/*
* Reset hardware settings.
*/
- tegra_soc_pwr_domain_on_finish(target_state);
+ (void)tegra_soc_pwr_domain_on_finish(target_state);
}
/*******************************************************************************
@@ -305,7 +321,7 @@
INFO("Restarting system...\n");
/* per-SoC system reset handler */
- tegra_soc_prepare_system_reset();
+ (void)tegra_soc_prepare_system_reset();
/*
* Program the PMC in order to restart the system.
@@ -316,10 +332,10 @@
/*******************************************************************************
* Handler called to check the validity of the power state parameter.
******************************************************************************/
-int32_t tegra_validate_power_state(unsigned int power_state,
+int32_t tegra_validate_power_state(uint32_t power_state,
psci_power_state_t *req_state)
{
- assert(req_state);
+ assert(req_state != NULL);
return tegra_soc_validate_power_state(power_state, req_state);
}
@@ -327,16 +343,19 @@
/*******************************************************************************
* Platform handler called to check the validity of the non secure entrypoint.
******************************************************************************/
-int tegra_validate_ns_entrypoint(uintptr_t entrypoint)
+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))
- return PSCI_E_SUCCESS;
+ if ((entrypoint >= TEGRA_DRAM_BASE) && (entrypoint <= TEGRA_DRAM_END)) {
+ ret = PSCI_E_SUCCESS;
+ }
- return PSCI_E_INVALID_ADDRESS;
+ return ret;
}
/*******************************************************************************
@@ -376,7 +395,7 @@
/*
* Reset hardware settings.
*/
- tegra_soc_pwr_domain_on_finish(&target_state);
+ (void)tegra_soc_pwr_domain_on_finish(&target_state);
/*
* Initialize PSCI ops struct
diff --git a/plat/nvidia/tegra/common/tegra_sip_calls.c b/plat/nvidia/tegra/common/tegra_sip_calls.c
index e7acece..4955b2f 100644
--- a/plat/nvidia/tegra/common/tegra_sip_calls.c
+++ b/plat/nvidia/tegra/common/tegra_sip_calls.c
@@ -69,7 +69,7 @@
void *handle,
u_register_t flags)
{
- uint32_t regval;
+ uint32_t regval, local_x2_32 = (uint32_t)x2;
int32_t err;
/* Check if this is a SoC specific SiP */
@@ -84,14 +84,11 @@
case TEGRA_SIP_NEW_VIDEOMEM_REGION:
- /* clean up the high bits */
- x2 = (uint32_t)x2;
-
/*
* Check if Video Memory overlaps TZDRAM (contains bl31/bl32)
* or falls outside of the valid DRAM range
*/
- err = bl31_check_ns_address(x1, x2);
+ err = bl31_check_ns_address(x1, local_x2_32);
if (err != 0) {
SMC_RET1(handle, (uint64_t)err);
}
@@ -99,9 +96,9 @@
/*
* Check if Video Memory is aligned to 1MB.
*/
- if (((x1 & 0xFFFFFU) != 0U) || ((x2 & 0xFFFFFU) != 0U)) {
+ if (((x1 & 0xFFFFFU) != 0U) || ((local_x2_32 & 0xFFFFFU) != 0U)) {
ERROR("Unaligned Video Memory base address!\n");
- SMC_RET1(handle, -ENOTSUP);
+ SMC_RET1(handle, (uint64_t)-ENOTSUP);
}
/*
@@ -111,13 +108,13 @@
*/
regval = mmio_read_32(TEGRA_CAR_RESET_BASE +
TEGRA_GPU_RESET_REG_OFFSET);
- if ((regval & GPU_RESET_BIT) == 0UL) {
+ if ((regval & GPU_RESET_BIT) == 0U) {
ERROR("GPU not in reset! Video Memory setup failed\n");
- SMC_RET1(handle, -ENOTSUP);
+ SMC_RET1(handle, (uint64_t)-ENOTSUP);
}
/* new video memory carveout settings */
- tegra_memctrl_videomem_setup(x1, (uint32_t)x2);
+ tegra_memctrl_videomem_setup(x1, local_x2_32);
SMC_RET1(handle, 0);
diff --git a/plat/nvidia/tegra/common/tegra_topology.c b/plat/nvidia/tegra/common/tegra_topology.c
index 4f6cf93..14631a7 100644
--- a/plat/nvidia/tegra/common/tegra_topology.c
+++ b/plat/nvidia/tegra/common/tegra_topology.c
@@ -23,10 +23,14 @@
u_register_t cluster_id, cpu_id;
int32_t result;
- 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;
+ 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;
- result = (int32_t)cpu_id + ((int32_t)cluster_id * 4);
+ /* CorePos = CoreId + (ClusterId * cpus per cluster) */
+ result = (int32_t)cpu_id + ((int32_t)cluster_id *
+ PLATFORM_MAX_CPUS_PER_CLUSTER);
if (cluster_id >= (u_register_t)PLATFORM_CLUSTER_COUNT) {
result = PSCI_E_NOT_PRESENT;
diff --git a/plat/nvidia/tegra/include/drivers/bpmp.h b/plat/nvidia/tegra/include/drivers/bpmp.h
index 27f57df..03da6f6 100644
--- a/plat/nvidia/tegra/include/drivers/bpmp.h
+++ b/plat/nvidia/tegra/include/drivers/bpmp.h
@@ -10,25 +10,25 @@
#include <stdint.h>
/* macro to enable clock to the Atomics block */
-#define CAR_ENABLE_ATOMICS (1UL << 16)
+#define CAR_ENABLE_ATOMICS (1U << 16)
/* command to get the channel base addresses from bpmp */
-#define ATOMIC_CMD_GET 4UL
+#define ATOMIC_CMD_GET 4U
/* Hardware IRQ # used to signal bpmp of an incoming command */
-#define INT_SHR_SEM_OUTBOX_FULL 6UL
+#define INT_SHR_SEM_OUTBOX_FULL 6U
/* macros to decode the bpmp's state */
-#define CH_MASK(ch) (0x3UL << ((ch) * 2UL))
-#define MA_FREE(ch) (0x2UL << ((ch) * 2UL))
-#define MA_ACKD(ch) (0x3UL << ((ch) * 2UL))
+#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 0xAAAAAAAAUL
+#define SIGN_OF_LIFE 0xAAAAAAAAU
/* flags to indicate bpmp driver's state */
-#define BPMP_INIT_COMPLETE 0xBEEFF00DUL
-#define BPMP_INIT_PENDING 0xDEADBEEFUL
+#define BPMP_INIT_COMPLETE 0xBEEFF00DU
+#define BPMP_INIT_PENDING 0xDEADBEEFU
/* requests serviced by the bpmp */
#define MRQ_PING 0
@@ -64,14 +64,14 @@
#define TEGRA_PM_SC7 23
/* flag to indicate if entry into a CCx power state is allowed */
-#define BPMP_CCx_ALLOWED 0UL
+#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 (0UL << 0UL)
-#define DO_ACK (1UL << 0UL)
+#define NO_ACK (0U << 0U)
+#define DO_ACK (1U << 0U)
/* size of the command/response data */
#define MSG_DATA_MAX_SZ 120U
diff --git a/plat/nvidia/tegra/include/drivers/bpmp_ipc.h b/plat/nvidia/tegra/include/drivers/bpmp_ipc.h
new file mode 100644
index 0000000..9304150
--- /dev/null
+++ b/plat/nvidia/tegra/include/drivers/bpmp_ipc.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __BPMP_IPC_H__
+#define __BPMP_IPC_H__
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <utils_def.h>
+
+/**
+ * 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);
+
+#endif /* __BPMP_IPC_H__ */
diff --git a/plat/nvidia/tegra/include/drivers/gpcdma.h b/plat/nvidia/tegra/include/drivers/gpcdma.h
new file mode 100644
index 0000000..fb5486a
--- /dev/null
+++ b/plat/nvidia/tegra/include/drivers/gpcdma.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef __GPCDMA_H__
+#define __GPCDMA_H__
+
+#include <stdint.h>
+
+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/plat/nvidia/tegra/include/drivers/memctrl.h b/plat/nvidia/tegra/include/drivers/memctrl.h
index 17427cb..d5ef60d 100644
--- a/plat/nvidia/tegra/include/drivers/memctrl.h
+++ b/plat/nvidia/tegra/include/drivers/memctrl.h
@@ -13,5 +13,6 @@
void tegra_memctrl_tzram_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/plat/nvidia/tegra/include/drivers/memctrl_v2.h b/plat/nvidia/tegra/include/drivers/memctrl_v2.h
index ffe5269..f5b0ed4 100644
--- a/plat/nvidia/tegra/include/drivers/memctrl_v2.h
+++ b/plat/nvidia/tegra/include/drivers/memctrl_v2.h
@@ -11,185 +11,10 @@
#ifndef __ASSEMBLY__
+#include <mmio.h>
#include <stdint.h>
/*******************************************************************************
- * StreamID to indicate no SMMU translations (requests to be steered on the
- * SMMU bypass path)
- ******************************************************************************/
-#define MC_STREAM_ID_MAX 0x7F
-
-/*******************************************************************************
- * Stream ID Override Config registers
- ******************************************************************************/
-#define MC_STREAMID_OVERRIDE_CFG_PTCR 0x000
-#define MC_STREAMID_OVERRIDE_CFG_AFIR 0x070
-#define MC_STREAMID_OVERRIDE_CFG_HDAR 0x0A8
-#define MC_STREAMID_OVERRIDE_CFG_HOST1XDMAR 0x0B0
-#define MC_STREAMID_OVERRIDE_CFG_NVENCSRD 0x0E0
-#define MC_STREAMID_OVERRIDE_CFG_SATAR 0x0F8
-#define MC_STREAMID_OVERRIDE_CFG_MPCORER 0x138
-#define MC_STREAMID_OVERRIDE_CFG_NVENCSWR 0x158
-#define MC_STREAMID_OVERRIDE_CFG_AFIW 0x188
-#define MC_STREAMID_OVERRIDE_CFG_HDAW 0x1A8
-#define MC_STREAMID_OVERRIDE_CFG_MPCOREW 0x1C8
-#define MC_STREAMID_OVERRIDE_CFG_SATAW 0x1E8
-#define MC_STREAMID_OVERRIDE_CFG_ISPRA 0x220
-#define MC_STREAMID_OVERRIDE_CFG_ISPWA 0x230
-#define MC_STREAMID_OVERRIDE_CFG_ISPWB 0x238
-#define MC_STREAMID_OVERRIDE_CFG_XUSB_HOSTR 0x250
-#define MC_STREAMID_OVERRIDE_CFG_XUSB_HOSTW 0x258
-#define MC_STREAMID_OVERRIDE_CFG_XUSB_DEVR 0x260
-#define MC_STREAMID_OVERRIDE_CFG_XUSB_DEVW 0x268
-#define MC_STREAMID_OVERRIDE_CFG_TSECSRD 0x2A0
-#define MC_STREAMID_OVERRIDE_CFG_TSECSWR 0x2A8
-#define MC_STREAMID_OVERRIDE_CFG_GPUSRD 0x2C0
-#define MC_STREAMID_OVERRIDE_CFG_GPUSWR 0x2C8
-#define MC_STREAMID_OVERRIDE_CFG_SDMMCRA 0x300
-#define MC_STREAMID_OVERRIDE_CFG_SDMMCRAA 0x308
-#define MC_STREAMID_OVERRIDE_CFG_SDMMCR 0x310
-#define MC_STREAMID_OVERRIDE_CFG_SDMMCRAB 0x318
-#define MC_STREAMID_OVERRIDE_CFG_SDMMCWA 0x320
-#define MC_STREAMID_OVERRIDE_CFG_SDMMCWAA 0x328
-#define MC_STREAMID_OVERRIDE_CFG_SDMMCW 0x330
-#define MC_STREAMID_OVERRIDE_CFG_SDMMCWAB 0x338
-#define MC_STREAMID_OVERRIDE_CFG_VICSRD 0x360
-#define MC_STREAMID_OVERRIDE_CFG_VICSWR 0x368
-#define MC_STREAMID_OVERRIDE_CFG_VIW 0x390
-#define MC_STREAMID_OVERRIDE_CFG_NVDECSRD 0x3C0
-#define MC_STREAMID_OVERRIDE_CFG_NVDECSWR 0x3C8
-#define MC_STREAMID_OVERRIDE_CFG_APER 0x3D0
-#define MC_STREAMID_OVERRIDE_CFG_APEW 0x3D8
-#define MC_STREAMID_OVERRIDE_CFG_NVJPGSRD 0x3F0
-#define MC_STREAMID_OVERRIDE_CFG_NVJPGSWR 0x3F8
-#define MC_STREAMID_OVERRIDE_CFG_SESRD 0x400
-#define MC_STREAMID_OVERRIDE_CFG_SESWR 0x408
-#define MC_STREAMID_OVERRIDE_CFG_ETRR 0x420
-#define MC_STREAMID_OVERRIDE_CFG_ETRW 0x428
-#define MC_STREAMID_OVERRIDE_CFG_TSECSRDB 0x430
-#define MC_STREAMID_OVERRIDE_CFG_TSECSWRB 0x438
-#define MC_STREAMID_OVERRIDE_CFG_GPUSRD2 0x440
-#define MC_STREAMID_OVERRIDE_CFG_GPUSWR2 0x448
-#define MC_STREAMID_OVERRIDE_CFG_AXISR 0x460
-#define MC_STREAMID_OVERRIDE_CFG_AXISW 0x468
-#define MC_STREAMID_OVERRIDE_CFG_EQOSR 0x470
-#define MC_STREAMID_OVERRIDE_CFG_EQOSW 0x478
-#define MC_STREAMID_OVERRIDE_CFG_UFSHCR 0x480
-#define MC_STREAMID_OVERRIDE_CFG_UFSHCW 0x488
-#define MC_STREAMID_OVERRIDE_CFG_NVDISPLAYR 0x490
-#define MC_STREAMID_OVERRIDE_CFG_BPMPR 0x498
-#define MC_STREAMID_OVERRIDE_CFG_BPMPW 0x4A0
-#define MC_STREAMID_OVERRIDE_CFG_BPMPDMAR 0x4A8
-#define MC_STREAMID_OVERRIDE_CFG_BPMPDMAW 0x4B0
-#define MC_STREAMID_OVERRIDE_CFG_AONR 0x4B8
-#define MC_STREAMID_OVERRIDE_CFG_AONW 0x4C0
-#define MC_STREAMID_OVERRIDE_CFG_AONDMAR 0x4C8
-#define MC_STREAMID_OVERRIDE_CFG_AONDMAW 0x4D0
-#define MC_STREAMID_OVERRIDE_CFG_SCER 0x4D8
-#define MC_STREAMID_OVERRIDE_CFG_SCEW 0x4E0
-#define MC_STREAMID_OVERRIDE_CFG_SCEDMAR 0x4E8
-#define MC_STREAMID_OVERRIDE_CFG_SCEDMAW 0x4F0
-#define MC_STREAMID_OVERRIDE_CFG_APEDMAR 0x4F8
-#define MC_STREAMID_OVERRIDE_CFG_APEDMAW 0x500
-#define MC_STREAMID_OVERRIDE_CFG_NVDISPLAYR1 0x508
-#define MC_STREAMID_OVERRIDE_CFG_VICSRD1 0x510
-#define MC_STREAMID_OVERRIDE_CFG_NVDECSRD1 0x518
-
-/*******************************************************************************
- * Macro to calculate Security cfg register addr from StreamID Override register
- ******************************************************************************/
-#define MC_STREAMID_OVERRIDE_TO_SECURITY_CFG(addr) (addr + sizeof(uint32_t))
-
-#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_NO_OVERRIDE_SO_DEV (0UL << 4)
-#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_FORCE_NON_COHERENT_SO_DEV (1UL << 4)
-#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_FORCE_COHERENT_SO_DEV (2UL << 4)
-#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_FORCE_COHERENT_SNOOP_SO_DEV (3UL << 4)
-
-#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_NO_OVERRIDE_NORMAL (0UL << 8)
-#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_FORCE_NON_COHERENT_NORMAL (1UL << 8)
-#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_FORCE_COHERENT_NORMAL (2UL << 8)
-#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_FORCE_COHERENT_SNOOP_NORMAL (3UL << 8)
-
-#define MC_TXN_OVERRIDE_CONFIG_CGID_SO_DEV_ZERO (0UL << 12)
-#define MC_TXN_OVERRIDE_CONFIG_CGID_SO_DEV_CLIENT_AXI_ID (1UL << 12)
-
-/*******************************************************************************
- * Memory Controller transaction override config registers
- ******************************************************************************/
-#define MC_TXN_OVERRIDE_CONFIG_HDAR 0x10a8
-#define MC_TXN_OVERRIDE_CONFIG_BPMPW 0x14a0
-#define MC_TXN_OVERRIDE_CONFIG_PTCR 0x1000
-#define MC_TXN_OVERRIDE_CONFIG_NVDISPLAYR 0x1490
-#define MC_TXN_OVERRIDE_CONFIG_EQOSW 0x1478
-#define MC_TXN_OVERRIDE_CONFIG_NVJPGSWR 0x13f8
-#define MC_TXN_OVERRIDE_CONFIG_ISPRA 0x1220
-#define MC_TXN_OVERRIDE_CONFIG_SDMMCWAA 0x1328
-#define MC_TXN_OVERRIDE_CONFIG_VICSRD 0x1360
-#define MC_TXN_OVERRIDE_CONFIG_MPCOREW 0x11c8
-#define MC_TXN_OVERRIDE_CONFIG_GPUSRD 0x12c0
-#define MC_TXN_OVERRIDE_CONFIG_AXISR 0x1460
-#define MC_TXN_OVERRIDE_CONFIG_SCEDMAW 0x14f0
-#define MC_TXN_OVERRIDE_CONFIG_SDMMCW 0x1330
-#define MC_TXN_OVERRIDE_CONFIG_EQOSR 0x1470
-#define MC_TXN_OVERRIDE_CONFIG_APEDMAR 0x14f8
-#define MC_TXN_OVERRIDE_CONFIG_NVENCSRD 0x10e0
-#define MC_TXN_OVERRIDE_CONFIG_SDMMCRAB 0x1318
-#define MC_TXN_OVERRIDE_CONFIG_VICSRD1 0x1510
-#define MC_TXN_OVERRIDE_CONFIG_BPMPDMAR 0x14a8
-#define MC_TXN_OVERRIDE_CONFIG_VIW 0x1390
-#define MC_TXN_OVERRIDE_CONFIG_SDMMCRAA 0x1308
-#define MC_TXN_OVERRIDE_CONFIG_AXISW 0x1468
-#define MC_TXN_OVERRIDE_CONFIG_XUSB_DEVR 0x1260
-#define MC_TXN_OVERRIDE_CONFIG_UFSHCR 0x1480
-#define MC_TXN_OVERRIDE_CONFIG_TSECSWR 0x12a8
-#define MC_TXN_OVERRIDE_CONFIG_GPUSWR 0x12c8
-#define MC_TXN_OVERRIDE_CONFIG_SATAR 0x10f8
-#define MC_TXN_OVERRIDE_CONFIG_XUSB_HOSTW 0x1258
-#define MC_TXN_OVERRIDE_CONFIG_TSECSWRB 0x1438
-#define MC_TXN_OVERRIDE_CONFIG_GPUSRD2 0x1440
-#define MC_TXN_OVERRIDE_CONFIG_SCEDMAR 0x14e8
-#define MC_TXN_OVERRIDE_CONFIG_GPUSWR2 0x1448
-#define MC_TXN_OVERRIDE_CONFIG_AONDMAW 0x14d0
-#define MC_TXN_OVERRIDE_CONFIG_APEDMAW 0x1500
-#define MC_TXN_OVERRIDE_CONFIG_AONW 0x14c0
-#define MC_TXN_OVERRIDE_CONFIG_HOST1XDMAR 0x10b0
-#define MC_TXN_OVERRIDE_CONFIG_ETRR 0x1420
-#define MC_TXN_OVERRIDE_CONFIG_SESWR 0x1408
-#define MC_TXN_OVERRIDE_CONFIG_NVJPGSRD 0x13f0
-#define MC_TXN_OVERRIDE_CONFIG_NVDECSRD 0x13c0
-#define MC_TXN_OVERRIDE_CONFIG_TSECSRDB 0x1430
-#define MC_TXN_OVERRIDE_CONFIG_BPMPDMAW 0x14b0
-#define MC_TXN_OVERRIDE_CONFIG_APER 0x13d0
-#define MC_TXN_OVERRIDE_CONFIG_NVDECSRD1 0x1518
-#define MC_TXN_OVERRIDE_CONFIG_XUSB_HOSTR 0x1250
-#define MC_TXN_OVERRIDE_CONFIG_ISPWA 0x1230
-#define MC_TXN_OVERRIDE_CONFIG_SESRD 0x1400
-#define MC_TXN_OVERRIDE_CONFIG_SCER 0x14d8
-#define MC_TXN_OVERRIDE_CONFIG_AONR 0x14b8
-#define MC_TXN_OVERRIDE_CONFIG_MPCORER 0x1138
-#define MC_TXN_OVERRIDE_CONFIG_SDMMCWA 0x1320
-#define MC_TXN_OVERRIDE_CONFIG_HDAW 0x11a8
-#define MC_TXN_OVERRIDE_CONFIG_NVDECSWR 0x13c8
-#define MC_TXN_OVERRIDE_CONFIG_UFSHCW 0x1488
-#define MC_TXN_OVERRIDE_CONFIG_AONDMAR 0x14c8
-#define MC_TXN_OVERRIDE_CONFIG_SATAW 0x11e8
-#define MC_TXN_OVERRIDE_CONFIG_ETRW 0x1428
-#define MC_TXN_OVERRIDE_CONFIG_VICSWR 0x1368
-#define MC_TXN_OVERRIDE_CONFIG_NVENCSWR 0x1158
-#define MC_TXN_OVERRIDE_CONFIG_AFIR 0x1070
-#define MC_TXN_OVERRIDE_CONFIG_SDMMCWAB 0x1338
-#define MC_TXN_OVERRIDE_CONFIG_SDMMCRA 0x1300
-#define MC_TXN_OVERRIDE_CONFIG_NVDISPLAYR1 0x1508
-#define MC_TXN_OVERRIDE_CONFIG_ISPWB 0x1238
-#define MC_TXN_OVERRIDE_CONFIG_BPMPR 0x1498
-#define MC_TXN_OVERRIDE_CONFIG_APEW 0x13d8
-#define MC_TXN_OVERRIDE_CONFIG_SDMMCR 0x1310
-#define MC_TXN_OVERRIDE_CONFIG_XUSB_DEVW 0x1268
-#define MC_TXN_OVERRIDE_CONFIG_TSECSRD 0x12a0
-#define MC_TXN_OVERRIDE_CONFIG_AFIW 0x1188
-#define MC_TXN_OVERRIDE_CONFIG_SCEW 0x14e0
-
-/*******************************************************************************
* Structure to hold the transaction override settings to use to override
* client inputs
******************************************************************************/
@@ -223,12 +48,31 @@
int 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 OVERRIDE_DISABLE 1
-#define OVERRIDE_ENABLE 0
-#define CLIENT_FLAG_SECURE 0
-#define CLIENT_FLAG_NON_SECURE 1
-#define CLIENT_INPUTS_OVERRIDE 1
-#define CLIENT_INPUTS_NO_OVERRIDE 0
+/*******************************************************************************
+ * 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)
#define mc_make_sec_cfg(off, ns, ovrrd, access) \
{ \
@@ -250,131 +94,10 @@
uint32_t num_streamid_security_cfgs;
const mc_txn_override_cfg_t *txn_override_cfg;
uint32_t num_txn_override_cfgs;
+ void (*reconfig_mss_clients)(void);
+ void (*set_txn_overrides)(void);
} tegra_mc_settings_t;
-#endif /* __ASSEMBLY__ */
-
-/*******************************************************************************
- * Memory Controller SMMU Bypass config register
- ******************************************************************************/
-#define MC_SMMU_BYPASS_CONFIG 0x1820
-#define MC_SMMU_BYPASS_CTRL_MASK 0x3
-#define MC_SMMU_BYPASS_CTRL_SHIFT 0
-#define MC_SMMU_CTRL_TBU_BYPASS_ALL (0 << MC_SMMU_BYPASS_CTRL_SHIFT)
-#define MC_SMMU_CTRL_TBU_RSVD (1 << MC_SMMU_BYPASS_CTRL_SHIFT)
-#define MC_SMMU_CTRL_TBU_BYPASS_SPL_STREAMID (2 << MC_SMMU_BYPASS_CTRL_SHIFT)
-#define MC_SMMU_CTRL_TBU_BYPASS_NONE (3 << MC_SMMU_BYPASS_CTRL_SHIFT)
-#define MC_SMMU_BYPASS_CONFIG_WRITE_ACCESS_BIT (1 << 31)
-#define MC_SMMU_BYPASS_CONFIG_SETTINGS (MC_SMMU_BYPASS_CONFIG_WRITE_ACCESS_BIT | \
- MC_SMMU_CTRL_TBU_BYPASS_SPL_STREAMID)
-
-#define MC_TXN_OVERRIDE_CONFIG_AXID_OVERRIDE_CGID (1 << 0)
-#define MC_TXN_OVERRIDE_CONFIG_COH_PATH_OVERRIDE_SO_DEV (2 << 4)
-#define MC_TXN_OVERRIDE_CONFIG_AXID_OVERRIDE_SO_DEV_CGID_SO_DEV_CLIENT (1 << 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 0
-#define MC_TXN_OVERRIDE_CGID_TAG_CLIENT_AXI_ID 1
-#define MC_TXN_OVERRIDE_CGID_TAG_ZERO 2
-#define MC_TXN_OVERRIDE_CGID_TAG_ADR 3
-#define MC_TXN_OVERRIDE_CGID_TAG_MASK 3
-
-/*******************************************************************************
- * Memory Controller Reset Control registers
- ******************************************************************************/
-#define MC_CLIENT_HOTRESET_CTRL0 0x200
-#define MC_CLIENT_HOTRESET_CTRL0_RESET_VAL 0
-#define MC_CLIENT_HOTRESET_CTRL0_AFI_FLUSH_ENB (1 << 0)
-#define MC_CLIENT_HOTRESET_CTRL0_HC_FLUSH_ENB (1 << 6)
-#define MC_CLIENT_HOTRESET_CTRL0_HDA_FLUSH_ENB (1 << 7)
-#define MC_CLIENT_HOTRESET_CTRL0_ISP2_FLUSH_ENB (1 << 8)
-#define MC_CLIENT_HOTRESET_CTRL0_MPCORE_FLUSH_ENB (1 << 9)
-#define MC_CLIENT_HOTRESET_CTRL0_NVENC_FLUSH_ENB (1 << 11)
-#define MC_CLIENT_HOTRESET_CTRL0_SATA_FLUSH_ENB (1 << 15)
-#define MC_CLIENT_HOTRESET_CTRL0_VI_FLUSH_ENB (1 << 17)
-#define MC_CLIENT_HOTRESET_CTRL0_VIC_FLUSH_ENB (1 << 18)
-#define MC_CLIENT_HOTRESET_CTRL0_XUSB_HOST_FLUSH_ENB (1 << 19)
-#define MC_CLIENT_HOTRESET_CTRL0_XUSB_DEV_FLUSH_ENB (1 << 20)
-#define MC_CLIENT_HOTRESET_CTRL0_TSEC_FLUSH_ENB (1 << 22)
-#define MC_CLIENT_HOTRESET_CTRL0_SDMMC1A_FLUSH_ENB (1 << 29)
-#define MC_CLIENT_HOTRESET_CTRL0_SDMMC2A_FLUSH_ENB (1 << 30)
-#define MC_CLIENT_HOTRESET_CTRL0_SDMMC3A_FLUSH_ENB (1 << 31)
-#define MC_CLIENT_HOTRESET_STATUS0 0x204
-#define MC_CLIENT_HOTRESET_CTRL1 0x970
-#define MC_CLIENT_HOTRESET_CTRL1_RESET_VAL 0
-#define MC_CLIENT_HOTRESET_CTRL1_SDMMC4A_FLUSH_ENB (1 << 0)
-#define MC_CLIENT_HOTRESET_CTRL1_GPU_FLUSH_ENB (1 << 2)
-#define MC_CLIENT_HOTRESET_CTRL1_NVDEC_FLUSH_ENB (1 << 5)
-#define MC_CLIENT_HOTRESET_CTRL1_APE_FLUSH_ENB (1 << 6)
-#define MC_CLIENT_HOTRESET_CTRL1_SE_FLUSH_ENB (1 << 7)
-#define MC_CLIENT_HOTRESET_CTRL1_NVJPG_FLUSH_ENB (1 << 8)
-#define MC_CLIENT_HOTRESET_CTRL1_ETR_FLUSH_ENB (1 << 12)
-#define MC_CLIENT_HOTRESET_CTRL1_TSECB_FLUSH_ENB (1 << 13)
-#define MC_CLIENT_HOTRESET_CTRL1_AXIS_FLUSH_ENB (1 << 18)
-#define MC_CLIENT_HOTRESET_CTRL1_EQOS_FLUSH_ENB (1 << 19)
-#define MC_CLIENT_HOTRESET_CTRL1_UFSHC_FLUSH_ENB (1 << 20)
-#define MC_CLIENT_HOTRESET_CTRL1_NVDISPLAY_FLUSH_ENB (1 << 21)
-#define MC_CLIENT_HOTRESET_CTRL1_BPMP_FLUSH_ENB (1 << 22)
-#define MC_CLIENT_HOTRESET_CTRL1_AON_FLUSH_ENB (1 << 23)
-#define MC_CLIENT_HOTRESET_CTRL1_SCE_FLUSH_ENB (1 << 24)
-#define MC_CLIENT_HOTRESET_STATUS1 0x974
-
-/*******************************************************************************
- * Memory Controller's PCFIFO client configuration registers
- ******************************************************************************/
-#define MC_PCFIFO_CLIENT_CONFIG1 0xdd4UL
-#define MC_PCFIFO_CLIENT_CONFIG1_RESET_VAL 0x20000UL
-#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_AFIW_UNORDERED (0UL << 17)
-#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_AFIW_MASK (1UL << 17)
-#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_HDAW_UNORDERED (0UL << 21)
-#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_HDAW_MASK (1UL << 21)
-#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_SATAW_UNORDERED (0UL << 29)
-#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_SATAW_MASK (1UL << 29)
-
-#define MC_PCFIFO_CLIENT_CONFIG2 0xdd8UL
-#define MC_PCFIFO_CLIENT_CONFIG2_RESET_VAL 0x20000UL
-#define MC_PCFIFO_CLIENT_CONFIG2_PCFIFO_XUSB_HOSTW_UNORDERED (0UL << 11)
-#define MC_PCFIFO_CLIENT_CONFIG2_PCFIFO_XUSB_HOSTW_MASK (1UL << 11)
-#define MC_PCFIFO_CLIENT_CONFIG2_PCFIFO_XUSB_DEVW_UNORDERED (0UL << 13)
-#define MC_PCFIFO_CLIENT_CONFIG2_PCFIFO_XUSB_DEVW_MASK (1UL << 13)
-
-#define MC_PCFIFO_CLIENT_CONFIG3 0xddcUL
-#define MC_PCFIFO_CLIENT_CONFIG3_RESET_VAL 0UL
-#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_SDMMCWAB_UNORDERED (0UL << 7)
-#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_SDMMCWAB_MASK (1UL << 7)
-
-#define MC_PCFIFO_CLIENT_CONFIG4 0xde0UL
-#define MC_PCFIFO_CLIENT_CONFIG4_RESET_VAL 0UL
-#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_SESWR_UNORDERED (0UL << 1)
-#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_SESWR_MASK (1UL << 1)
-#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_ETRW_UNORDERED (0UL << 5)
-#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_ETRW_MASK (1UL << 5)
-#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_AXISW_UNORDERED (0UL << 13)
-#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_AXISW_MASK (1UL << 13)
-#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_EQOSW_UNORDERED (0UL << 15)
-#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_EQOSW_ORDERED (1UL << 15)
-#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_EQOSW_MASK (1UL << 15)
-#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_UFSHCW_UNORDERED (0UL << 17)
-#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_UFSHCW_MASK (1UL << 17)
-#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_BPMPDMAW_UNORDERED (0UL << 22)
-#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_BPMPDMAW_MASK (1UL << 22)
-#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_AONDMAW_UNORDERED (0UL << 26)
-#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_AONDMAW_MASK (1UL << 26)
-#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_SCEDMAW_UNORDERED (0UL << 30)
-#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_SCEDMAW_MASK (1UL << 30)
-
-#define MC_PCFIFO_CLIENT_CONFIG5 0xbf4UL
-#define MC_PCFIFO_CLIENT_CONFIG5_RESET_VAL 0UL
-#define MC_PCFIFO_CLIENT_CONFIG5_PCFIFO_APEDMAW_UNORDERED (0UL << 0)
-#define MC_PCFIFO_CLIENT_CONFIG5_PCFIFO_APEDMAW_MASK (1UL << 0)
-
-#ifndef __ASSEMBLY__
-
-#include <lib/mmio.h>
-
static inline uint32_t tegra_mc_read_32(uint32_t off)
{
return mmio_read_32(TEGRA_MC_BASE + off);
@@ -396,7 +119,7 @@
}
#define mc_set_pcfifo_unordered_boot_so_mss(id, client) \
- (~MC_PCFIFO_CLIENT_CONFIG##id##_PCFIFO_##client##_MASK | \
+ ((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) \
@@ -406,8 +129,24 @@
{ \
mmio_write_32(TEGRA_TSA_BASE + TSA_CONFIG_STATIC0_CSW_##client, \
(TSA_CONFIG_STATIC0_CSW_##client##_RESET & \
- ~TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_MASK) | \
- TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_PASTHRU); \
+ (uint32_t)~TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_MASK) | \
+ (uint32_t)TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_PASTHRU); \
+ }
+
+#define mc_set_tsa_w_passthrough(client) \
+ { \
+ 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); \
+ }
+
+#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); \
}
#define mc_set_txn_override(client, normal_axi_id, so_dev_axi_id, normal_override, so_dev_override) \
@@ -426,6 +165,14 @@
******************************************************************************/
tegra_mc_settings_t *tegra_get_mc_settings(void);
+/*******************************************************************************
+ * 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 /* __ASSMEBLY__ */
+#endif /* __ASSEMBLY__ */
#endif /* MEMCTRL_V2_H */
diff --git a/plat/nvidia/tegra/include/drivers/security_engine.h b/plat/nvidia/tegra/include/drivers/security_engine.h
index abfb217..4ab2f9a 100644
--- a/plat/nvidia/tegra/include/drivers/security_engine.h
+++ b/plat/nvidia/tegra/include/drivers/security_engine.h
@@ -38,8 +38,16 @@
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
******************************************************************************/
diff --git a/plat/nvidia/tegra/include/drivers/smmu.h b/plat/nvidia/tegra/include/drivers/smmu.h
index 9582a67..41b0c51 100644
--- a/plat/nvidia/tegra/include/drivers/smmu.h
+++ b/plat/nvidia/tegra/include/drivers/smmu.h
@@ -586,12 +586,12 @@
/*******************************************************************************
* SMMU Global Aux. Control Register
******************************************************************************/
-#define SMMU_CBn_ACTLR_CPRE_BIT (1U << 1)
+#define SMMU_CBn_ACTLR_CPRE_BIT (1ULL << 1U)
/*******************************************************************************
* SMMU configuration constants
******************************************************************************/
-#define ID1_PAGESIZE (1U << 31)
+#define ID1_PAGESIZE (1U << 31U)
#define ID1_NUMPAGENDXB_SHIFT 28U
#define ID1_NUMPAGENDXB_MASK 7U
#define ID1_NUMS2CB_SHIFT 16U
@@ -705,5 +705,6 @@
void tegra_smmu_init(void);
void tegra_smmu_save_context(uint64_t smmu_ctx_addr);
smmu_regs_t *plat_get_smmu_ctx(void);
+uint32_t plat_get_num_smmu_devices(void);
#endif /* SMMU_H */
diff --git a/plat/nvidia/tegra/include/lib/profiler.h b/plat/nvidia/tegra/include/lib/profiler.h
new file mode 100644
index 0000000..60f8d80
--- /dev/null
+++ b/plat/nvidia/tegra/include/lib/profiler.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2017, ARM Limited and Contributors. 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/plat/nvidia/tegra/include/t132/tegra_def.h b/plat/nvidia/tegra/include/t132/tegra_def.h
index 1f58caa..fd75fbc 100644
--- a/plat/nvidia/tegra/include/t132/tegra_def.h
+++ b/plat/nvidia/tegra/include/t132/tegra_def.h
@@ -83,6 +83,9 @@
******************************************************************************/
#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)
diff --git a/plat/nvidia/tegra/include/t186/tegra186_private.h b/plat/nvidia/tegra/include/t186/tegra186_private.h
new file mode 100644
index 0000000..9e2c02b
--- /dev/null
+++ b/plat/nvidia/tegra/include/t186/tegra186_private.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef TEGRA186_PRIVATE_H
+#define TEGRA186_PRIVATE_H
+
+void tegra186_cpu_reset_handler(void);
+uint64_t tegra186_get_cpu_reset_handler_base(void);
+uint64_t tegra186_get_cpu_reset_handler_size(void);
+uint64_t tegra186_get_smmu_ctx_offset(void);
+void tegra186_set_system_suspend_entry(void);
+
+#endif /* TEGRA186_PRIVATE_H */
diff --git a/plat/nvidia/tegra/include/t186/tegra_def.h b/plat/nvidia/tegra/include/t186/tegra_def.h
index 3abba55..231f93a 100644
--- a/plat/nvidia/tegra/include/t186/tegra_def.h
+++ b/plat/nvidia/tegra/include/t186/tegra_def.h
@@ -112,10 +112,15 @@
#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 (U(0x3) << 11)
-#define TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_PASTHRU (U(0) << 11)
+#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)
@@ -124,18 +129,23 @@
/* 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_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)
@@ -156,7 +166,10 @@
#define MC_TZRAM_BASE_LO U(0x2194)
#define MC_TZRAM_BASE_HI U(0x2198)
#define MC_TZRAM_SIZE U(0x219C)
-#define MC_TZRAM_CLIENT_ACCESS_CFG0 U(0x21A0)
+#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
@@ -198,6 +211,8 @@
#define TEGRA_CAR_RESET_BASE U(0x05000000)
#define TEGRA_GPU_RESET_REG_OFFSET U(0x30)
#define GPU_RESET_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
@@ -221,10 +236,19 @@
#define SECURE_SCRATCH_RSV11_HI U(0x6AC)
#define SECURE_SCRATCH_RSV53_LO U(0x7F8)
#define SECURE_SCRATCH_RSV53_HI U(0x7FC)
-#define SECURE_SCRATCH_RSV54_HI U(0x804)
#define SECURE_SCRATCH_RSV55_LO U(0x808)
#define SECURE_SCRATCH_RSV55_HI U(0x80C)
+#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_SMMU_TABLE_ADDR_LO SECURE_SCRATCH_RSV11_LO
+#define SCRATCH_SMMU_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
******************************************************************************/
diff --git a/plat/nvidia/tegra/include/t186/tegra_mc_def.h b/plat/nvidia/tegra/include/t186/tegra_mc_def.h
new file mode 100644
index 0000000..d051a15
--- /dev/null
+++ b/plat/nvidia/tegra/include/t186/tegra_mc_def.h
@@ -0,0 +1,285 @@
+/*
+ * Copyright (c) 2017, 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
+
+#endif /* TEGRA_MC_DEF_H */
diff --git a/plat/nvidia/tegra/include/t210/tegra_def.h b/plat/nvidia/tegra/include/t210/tegra_def.h
index 8d71cae..75919e1 100644
--- a/plat/nvidia/tegra/include/t210/tegra_def.h
+++ b/plat/nvidia/tegra/include/t210/tegra_def.h
@@ -89,6 +89,16 @@
#define TEGRA_RST_DEV_CLR_V U(0x434)
#define TEGRA_CLK_ENB_V U(0x440)
+/* SE Clock Offsets */
+#define TEGRA_RST_DEVICES_V 0x358UL
+#define SE_RESET_BIT (0x1UL << 31)
+#define TEGRA_RST_DEVICES_W 0x35CUL
+#define ENTROPY_CLK_ENB_BIT (0x1UL << 21)
+#define TEGRA_CLK_OUT_ENB_V 0x360UL
+#define SE_CLK_ENB_BIT (0x1UL << 31)
+#define TEGRA_CLK_OUT_ENB_W 0x364UL
+#define ENTROPY_RESET_BIT (0x1UL << 21)
+
/*******************************************************************************
* Tegra Flow Controller constants
******************************************************************************/
@@ -125,6 +135,16 @@
#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)
@@ -143,6 +163,9 @@
******************************************************************************/
#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)
@@ -153,6 +176,10 @@
#define MC_VIDEO_PROTECT_BASE_LO U(0x648)
#define MC_VIDEO_PROTECT_SIZE_MB U(0x64c)
+/* SMMU configuration registers*/
+#define MC_SMMU_PPCS_ASID_0 0x270U
+#define PPCS_SMMU_ENABLE (0x1U << 31)
+
/*******************************************************************************
* Tegra SE constants
******************************************************************************/
@@ -168,4 +195,10 @@
#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)
+
#endif /* TEGRA_DEF_H */
diff --git a/plat/nvidia/tegra/include/tegra_platform.h b/plat/nvidia/tegra/include/tegra_platform.h
index 1e7ba16..13c92e0 100644
--- a/plat/nvidia/tegra/include/tegra_platform.h
+++ b/plat/nvidia/tegra/include/tegra_platform.h
@@ -46,7 +46,6 @@
bool tegra_chipid_is_t210(void);
bool tegra_chipid_is_t210_b01(void);
-
/*
* Tegra platform identifiers
*/
diff --git a/plat/nvidia/tegra/include/tegra_private.h b/plat/nvidia/tegra/include/tegra_private.h
index 1682927..68b4624 100644
--- a/plat/nvidia/tegra/include/tegra_private.h
+++ b/plat/nvidia/tegra/include/tegra_private.h
@@ -23,6 +23,16 @@
#define TEGRA_DRAM_END ULL(0x27FFFFFFF)
/*******************************************************************************
+ * 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 {
@@ -31,9 +41,11 @@
/* TZ memory base */
uint64_t tzdram_base;
/* UART port ID */
- int uart_id;
+ int32_t uart_id;
/* L2 ECC parity protection disable flag */
- int l2_ecc_parity_prot_dis;
+ int32_t l2_ecc_parity_prot_dis;
+ /* SHMEM base address for storing the boot logs */
+ uint64_t boot_profiler_shmem_base;
} plat_params_from_bl2_t;
/*******************************************************************************
@@ -63,6 +75,8 @@
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);
/* Declarations for plat_secondary.c */
void plat_secondary_setup(void);
@@ -82,7 +96,30 @@
void tegra_pm_system_suspend_entry(void);
void tegra_pm_system_suspend_exit(void);
-int tegra_system_suspended(void);
+int32_t tegra_system_suspended(void);
+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_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);
+void tegra_get_sys_suspend_power_state(psci_power_state_t *req_state);
+void tegra_cpu_standby(plat_local_state_t cpu_state);
+int32_t tegra_pwr_domain_on(u_register_t mpidr);
+void tegra_pwr_domain_off(const psci_power_state_t *target_state);
+void tegra_pwr_domain_suspend(const psci_power_state_t *target_state);
+void __dead2 tegra_pwr_domain_power_down_wfi(const psci_power_state_t *target_state);
+void tegra_pwr_domain_on_finish(const psci_power_state_t *target_state);
+void tegra_pwr_domain_suspend_finish(const psci_power_state_t *target_state);
+__dead2 void tegra_system_off(void);
+__dead2 void tegra_system_reset(void);
+int32_t tegra_validate_power_state(uint32_t power_state,
+ psci_power_state_t *req_state);
+int32_t tegra_validate_ns_entrypoint(uintptr_t entrypoint);
/* Declarations for tegraXXX_pm.c */
int tegra_prepare_cpu_suspend(unsigned int id, unsigned int afflvl);
@@ -90,8 +127,7 @@
/* Declarations for tegra_bl31_setup.c */
plat_params_from_bl2_t *bl31_get_plat_params(void);
-int bl31_check_ns_address(uint64_t base, uint64_t size_in_bytes);
-void plat_early_platform_setup(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);
diff --git a/plat/nvidia/tegra/platform.mk b/plat/nvidia/tegra/platform.mk
index 33548b7..614d2a2 100644
--- a/plat/nvidia/tegra/platform.mk
+++ b/plat/nvidia/tegra/platform.mk
@@ -12,6 +12,8 @@
# enable assert() for release/debug builds
ENABLE_ASSERTIONS := 1
+PLAT_LOG_LEVEL_ASSERT := 40
+$(eval $(call add_define,PLAT_LOG_LEVEL_ASSERT))
# enable dynamic memory mapping
PLAT_XLAT_TABLES_DYNAMIC := 1
@@ -29,11 +31,14 @@
# do not enable SVE
ENABLE_SVE_FOR_NS := 0
+# enable D-cache early during CPU warmboot
+WARMBOOT_ENABLE_DCACHE_EARLY := 1
+
include plat/nvidia/tegra/common/tegra_common.mk
include ${SOC_DIR}/platform_${TARGET_SOC}.mk
# modify BUILD_PLAT to point to SoC specific build directory
BUILD_PLAT := ${BUILD_BASE}/${PLAT}/${TARGET_SOC}/${BUILD_TYPE}
-# enable signed comparison checks
-TF_CFLAGS += -Wsign-compare
+# platform cflags (enable signed comparisons, disable stdlib)
+TF_CFLAGS += -Wsign-compare -nostdlib
diff --git a/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c
index 7226120..bd3f46f 100644
--- a/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t132/plat_psci_handlers.c
@@ -98,19 +98,24 @@
int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state)
{
+ uint64_t val;
+
tegra_fc_cpu_off(read_mpidr() & MPIDR_CPU_MASK);
/* Disable DCO operations */
denver_disable_dco();
/* Power down the CPU */
- write_actlr_el1(DENVER_CPU_STATE_POWER_DOWN);
+ val = read_actlr_el1() & ~ACTLR_EL1_PMSTATE_MASK;
+ write_actlr_el1(val | DENVER_CPU_STATE_POWER_DOWN);
return PSCI_E_SUCCESS;
}
int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state)
{
+ uint64_t val;
+
#if ENABLE_ASSERTIONS
int cpu = read_mpidr() & MPIDR_CPU_MASK;
@@ -128,7 +133,8 @@
denver_disable_dco();
/* Program the suspend state ID */
- write_actlr_el1(target_state->pwr_domain_state[PLAT_MAX_PWR_LVL]);
+ val = read_actlr_el1() & ~ACTLR_EL1_PMSTATE_MASK;
+ write_actlr_el1(val | target_state->pwr_domain_state[PLAT_MAX_PWR_LVL]);
return PSCI_E_SUCCESS;
}
diff --git a/plat/nvidia/tegra/soc/t132/platform_t132.mk b/plat/nvidia/tegra/soc/t132/platform_t132.mk
index f15ee74..bb7b7ee 100644
--- a/plat/nvidia/tegra/soc/t132/platform_t132.mk
+++ b/plat/nvidia/tegra/soc/t132/platform_t132.mk
@@ -19,7 +19,8 @@
MAX_MMAP_REGIONS := 8
$(eval $(call add_define,MAX_MMAP_REGIONS))
-BL31_SOURCES += lib/cpus/aarch64/denver.S \
+BL31_SOURCES += drivers/ti/uart/aarch64/16550_console.S \
+ lib/cpus/aarch64/denver.S \
${COMMON_DIR}/drivers/flowctrl/flowctrl.c \
${COMMON_DIR}/drivers/memctrl/memctrl_v1.c \
${SOC_DIR}/plat_psci_handlers.c \
diff --git a/plat/nvidia/tegra/soc/t186/drivers/include/mce_private.h b/plat/nvidia/tegra/soc/t186/drivers/include/mce_private.h
index 96a5525..203f61a 100644
--- a/plat/nvidia/tegra/soc/t186/drivers/include/mce_private.h
+++ b/plat/nvidia/tegra/soc/t186/drivers/include/mce_private.h
@@ -64,19 +64,17 @@
#define MCA_ARG_FINISH_MASK U(0xFF)
/*******************************************************************************
- * Uncore PERFMON ARI struct
+ * 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_CMD_SHIFT U(24)
#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)
-#define UNCORE_PERFMON_RESP_STATUS_SHIFT U(24)
/*******************************************************************************
* Structure populated by arch specific code to export routines which perform
diff --git a/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c b/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c
index 599e46e..a57bc11 100644
--- a/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c
+++ b/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c
@@ -35,8 +35,8 @@
#define ARI_REQUEST_VALID_BIT (1U << 8)
#define ARI_EVT_MASK_STANDBYWFI_BIT (1U << 7)
-/* default timeout (ms) to wait for ARI completion */
-#define ARI_MAX_RETRY_COUNT 2000
+/* default timeout (us) to wait for ARI completion */
+#define ARI_MAX_RETRY_COUNT U(2000000)
/*******************************************************************************
* ARI helper functions
@@ -80,7 +80,7 @@
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 = ARI_MAX_RETRY_COUNT;
+ uint32_t retries = (uint32_t)ARI_MAX_RETRY_COUNT;
uint32_t status;
int32_t ret = 0;
@@ -115,8 +115,8 @@
break;
}
- /* delay 1 ms */
- mdelay(1);
+ /* delay 1 us */
+ udelay(1);
/* decrement the retry count */
retries--;
@@ -151,7 +151,7 @@
/* Enter the cstate, to be woken up after wake_time (TSC ticks) */
ret = ari_request_wait(ari_base, ARI_EVT_MASK_STANDBYWFI_BIT,
- TEGRA_ARI_ENTER_CSTATE, state, wake_time);
+ (uint32_t)TEGRA_ARI_ENTER_CSTATE, state, wake_time);
}
return ret;
@@ -191,7 +191,7 @@
}
/* set the updated cstate info */
- return ari_request_wait(ari_base, 0U, TEGRA_ARI_UPDATE_CSTATE_INFO,
+ return ari_request_wait(ari_base, 0U, (uint32_t)TEGRA_ARI_UPDATE_CSTATE_INFO,
(uint32_t)val, wake_mask);
}
@@ -208,8 +208,8 @@
ari_clobber_response(ari_base);
/* update crossover threshold time */
- ret = ari_request_wait(ari_base, 0U, TEGRA_ARI_UPDATE_CROSSOVER,
- type, time);
+ ret = ari_request_wait(ari_base, 0U,
+ (uint32_t)TEGRA_ARI_UPDATE_CROSSOVER, type, time);
}
return ret;
@@ -227,7 +227,8 @@
/* clean the previous response state */
ari_clobber_response(ari_base);
- ret = ari_request_wait(ari_base, 0U, TEGRA_ARI_CSTATE_STATS, state, 0U);
+ ret = ari_request_wait(ari_base, 0U,
+ (uint32_t)TEGRA_ARI_CSTATE_STATS, state, 0U);
if (ret != 0) {
result = EINVAL;
} else {
@@ -243,8 +244,8 @@
ari_clobber_response(ari_base);
/* write the cstate stats */
- return ari_request_wait(ari_base, 0U, TEGRA_ARI_WRITE_CSTATE_STATS, state,
- 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)
@@ -261,7 +262,7 @@
local_data = 0U;
}
- ret = ari_request_wait(ari_base, 0U, TEGRA_ARI_MISC, cmd, local_data);
+ ret = ari_request_wait(ari_base, 0U, (uint32_t)TEGRA_ARI_MISC, cmd, local_data);
if (ret != 0) {
resp = (uint64_t)ret;
} else {
@@ -281,8 +282,8 @@
/* clean the previous response state */
ari_clobber_response(ari_base);
- ret = ari_request_wait(ari_base, 0U, TEGRA_ARI_IS_CCX_ALLOWED, state & 0x7U,
- wake_time);
+ 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;
@@ -307,8 +308,8 @@
/* clean the previous response state */
ari_clobber_response(ari_base);
- ret = ari_request_wait(ari_base, 0U, TEGRA_ARI_IS_SC7_ALLOWED, state,
- wake_time);
+ 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;
@@ -346,7 +347,8 @@
} else {
/* clean the previous response state */
ari_clobber_response(ari_base);
- ret = ari_request_wait(ari_base, 0U, TEGRA_ARI_ONLINE_CORE, core, 0U);
+ ret = ari_request_wait(ari_base, 0U,
+ (uint32_t)TEGRA_ARI_ONLINE_CORE, core, 0U);
}
}
@@ -374,7 +376,8 @@
((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, TEGRA_ARI_CC3_CTRL, val, 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)
@@ -386,7 +389,8 @@
* Need to program the CPU reset vector one time during cold boot
* and SC7 exit
*/
- (void)ari_request_wait(ari_base, 0U, TEGRA_ARI_COPY_MISCREG_AA64_RST, 0U, 0U);
+ (void)ari_request_wait(ari_base, 0U,
+ (uint32_t)TEGRA_ARI_COPY_MISCREG_AA64_RST, 0U, 0U);
return 0;
}
@@ -396,8 +400,8 @@
/* clean the previous response state */
ari_clobber_response(ari_base);
- return ari_request_wait(ari_base, 0U, TEGRA_ARI_ROC_FLUSH_CACHE_TRBITS,
- 0U, 0U);
+ 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)
@@ -405,8 +409,8 @@
/* clean the previous response state */
ari_clobber_response(ari_base);
- return ari_request_wait(ari_base, 0U, TEGRA_ARI_ROC_FLUSH_CACHE_ONLY,
- 0U, 0U);
+ 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)
@@ -414,8 +418,8 @@
/* clean the previous response state */
ari_clobber_response(ari_base);
- return ari_request_wait(ari_base, 0U, TEGRA_ARI_ROC_CLEAN_CACHE_ONLY,
- 0U, 0U);
+ 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)
@@ -432,7 +436,7 @@
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, TEGRA_ARI_MCA,
+ 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) {
@@ -473,7 +477,8 @@
* the ID, from the MC registers and update the internal GSC registers
* of the CCPLEX.
*/
- (void)ari_request_wait(ari_base, 0U, TEGRA_ARI_UPDATE_CCPLEX_GSC, gsc_idx, 0U);
+ (void)ari_request_wait(ari_base, 0U,
+ (uint32_t)TEGRA_ARI_UPDATE_CCPLEX_GSC, gsc_idx, 0U);
}
return ret;
@@ -487,7 +492,8 @@
/*
* The MCE will shutdown or restart the entire system
*/
- (void)ari_request_wait(ari_base, 0U, TEGRA_ARI_MISC_CCPLEX, state_idx, 0U);
+ (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,
@@ -497,7 +503,7 @@
uint32_t val, req_status;
uint8_t req_cmd;
- req_cmd = (uint8_t)(req >> UNCORE_PERFMON_CMD_SHIFT);
+ req_cmd = (uint8_t)(req & UNCORE_PERFMON_CMD_MASK);
/* clean the previous response state */
ari_clobber_response(ari_base);
@@ -514,8 +520,8 @@
val = (req_cmd == UNCORE_PERFMON_CMD_WRITE) ?
(uint32_t)*data : 0U;
- ret = ari_request_wait(ari_base, 0U, TEGRA_ARI_PERFMON, val,
- (uint32_t)req);
+ ret = ari_request_wait(ari_base, 0U,
+ (uint32_t)TEGRA_ARI_PERFMON, val, (uint32_t)req);
if (ret != 0) {
result = ret;
} else {
@@ -527,7 +533,7 @@
* For "read" commands get the data from the uncore
* perfmon registers
*/
- req_status >>= UNCORE_PERFMON_RESP_STATUS_SHIFT;
+ req_status &= UNCORE_PERFMON_RESP_STATUS_MASK;
if ((req_status == 0U) && (req_cmd == UNCORE_PERFMON_CMD_READ)) {
*data = ari_get_response_low(ari_base);
}
@@ -552,6 +558,7 @@
} else {
/* clean the previous response state */
ari_clobber_response(ari_base);
- (void)ari_request_wait(ari_base, 0U, TEGRA_ARI_MISC_CCPLEX, index, value);
+ (void)ari_request_wait(ari_base, 0U,
+ (uint32_t)TEGRA_ARI_MISC_CCPLEX, index, value);
}
}
diff --git a/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c b/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c
index e948e99..9e42b2b 100644
--- a/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c
+++ b/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c
@@ -170,12 +170,12 @@
cpu_ari_base = mce_get_curr_cpu_ari_base();
switch (cmd) {
- case MCE_CMD_ENTER_CSTATE:
+ case (uint64_t)MCE_CMD_ENTER_CSTATE:
ret = ops->enter_cstate(cpu_ari_base, arg0, arg1);
break;
- case MCE_CMD_UPDATE_CSTATE_INFO:
+ case (uint64_t)MCE_CMD_UPDATE_CSTATE_INFO:
/*
* get the parameters required for the update cstate info
* command
@@ -194,12 +194,12 @@
break;
- case MCE_CMD_UPDATE_CROSSOVER_TIME:
+ case (uint64_t)MCE_CMD_UPDATE_CROSSOVER_TIME:
ret = ops->update_crossover_time(cpu_ari_base, arg0, arg1);
break;
- case MCE_CMD_READ_CSTATE_STATS:
+ case (uint64_t)MCE_CMD_READ_CSTATE_STATS:
ret64 = ops->read_cstate_stats(cpu_ari_base, arg0);
/* update context to return cstate stats value */
@@ -208,12 +208,12 @@
break;
- case MCE_CMD_WRITE_CSTATE_STATS:
+ case (uint64_t)MCE_CMD_WRITE_CSTATE_STATS:
ret = ops->write_cstate_stats(cpu_ari_base, arg0, arg1);
break;
- case MCE_CMD_IS_CCX_ALLOWED:
+ 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 */
@@ -221,7 +221,7 @@
break;
- case MCE_CMD_IS_SC7_ALLOWED:
+ 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 */
@@ -230,17 +230,17 @@
break;
- case MCE_CMD_ONLINE_CORE:
+ case (uint64_t)MCE_CMD_ONLINE_CORE:
ret = ops->online_core(cpu_ari_base, arg0);
break;
- case MCE_CMD_CC3_CTRL:
+ case (uint64_t)MCE_CMD_CC3_CTRL:
ret = ops->cc3_ctrl(cpu_ari_base, arg0, arg1, arg2);
break;
- case MCE_CMD_ECHO_DATA:
+ case (uint64_t)MCE_CMD_ECHO_DATA:
ret64 = ops->call_enum_misc(cpu_ari_base, TEGRA_ARI_MISC_ECHO,
arg0);
@@ -252,7 +252,7 @@
break;
- case MCE_CMD_READ_VERSIONS:
+ case (uint64_t)MCE_CMD_READ_VERSIONS:
ret64 = ops->call_enum_misc(cpu_ari_base, TEGRA_ARI_MISC_VERSION,
arg0);
@@ -265,7 +265,7 @@
break;
- case MCE_CMD_ENUM_FEATURES:
+ case (uint64_t)MCE_CMD_ENUM_FEATURES:
ret64 = ops->call_enum_misc(cpu_ari_base,
TEGRA_ARI_MISC_FEATURE_LEAF_0, arg0);
@@ -274,22 +274,22 @@
break;
- case MCE_CMD_ROC_FLUSH_CACHE_TRBITS:
+ case (uint64_t)MCE_CMD_ROC_FLUSH_CACHE_TRBITS:
ret = ops->roc_flush_cache_trbits(cpu_ari_base);
break;
- case MCE_CMD_ROC_FLUSH_CACHE:
+ case (uint64_t)MCE_CMD_ROC_FLUSH_CACHE:
ret = ops->roc_flush_cache(cpu_ari_base);
break;
- case MCE_CMD_ROC_CLEAN_CACHE:
+ case (uint64_t)MCE_CMD_ROC_CLEAN_CACHE:
ret = ops->roc_clean_cache(cpu_ari_base);
break;
- case MCE_CMD_ENUM_READ_MCA:
+ 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 */
@@ -299,7 +299,7 @@
break;
- case MCE_CMD_ENUM_WRITE_MCA:
+ case (uint64_t)MCE_CMD_ENUM_WRITE_MCA:
ret64 = ops->read_write_mca(cpu_ari_base, arg0, &arg1);
/* update context to return MCA error */
@@ -309,7 +309,7 @@
break;
#if ENABLE_CHIP_VERIFICATION_HARNESS
- case MCE_CMD_ENABLE_LATIC:
+ 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
@@ -327,14 +327,14 @@
break;
#endif
- case MCE_CMD_UNCORE_PERFMON_REQ:
+ 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 MCE_CMD_MISC_CCPLEX:
+ case (uint64_t)MCE_CMD_MISC_CCPLEX:
ops->misc_ccplex(cpu_ari_base, arg0, arg1);
break;
diff --git a/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c b/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c
index 44ee8fb..cbc9aa3 100644
--- a/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c
+++ b/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c
@@ -14,10 +14,12 @@
#include <mce_private.h>
#include <t18x_ari.h>
+#include <tegra_private.h>
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;
@@ -28,10 +30,11 @@
ret = EINVAL;
} else {
/* time (TSC ticks) until the core is expected to get a wake event */
- nvg_set_request_data(TEGRA_NVG_CHANNEL_WAKE_TIME, wake_time);
+ nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_WAKE_TIME, wake_time);
/* set the core cstate */
- write_actlr_el1(state);
+ val = read_actlr_el1() & ~ACTLR_EL1_PMSTATE_MASK;
+ write_actlr_el1(val | (uint64_t)state);
}
return ret;
@@ -78,7 +81,7 @@
val |= ((uint64_t)wake_mask << CSTATE_WAKE_MASK_SHIFT);
/* set the updated cstate info */
- nvg_set_request_data(TEGRA_NVG_CHANNEL_CSTATE_INFO, val);
+ nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_CSTATE_INFO, val);
return 0;
}
@@ -189,7 +192,7 @@
((uint64_t)state & MCE_SC7_ALLOWED_MASK);
/* issue command to check if SC7 is allowed */
- nvg_set_request_data(TEGRA_NVG_CHANNEL_IS_SC7_ALLOWED, val);
+ 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;
@@ -219,7 +222,7 @@
ret = EINVAL;
} else {
/* get a core online */
- nvg_set_request_data(TEGRA_NVG_CHANNEL_ONLINE_CORE,
+ nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_ONLINE_CORE,
((uint64_t)core & MCE_CORE_ID_MASK));
}
}
@@ -247,7 +250,7 @@
((volt & MCE_AUTO_CC3_VTG_MASK) << MCE_AUTO_CC3_VTG_SHIFT) |\
((enable != 0U) ? MCE_AUTO_CC3_ENABLE_BIT : 0U));
- nvg_set_request_data(TEGRA_NVG_CHANNEL_CC3_CTRL, (uint64_t)val);
+ nvg_set_request_data((uint64_t)TEGRA_NVG_CHANNEL_CC3_CTRL, (uint64_t)val);
return 0;
}
diff --git a/plat/nvidia/tegra/soc/t186/plat_memctrl.c b/plat/nvidia/tegra/soc/t186/plat_memctrl.c
index 38dffb2..376ee86 100644
--- a/plat/nvidia/tegra/soc/t186/plat_memctrl.c
+++ b/plat/nvidia/tegra/soc/t186/plat_memctrl.c
@@ -4,9 +4,13 @@
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <assert.h>
#include <common/bl_common.h>
+#include <mce.h>
#include <memctrl_v2.h>
+#include <tegra_mc_def.h>
+#include <tegra_platform.h>
/*******************************************************************************
* Array to hold stream_id override config register offsets
@@ -201,16 +205,330 @@
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 |
+#if ENABLE_AFI_DEVICE
+ MC_CLIENT_HOTRESET_CTRL0_AFI_FLUSH_ENB |
+#endif
+ 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
+ */
+#if ENABLE_AFI_DEVICE
+ mc_set_tsa_passthrough(AFIW);
+#endif
+ 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 &
+#if ENABLE_AFI_DEVICE
+ mc_set_pcfifo_unordered_boot_so_mss(1, AFIW) &
+#endif
+ 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)
+{
+ const tegra_mc_settings_t *plat_mc_settings = tegra_get_mc_settings();
+ const mc_txn_override_cfg_t *mc_txn_override_cfgs;
+ uint32_t num_txn_override_cfgs;
+ uint32_t i, val;
+
+ /* Get the settings from the platform */
+ assert(plat_mc_settings != NULL);
+ mc_txn_override_cfgs = plat_mc_settings->txn_override_cfg;
+ num_txn_override_cfgs = plat_mc_settings->num_txn_override_cfgs;
+
+ /*
+ * 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 < num_txn_override_cfgs; i++) {
+ val = tegra_mc_read_32(mc_txn_override_cfgs[i].offset);
+ val &= (uint32_t)~MC_TXN_OVERRIDE_CGID_TAG_MASK;
+ tegra_mc_write_32(mc_txn_override_cfgs[i].offset,
+ val | mc_txn_override_cfgs[i].cgid_tag);
+ }
+ }
+}
+
/*******************************************************************************
* Struct to hold the memory controller settings
******************************************************************************/
static tegra_mc_settings_t tegra186_mc_settings = {
.streamid_override_cfg = tegra186_streamid_override_regs,
- .num_streamid_override_cfgs = ARRAY_SIZE(tegra186_streamid_override_regs),
+ .num_streamid_override_cfgs = (uint32_t)ARRAY_SIZE(tegra186_streamid_override_regs),
.streamid_security_cfg = tegra186_streamid_sec_cfgs,
- .num_streamid_security_cfgs = ARRAY_SIZE(tegra186_streamid_sec_cfgs),
+ .num_streamid_security_cfgs = (uint32_t)ARRAY_SIZE(tegra186_streamid_sec_cfgs),
.txn_override_cfg = tegra186_txn_override_cfgs,
- .num_txn_override_cfgs = ARRAY_SIZE(tegra186_txn_override_cfgs)
+ .num_txn_override_cfgs = (uint32_t)ARRAY_SIZE(tegra186_txn_override_cfgs),
+ .reconfig_mss_clients = tegra186_memctrl_reconfig_mss_clients,
+ .set_txn_overrides = tegra186_memctrl_set_overrides,
};
/*******************************************************************************
@@ -220,3 +538,45 @@
{
return &tegra186_mc_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 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/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
index 7a9ce28..09e257d 100644
--- a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c
@@ -20,19 +20,13 @@
#include <mce.h>
#include <smmu.h>
+#include <stdbool.h>
#include <t18x_ari.h>
+#include <tegra186_private.h>
#include <tegra_private.h>
extern void memcpy16(void *dest, const void *src, unsigned int length);
-extern void prepare_cpu_pwr_dwn(void);
-extern void tegra186_cpu_reset_handler(void);
-extern uint32_t __tegra186_cpu_reset_handler_end,
- __tegra186_smmu_context;
-
-/* TZDRAM offset for saving SMMU context */
-#define TEGRA186_SMMU_CTX_OFFSET 16UL
-
/* state id mask */
#define TEGRA186_STATE_ID_MASK 0xFU
/* constants to get power state's wake time */
@@ -111,7 +105,7 @@
/* Enter CPU idle/powerdown */
val = (stateid_afflvl0 == PSTATE_ID_CORE_IDLE) ?
- TEGRA_ARI_CORE_C6 : TEGRA_ARI_CORE_C7;
+ (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);
@@ -127,32 +121,36 @@
/* save 'Secure Boot' Processor Feature Config Register */
val = mmio_read_32(TEGRA_MISC_BASE + MISCREG_PFCFG);
- mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV6, val);
+ mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_SECURE_BOOTP_FCFG, val);
/* save SMMU context to TZDRAM */
smmu_ctx_base = params_from_bl2->tzdram_base +
- ((uintptr_t)&__tegra186_smmu_context -
- (uintptr_t)tegra186_cpu_reset_handler);
+ tegra186_get_smmu_ctx_offset();
tegra_smmu_save_context((uintptr_t)smmu_ctx_base);
/* Prepare for system suspend */
- cstate_info.cluster = TEGRA_ARI_CLUSTER_CC7;
- cstate_info.system = TEGRA_ARI_SYSTEM_SC7;
+ 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,
- TEGRA_ARI_CORE_C7,
+ (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,
- TEGRA_ARI_CORE_C7, MCE_CORE_SLEEP_TIME_INFINITE, 0U);
+ (uint64_t)TEGRA_ARI_CORE_C7, MCE_CORE_SLEEP_TIME_INFINITE, 0U);
+
+ /* set system suspend state for house-keeping */
+ tegra186_set_system_suspend_entry();
+
} else {
; /* do nothing */
}
@@ -161,32 +159,41 @@
}
/*******************************************************************************
- * Platform handler to calculate the proper target power level at the
- * specified affinity level
+ * Helper function to check if this is the last ON CPU in the cluster
******************************************************************************/
-plat_local_state_t tegra_soc_get_target_pwr_state(uint32_t lvl,
- const plat_local_state_t *states,
- uint32_t ncpu)
+static bool tegra_last_cpu_in_cluster(const plat_local_state_t *states,
+ uint32_t ncpu)
{
- plat_local_state_t target = *states;
- uint32_t pos = 0;
- plat_local_state_t result = PSCI_LOCAL_STATE_RUN;
- uint32_t cpu = plat_my_core_pos(), num_cpu = ncpu;
- int32_t ret, cluster_powerdn = 1;
- uint64_t core_pos = read_mpidr() & (uint64_t)MPIDR_CPU_MASK;
- mce_cstate_info_t cstate_info = { 0 };
+ plat_local_state_t target;
+ bool last_on_cpu = true;
+ uint32_t num_cpus = ncpu, pos = 0;
- /* get the power state at this level */
- if (lvl == (uint32_t)MPIDR_AFFLVL1) {
- target = states[core_pos];
- }
- if (lvl == (uint32_t)MPIDR_AFFLVL2) {
- target = states[cpu];
- }
+ do {
+ target = states[pos];
+ if (target != PLAT_MAX_OFF_STATE) {
+ last_on_cpu = false;
+ }
+ --num_cpus;
+ pos++;
+ } while (num_cpus != 0U);
- /* CPU suspend */
- if ((lvl == (uint32_t)MPIDR_AFFLVL1) && (target == PSTATE_ID_CORE_POWERDN)) {
+ 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;
@@ -194,41 +201,30 @@
/* Check if CCx state is allowed. */
ret = mce_command_handler((uint64_t)MCE_CMD_IS_CCX_ALLOWED,
- TEGRA_ARI_CORE_C7, tegra_percpu_data[cpu].wake_time,
+ (uint64_t)TEGRA_ARI_CORE_C7,
+ tegra_percpu_data[cpu].wake_time,
0U);
- if (ret != 0) {
- result = PSTATE_ID_CORE_POWERDN;
+ if (ret == 0) {
+ target = PSCI_LOCAL_STATE_RUN;
}
}
/* CPU off */
- if ((lvl == (uint32_t)MPIDR_AFFLVL1) && (target == PLAT_MAX_OFF_STATE)) {
-
- /* find out the number of ON cpus in the cluster */
- do {
- target = states[pos];
- if (target != PLAT_MAX_OFF_STATE) {
- cluster_powerdn = 0;
- }
- --num_cpu;
- pos++;
- } while (num_cpu != 0U);
-
+ if (target == PLAT_MAX_OFF_STATE) {
/* Enable cluster powerdn from last CPU in the cluster */
- if (cluster_powerdn != 0) {
-
+ if (tegra_last_cpu_in_cluster(states, ncpu)) {
/* Enable CC7 state and turn off wake mask */
- cstate_info.cluster = TEGRA_ARI_CLUSTER_CC7;
+ 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,
- TEGRA_ARI_CORE_C7,
+ (uint64_t)TEGRA_ARI_CORE_C7,
MCE_CORE_SLEEP_TIME_INFINITE,
0U);
- if (ret != 0) {
- result = PSTATE_ID_CORE_POWERDN;
+ if (ret == 0) {
+ target = PSCI_LOCAL_STATE_RUN;
}
} else {
@@ -236,17 +232,37 @@
/* 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) || (lvl == (uint32_t)MPIDR_AFFLVL1)) &&
- (target == PSTATE_ID_SOC_POWERDN)) {
- result = PSTATE_ID_SOC_POWERDN;
+ 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);
}
- /* default state */
- return result;
+ /* target cluster/system state */
+ return target;
}
int32_t tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state)
@@ -265,8 +281,7 @@
* BL3-1 over to TZDRAM.
*/
val = params_from_bl2->tzdram_base +
- ((uintptr_t)&__tegra186_cpu_reset_handler_end -
- (uintptr_t)&tegra186_cpu_reset_handler);
+ tegra186_get_cpu_reset_handler_size();
memcpy16((void *)(uintptr_t)val, (void *)(uintptr_t)BL31_BASE,
(uintptr_t)&__BL31_END__ - (uintptr_t)BL31_BASE);
}
@@ -276,12 +291,12 @@
int32_t tegra_soc_pwr_domain_on(u_register_t mpidr)
{
- uint32_t target_cpu = mpidr & (uint64_t)MPIDR_CPU_MASK;
- uint32_t target_cluster = (mpidr & MPIDR_CLUSTER_MASK) >>
- (uint64_t)MPIDR_AFFINITY_BITS;
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 > (uint64_t)MPIDR_AFFLVL1) {
+ if (target_cluster > ((uint32_t)PLATFORM_CLUSTER_COUNT - 1U)) {
ERROR("%s: unsupported CPU (0x%lx)\n", __func__, mpidr);
ret = PSCI_E_NOT_PRESENT;
@@ -304,14 +319,13 @@
uint64_t impl, val;
const plat_params_from_bl2_t *plat_params = bl31_get_plat_params();
- impl = (read_midr() >> MIDR_IMPL_SHIFT) & (uint64_t)MIDR_IMPL_MASK;
+ 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 != (uint64_t)DENVER_IMPL)) {
+ if ((plat_params->l2_ecc_parity_prot_dis != 1) && (impl != DENVER_IMPL)) {
val = read_l2ctlr_el1();
val |= CORTEX_A57_L2_ECC_PARITY_PROTECTION_BIT;
@@ -327,7 +341,7 @@
*/
if (stateid_afflvl0 == PLAT_MAX_OFF_STATE) {
- cstate_info.cluster = TEGRA_ARI_CLUSTER_CC1;
+ cstate_info.cluster = (uint32_t)TEGRA_ARI_CLUSTER_CC1;
cstate_info.update_wake_mask = 1;
mce_update_cstate_info(&cstate_info);
}
@@ -354,8 +368,8 @@
* and SC7 for SC7 entry which may not be requested by
* non-secure SW which controls idle states.
*/
- cstate_info.cluster = TEGRA_ARI_CLUSTER_CC7;
- cstate_info.system = TEGRA_ARI_SYSTEM_SC1;
+ 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);
}
@@ -375,8 +389,8 @@
}
/* Turn off CPU */
- (void)mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE, TEGRA_ARI_CORE_C7,
- MCE_CORE_SLEEP_TIME_INFINITE, 0U);
+ (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;
}
@@ -384,7 +398,7 @@
__dead2 void tegra_soc_prepare_system_off(void)
{
/* power off the entire system */
- mce_enter_ccplex_state(TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF);
+ mce_enter_ccplex_state((uint32_t)TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF);
wfi();
@@ -396,7 +410,7 @@
int32_t tegra_soc_prepare_system_reset(void)
{
- mce_enter_ccplex_state(TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT);
+ mce_enter_ccplex_state((uint32_t)TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT);
return PSCI_E_SUCCESS;
}
diff --git a/plat/nvidia/tegra/soc/t186/plat_secondary.c b/plat/nvidia/tegra/soc/t186/plat_secondary.c
index 35a403b..1650809 100644
--- a/plat/nvidia/tegra/soc/t186/plat_secondary.c
+++ b/plat/nvidia/tegra/soc/t186/plat_secondary.c
@@ -11,6 +11,7 @@
#include <lib/mmio.h>
#include <mce.h>
+#include <tegra186_private.h>
#include <tegra_def.h>
#include <tegra_private.h>
@@ -24,9 +25,6 @@
extern void memcpy16(void *dest, const void *src, unsigned int length);
-extern uint64_t tegra_bl31_phys_base;
-extern uint64_t __tegra186_cpu_reset_handler_end;
-
/*******************************************************************************
* Setup secondary CPU vectors
******************************************************************************/
@@ -34,39 +32,33 @@
{
uint32_t addr_low, addr_high;
const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params();
- uint64_t cpu_reset_handler_base;
+ uint64_t cpu_reset_handler_base, cpu_reset_handler_size;
INFO("Setting up secondary CPU boot\n");
- if ((tegra_bl31_phys_base >= TEGRA_TZRAM_BASE) &&
- (tegra_bl31_phys_base <= (TEGRA_TZRAM_BASE + TEGRA_TZRAM_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 = params_from_bl2->tzdram_base;
- memcpy16((void *)((uintptr_t)cpu_reset_handler_base),
- (void *)(uintptr_t)tegra186_cpu_reset_handler,
- (uintptr_t)&__tegra186_cpu_reset_handler_end -
- (uintptr_t)tegra186_cpu_reset_handler);
+ /*
+ * 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 = tegra186_get_cpu_reset_handler_base();
+ cpu_reset_handler_size = tegra186_get_cpu_reset_handler_size();
+ (void)memcpy16((void *)(uintptr_t)params_from_bl2->tzdram_base,
+ (const void *)(uintptr_t)cpu_reset_handler_base,
+ cpu_reset_handler_size);
- } else {
- cpu_reset_handler_base = (uintptr_t)tegra_secure_entrypoint;
- }
-
- addr_low = (uint32_t)cpu_reset_handler_base | CPU_RESET_MODE_AA64;
- addr_high = (uint32_t)((cpu_reset_handler_base >> 32U) & 0x7ffU);
+ /* 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);
mmio_write_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_SECURE_RSV1_SCRATCH_0,
+ mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_LO,
addr_low);
- mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_SECURE_RSV1_SCRATCH_1,
+ mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_HI,
addr_high);
/* update reset vector address to the CCPLEX */
diff --git a/plat/nvidia/tegra/soc/t186/plat_setup.c b/plat/nvidia/tegra/soc/t186/plat_setup.c
index bbd19c1..fd109e5 100644
--- a/plat/nvidia/tegra/soc/t186/plat_setup.c
+++ b/plat/nvidia/tegra/soc/t186/plat_setup.c
@@ -40,7 +40,7 @@
* the number of power domains at the highest power level.
*******************************************************************************
*/
-const uint8_t tegra_power_domain_tree_desc[] = {
+static const uint8_t tegra_power_domain_tree_desc[] = {
/* No of root nodes */
1,
/* No of clusters */
@@ -211,7 +211,7 @@
{
uint32_t val;
- val = mmio_read_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV53_LO);
+ val = mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_BL31_PARAMS_ADDR);
return (struct tegra_bl31_params *)(uintptr_t)val;
}
@@ -223,7 +223,7 @@
{
uint32_t val;
- val = mmio_read_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV53_HI);
+ val = mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_BL31_PLAT_PARAMS_ADDR);
return (plat_params_from_bl2_t *)(uintptr_t)val;
}
diff --git a/plat/nvidia/tegra/soc/t186/plat_sip_calls.c b/plat/nvidia/tegra/soc/t186/plat_sip_calls.c
index 955029e..4de8a9e 100644
--- a/plat/nvidia/tegra/soc/t186/plat_sip_calls.c
+++ b/plat/nvidia/tegra/soc/t186/plat_sip_calls.c
@@ -23,7 +23,7 @@
/*******************************************************************************
* Offset to read the ref_clk counter value
******************************************************************************/
-#define REF_CLK_OFFSET 4
+#define REF_CLK_OFFSET 4ULL
/*******************************************************************************
* Tegra186 SiP SMCs
@@ -35,7 +35,7 @@
#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_ONLINE_CORE 0xC2FFFF06
+
#define TEGRA_SIP_MCE_CMD_CC3_CTRL 0xC2FFFF07
#define TEGRA_SIP_MCE_CMD_ECHO_DATA 0xC2FFFF08
#define TEGRA_SIP_MCE_CMD_READ_VERSIONS 0xC2FFFF09
@@ -52,7 +52,7 @@
/*******************************************************************************
* This function is responsible for handling all T186 SiP calls
******************************************************************************/
-int plat_sip_handler(uint32_t smc_fid,
+int32_t plat_sip_handler(uint32_t smc_fid,
uint64_t x1,
uint64_t x2,
uint64_t x3,
@@ -61,24 +61,30 @@
void *handle,
uint64_t flags)
{
- int mce_ret;
- int impl, cpu;
+ 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 */
- x1 = (uint32_t)x1;
- x2 = (uint32_t)x2;
- x3 = (uint32_t)x3;
+ 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
*/
- smc_fid |= (SMC_64 << FUNCID_CC_SHIFT);
+ local_smc_fid |= (SMC_64 << FUNCID_CC_SHIFT);
- switch (smc_fid) {
+ switch (local_smc_fid) {
/*
* Micro Coded Engine (MCE) commands reside in the 0x82FFFF00 -
* 0x82FFFFFF SiP SMC space
@@ -103,14 +109,13 @@
case TEGRA_SIP_MCE_CMD_MISC_CCPLEX:
/* clean up the high bits */
- smc_fid &= MCE_CMD_MASK;
+ local_smc_fid &= MCE_CMD_MASK;
/* execute the command and store the result */
- mce_ret = mce_command_handler(smc_fid, x1, x2, x3);
- write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X0,
- (uint64_t)mce_ret);
-
- return 0;
+ 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
@@ -125,28 +130,30 @@
impl = ((uint32_t)x2 >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK;
/* sanity check target CPU number */
- if (cpu > PLATFORM_MAX_CPUS_PER_CLUSTER)
- return -EINVAL;
+ 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;
- /* 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);
- /* read the clock counter values */
- core_clk_ctr = mmio_read_32(base + (8 * cpu));
- ref_clk_ctr = mmio_read_32(base + (8 * 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));
+ }
- /* return the counter values as two different parameters */
- write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X1,
- (uint64_t)core_clk_ctr);
- write_ctx_reg(get_gpregs_ctx(handle), CTX_GPREG_X2,
- (uint64_t)ref_clk_ctr);
-
- return 0;
+ break;
default:
+ ret = -ENOTSUP;
break;
}
- return -ENOTSUP;
+ return ret;
}
diff --git a/plat/nvidia/tegra/soc/t186/plat_smmu.c b/plat/nvidia/tegra/soc/t186/plat_smmu.c
index 19e065c..95f6def 100644
--- a/plat/nvidia/tegra/soc/t186/plat_smmu.c
+++ b/plat/nvidia/tegra/soc/t186/plat_smmu.c
@@ -8,6 +8,9 @@
#include <smmu.h>
#include <tegra_def.h>
+#include <tegra_mc_def.h>
+
+#define MAX_NUM_SMMU_DEVICES U(1)
/*******************************************************************************
* Array to hold SMMU context for Tegra186
@@ -305,7 +308,15 @@
smmu_regs_t *plat_get_smmu_ctx(void)
{
/* index of _END_OF_TABLE_ */
- tegra186_smmu_context[0].val = ARRAY_SIZE(tegra186_smmu_context) - 1;
+ tegra186_smmu_context[0].val = (uint32_t)(ARRAY_SIZE(tegra186_smmu_context)) - 1U;
return tegra186_smmu_context;
}
+
+/*******************************************************************************
+ * Handler to return the support SMMU devices number
+ ******************************************************************************/
+uint32_t plat_get_num_smmu_devices(void)
+{
+ return MAX_NUM_SMMU_DEVICES;
+}
diff --git a/plat/nvidia/tegra/soc/t186/plat_trampoline.S b/plat/nvidia/tegra/soc/t186/plat_trampoline.S
index 69ca798..e3393e9 100644
--- a/plat/nvidia/tegra/soc/t186/plat_trampoline.S
+++ b/plat/nvidia/tegra/soc/t186/plat_trampoline.S
@@ -10,23 +10,32 @@
#include <plat/common/common_def.h>
#include <tegra_def.h>
+#define TEGRA186_STATE_SYSTEM_SUSPEND 0x5C7
+#define TEGRA186_STATE_SYSTEM_RESUME 0x600D
#define TEGRA186_SMMU_CTX_SIZE 0x420
.globl tegra186_cpu_reset_handler
/* CPU reset handler routine */
func tegra186_cpu_reset_handler _align=4
- /*
- * The TZRAM loses state during System Suspend. We use this
- * information to decide if the reset handler is running after a
- * System Suspend. Resume from system suspend requires restoring
- * the entire state from TZDRAM to TZRAM.
- */
- mov x0, #BL31_BASE
- ldr x0, [x0]
- cbnz x0, boot_cpu
+ /* check if we are exiting system suspend state */
+ adr x0, __tegra186_system_suspend_state
+ ldr x1, [x0]
+ mov x2, #TEGRA186_STATE_SYSTEM_SUSPEND
+ lsl x2, x2, #16
+ add x2, x2, #TEGRA186_STATE_SYSTEM_SUSPEND
+ cmp x1, x2
+ bne boot_cpu
- /* resume from system suspend */
+ /* set system resume state */
+ mov x1, #TEGRA186_STATE_SYSTEM_RESUME
+ lsl x1, x1, #16
+ mov x2, #TEGRA186_STATE_SYSTEM_RESUME
+ add x1, x1, x2
+ str x1, [x0]
+ dsb sy
+
+ /* prepare to relocate to TZSRAM */
mov x0, #BL31_BASE
adr x1, __tegra186_cpu_reset_handler_end
adr x2, __tegra186_cpu_reset_handler_data
@@ -69,6 +78,12 @@
__tegra186_cpu_reset_handler_data:
.quad tegra_secure_entrypoint
.quad __BL31_END__ - BL31_BASE
+
+ .globl __tegra186_system_suspend_state
+__tegra186_system_suspend_state:
+ .quad 0
+
+ .align 4
.globl __tegra186_smmu_context
__tegra186_smmu_context:
.rept TEGRA186_SMMU_CTX_SIZE
@@ -80,3 +95,50 @@
.align 4
.globl __tegra186_cpu_reset_handler_end
__tegra186_cpu_reset_handler_end:
+
+ .globl tegra186_get_cpu_reset_handler_size
+ .globl tegra186_get_cpu_reset_handler_base
+ .globl tegra186_get_smmu_ctx_offset
+ .globl tegra186_set_system_suspend_entry
+
+/* return size of the CPU reset handler */
+func tegra186_get_cpu_reset_handler_size
+ adr x0, __tegra186_cpu_reset_handler_end
+ adr x1, tegra186_cpu_reset_handler
+ sub x0, x0, x1
+ ret
+endfunc tegra186_get_cpu_reset_handler_size
+
+/* return the start address of the CPU reset handler */
+func tegra186_get_cpu_reset_handler_base
+ adr x0, tegra186_cpu_reset_handler
+ ret
+endfunc tegra186_get_cpu_reset_handler_base
+
+/* return the size of the SMMU context */
+func tegra186_get_smmu_ctx_offset
+ adr x0, __tegra186_smmu_context
+ adr x1, tegra186_cpu_reset_handler
+ sub x0, x0, x1
+ ret
+endfunc tegra186_get_smmu_ctx_offset
+
+/* set system suspend state before SC7 entry */
+func tegra186_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, __tegra186_system_suspend_state
+ adr x1, tegra186_cpu_reset_handler
+ sub x2, x0, x1 /* offset in TZDRAM */
+ mov x0, #TEGRA186_STATE_SYSTEM_SUSPEND
+ lsl x0, x0, #16
+ add x0, x0, #TEGRA186_STATE_SYSTEM_SUSPEND
+ str x0, [x3, x2] /* set value in TZDRAM */
+ dsb sy
+ ret
+endfunc tegra186_set_system_suspend_entry
diff --git a/plat/nvidia/tegra/soc/t186/platform_t186.mk b/plat/nvidia/tegra/soc/t186/platform_t186.mk
index c905323..fdeb886 100644
--- a/plat/nvidia/tegra/soc/t186/platform_t186.mk
+++ b/plat/nvidia/tegra/soc/t186/platform_t186.mk
@@ -11,18 +11,9 @@
ENABLE_ROC_FOR_ORDERING_CLIENT_REQUESTS := 1
$(eval $(call add_define,ENABLE_ROC_FOR_ORDERING_CLIENT_REQUESTS))
-RELOCATE_TO_BL31_BASE := 1
-$(eval $(call add_define,RELOCATE_TO_BL31_BASE))
-
ENABLE_CHIP_VERIFICATION_HARNESS := 0
$(eval $(call add_define,ENABLE_CHIP_VERIFICATION_HARNESS))
-ENABLE_SMMU_DEVICE := 1
-$(eval $(call add_define,ENABLE_SMMU_DEVICE))
-
-NUM_SMMU_DEVICES := 1
-$(eval $(call add_define,NUM_SMMU_DEVICES))
-
RESET_TO_BL31 := 1
PROGRAMMABLE_RESET_ADDRESS := 1
@@ -48,8 +39,10 @@
# platform files
PLAT_INCLUDES += -I${SOC_DIR}/drivers/include
-BL31_SOURCES += lib/cpus/aarch64/denver.S \
+BL31_SOURCES += drivers/ti/uart/aarch64/16550_console.S \
+ lib/cpus/aarch64/denver.S \
lib/cpus/aarch64/cortex_a57.S \
+ ${COMMON_DIR}/drivers/gpcdma/gpcdma.c \
${COMMON_DIR}/drivers/memctrl/memctrl_v2.c \
${COMMON_DIR}/drivers/smmu/smmu.c \
${SOC_DIR}/drivers/mce/mce.c \
@@ -64,3 +57,13 @@
${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
diff --git a/plat/nvidia/tegra/soc/t210/drivers/se/se_private.h b/plat/nvidia/tegra/soc/t210/drivers/se/se_private.h
index 0157747..be1f9cc 100644
--- a/plat/nvidia/tegra/soc/t210/drivers/se/se_private.h
+++ b/plat/nvidia/tegra/soc/t210/drivers/se/se_private.h
@@ -16,14 +16,16 @@
*/
/* 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_SCRATCH120_OFFSET 0xB38U
-#define PMC_SECURE_SCRATCH121_OFFSET 0xB3CU
-#define PMC_SECURE_SCRATCH122_OFFSET 0xB40U
-#define PMC_SECURE_SCRATCH123_OFFSET 0xB44U
+#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
@@ -32,6 +34,12 @@
#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
@@ -42,8 +50,24 @@
#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_REG_OFFSET 0x14U
#define SE_CONFIG_ENC_ALG_SHIFT 12
#define SE_CONFIG_ENC_ALG_AES_ENC \
((1U) << SE_CONFIG_ENC_ALG_SHIFT)
@@ -66,7 +90,7 @@
#define SE_CONFIG_DEC_ALG(x) \
((x) & ((0xFU) << SE_CONFIG_DEC_ALG_SHIFT))
-#define SE_CONFIG_DST_SHIFT 2
+#define SE_CONFIG_DST_SHIFT 2
#define SE_CONFIG_DST_MEMORY \
((0U) << SE_CONFIG_DST_SHIFT)
#define SE_CONFIG_DST_HASHREG \
@@ -80,33 +104,75 @@
#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 \
- ((0UL) << DRBG_MODE_SHIFT)
+ ((0U) << DRBG_MODE_SHIFT)
#define DRBG_MODE_FORCE_INSTANTION \
- ((1UL) << DRBG_MODE_SHIFT)
+ ((1U) << DRBG_MODE_SHIFT)
#define DRBG_MODE_FORCE_RESEED \
- ((2UL) << DRBG_MODE_SHIFT)
+ ((2U) << DRBG_MODE_SHIFT)
#define SE_RNG_CONFIG_MODE(x) \
- ((x) & ((0x3UL) << DRBG_MODE_SHIFT))
+ ((x) & ((0x3U) << DRBG_MODE_SHIFT))
#define DRBG_SRC_SHIFT 2
#define DRBG_SRC_NONE \
- ((0UL) << DRBG_SRC_SHIFT)
+ ((0U) << DRBG_SRC_SHIFT)
#define DRBG_SRC_ENTROPY \
- ((1UL) << DRBG_SRC_SHIFT)
+ ((1U) << DRBG_SRC_SHIFT)
#define DRBG_SRC_LFSR \
- ((2UL) << DRBG_SRC_SHIFT)
+ ((2U) << DRBG_SRC_SHIFT)
#define SE_RNG_SRC_CONFIG_MODE(x) \
- ((x) & ((0x3UL) << DRBG_SRC_SHIFT))
+ ((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_SHIFT 1
#define DRBG_RO_ENT_SRC_ENABLE \
((1U) << DRBG_RO_ENT_SRC_SHIFT)
#define DRBG_RO_ENT_SRC_DISABLE \
@@ -114,7 +180,7 @@
#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_SHIFT 0
#define DRBG_RO_ENT_SRC_LOCK_ENABLE \
((1U) << DRBG_RO_ENT_SRC_LOCK_SHIFT)
#define DRBG_RO_ENT_SRC_LOCK_DISABLE \
@@ -130,9 +196,97 @@
#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_OPERATION_SHIFT 0
#define SE_OP_ABORT \
((0x0U) << SE_OPERATION_SHIFT)
#define SE_OP_START \
@@ -146,11 +300,85 @@
#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_ENABLE_SHIFT 0
#define SE_CTX_SAVE_AUTO_DIS \
((0U) << SE_CTX_SAVE_AUTO_ENABLE_SHIFT)
#define SE_CTX_SAVE_AUTO_EN \
@@ -167,20 +395,22 @@
#define SE_CTX_SAVE_AUTO_LOCK(x) \
((x) & ((0x1U) << SE_CTX_SAVE_AUTO_LOCK_SHIFT))
-/* Current context save number of blocks */
+/* 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
+#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_OPERATION 0x540U
-#define SE_TZRAM_OP_MODE_SHIFT 1
+#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 \
@@ -188,7 +418,7 @@
#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_SHIFT 2
#define SE_TZRAM_OP_BUSY_OFF \
((0U) << SE_TZRAM_OP_BUSY_SHIFT)
#define SE_TZRAM_OP_BUSY_ON \
@@ -196,7 +426,7 @@
#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_SHIFT 0
#define SE_TZRAM_OP_REQ_IDLE \
((0U) << SE_TZRAM_OP_REQ_SHIFT)
#define SE_TZRAM_OP_REQ_INIT \
@@ -206,7 +436,7 @@
/* SE Interrupt */
#define SE_INT_STATUS_REG_OFFSET 0x10U
-#define SE_INT_OP_DONE_SHIFT 4
+#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 \
@@ -214,21 +444,188 @@
#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
+#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_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
******************************************************************************/
@@ -242,8 +639,21 @@
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/plat/nvidia/tegra/soc/t210/drivers/se/security_engine.c b/plat/nvidia/tegra/soc/t210/drivers/se/security_engine.c
index fa99db6..e0a0d6c 100644
--- a/plat/nvidia/tegra/soc/t210/drivers/se/security_engine.c
+++ b/plat/nvidia/tegra/soc/t210/drivers/se/security_engine.c
@@ -20,7 +20,8 @@
* Constants and Macros
******************************************************************************/
-#define TIMEOUT_100MS 100UL // Timeout in 100ms
+#define TIMEOUT_100MS 100U // Timeout in 100ms
+#define RNG_AES_KEY_INDEX 1
/*******************************************************************************
* Data structure and global variables
@@ -67,6 +68,15 @@
* #--------------------------------#
*/
+/* Known pattern data */
+static const uint32_t se_ctx_known_pattern_data[SE_CTX_KNOWN_PATTERN_SIZE_WORDS] = {
+ /* 128 bit AES block */
+ 0x0C0D0E0F,
+ 0x08090A0B,
+ 0x04050607,
+ 0x00010203,
+};
+
/* 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;
@@ -78,7 +88,7 @@
/* SE1 security engine device handle */
static tegra_se_dev_t se_dev_1 = {
.se_num = 1,
- /* setup base address for se */
+ /* 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,
@@ -86,12 +96,14 @@
.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 *)(TEGRA_TZRAM_CARVEOUT_BASE),
};
/* SE2 security engine device handle */
static tegra_se_dev_t se_dev_2 = {
.se_num = 2,
- /* setup base address for se */
+ /* 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,
@@ -99,8 +111,12 @@
.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
******************************************************************************/
@@ -186,35 +202,15 @@
}
/*
- * Verify the SE context save auto has been enabled.
- * SE_CTX_SAVE_AUTO.ENABLE == ENABLE
- * If the SE context save auto is not enabled, then set
- * the context save auto enable and lock the setting.
- * If the SE context save auto is not enabled and the
- * enable setting is locked, then return an error.
+ * Returns true if the SE engine is configured to perform SE context save in
+ * hardware.
*/
-static inline int32_t tegra_se_ctx_save_auto_enable(const tegra_se_dev_t *se_dev)
+static inline bool tegra_se_atomic_save_enabled(const tegra_se_dev_t *se_dev)
{
uint32_t val;
- int32_t ret = 0;
val = tegra_se_read_32(se_dev, SE_CTX_SAVE_AUTO_REG_OFFSET);
- if (SE_CTX_SAVE_AUTO_ENABLE(val) == SE_CTX_SAVE_AUTO_DIS) {
- if (SE_CTX_SAVE_AUTO_LOCK(val) == SE_CTX_SAVE_AUTO_LOCK_EN) {
- ERROR("%s: ERR: Cannot enable atomic. Write locked!\n",
- __func__);
- ret = -EACCES;
- }
-
- /* Program SE_CTX_SAVE_AUTO */
- if (ret == 0) {
- tegra_se_write_32(se_dev, SE_CTX_SAVE_AUTO_REG_OFFSET,
- SE_CTX_SAVE_AUTO_LOCK_EN |
- SE_CTX_SAVE_AUTO_EN);
- }
- }
-
- return ret;
+ return (SE_CTX_SAVE_AUTO_ENABLE(val) == SE_CTX_SAVE_AUTO_EN);
}
/*
@@ -259,14 +255,6 @@
/* Check that previous operation is finalized */
ret = tegra_se_operation_prepare(se_dev);
- /* Ensure HW atomic context save has been enabled
- * This should have been done at boot time.
- * SE_CTX_SAVE_AUTO.ENABLE == ENABLE
- */
- if (ret == 0) {
- ret = tegra_se_ctx_save_auto_enable(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
@@ -325,7 +313,8 @@
* 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)
+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;
@@ -351,7 +340,10 @@
tegra_se_make_data_coherent(se_dev);
/* Start hardware operation */
- tegra_se_write_32(se_dev, SE_OPERATION_REG_OFFSET, SE_OP_START);
+ 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);
@@ -361,6 +353,22 @@
}
/*
+ * 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.
@@ -381,7 +389,10 @@
se_dev->dst_ll_buf->last_buff_num = 0;
/* Configure random number generator */
- val = (DRBG_MODE_FORCE_RESEED | DRBG_SRC_ENTROPY);
+ 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 */
@@ -391,25 +402,562 @@
tegra_se_write_32(se_dev, SE_CONFIG_REG_OFFSET, val);
/* Perform hardware operation */
- ret = tegra_se_perform_operation(se_dev, 0);
+ 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;
+ /* First the modulus and then the exponent must be
+ * encrypted and saved. This is repeated for SLOT 0
+ * and SLOT 1. Hence the order:
+ * SLOT 0 exponent : RSA_KEY_INDEX : 0
+ * SLOT 0 modulus : RSA_KEY_INDEX : 1
+ * SLOT 1 exponent : RSA_KEY_INDEX : 2
+ * SLOT 1 modulus : RSA_KEY_INDEX : 3
+ */
+ const unsigned int key_index_mod[TEGRA_SE_RSA_KEYSLOT_COUNT][2] = {
+ /* RSA key slot 0 */
+ {SE_RSA_KEY_INDEX_SLOT0_EXP, SE_RSA_KEY_INDEX_SLOT0_MOD},
+ /* RSA key slot 1 */
+ {SE_RSA_KEY_INDEX_SLOT1_EXP, SE_RSA_KEY_INDEX_SLOT1_MOD},
+ };
+
+ 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 */
+ mmio_write_32((uint64_t)TEGRA_PMC_BASE + PMC_SECURE_SCRATCH117_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);
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);
+
+ /* 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.
@@ -417,21 +965,57 @@
int32_t tegra_se_suspend(void)
{
int32_t ret = 0;
+ uint32_t val = 0;
- /* Atomic context save se2 and pka1 */
- INFO("%s: SE2/PKA1 atomic context save\n", __func__);
- ret = tegra_se_context_save_atomic(&se_dev_2);
+ /* 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);
- /* Atomic context save se */
- if (ret == 0) {
- INFO("%s: SE1 atomic context save\n", __func__);
- ret = tegra_se_context_save_atomic(&se_dev_1);
- }
+ tegra_se_enable_clocks();
- if (ret == 0) {
- INFO("%s: SE atomic context save done\n", __func__);
+ if (tegra_se_atomic_save_enabled(&se_dev_2) &&
+ tegra_se_atomic_save_enabled(&se_dev_1)) {
+ /* Atomic context save se2 and pka1 */
+ INFO("%s: SE2/PKA1 atomic context save\n", __func__);
+ if (ret == 0) {
+ ret = tegra_se_context_save_atomic(&se_dev_2);
+ }
+
+ /* Atomic context save se */
+ if (ret == 0) {
+ INFO("%s: SE1 atomic context save\n", __func__);
+ ret = tegra_se_context_save_atomic(&se_dev_1);
+ }
+
+ if (ret == 0) {
+ INFO("%s: SE atomic context save done\n", __func__);
+ }
+ } else if (!tegra_se_atomic_save_enabled(&se_dev_2) &&
+ !tegra_se_atomic_save_enabled(&se_dev_1)) {
+ /* SW context save se2 and pka1 */
+ INFO("%s: SE2/PKA1 legacy(SW) context save\n", __func__);
+ if (ret == 0) {
+ ret = tegra_se_context_save_sw(&se_dev_2);
+ }
+
+ /* SW context save se */
+ if (ret == 0) {
+ INFO("%s: SE1 legacy(SW) context save\n", __func__);
+ ret = tegra_se_context_save_sw(&se_dev_1);
+ }
+
+ if (ret == 0) {
+ INFO("%s: SE SW context save done\n", __func__);
+ }
+ } else {
+ ERROR("%s: One SE set for atomic CTX save, the other is not\n",
+ __func__);
}
+ tegra_se_disable_clocks();
+
return ret;
}
@@ -445,6 +1029,7 @@
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);
@@ -465,6 +1050,8 @@
INFO("%s: SE TZRAM save done!\n", __func__);
}
+ tegra_se_disable_clocks();
+
return ret;
}
@@ -483,12 +1070,6 @@
DRBG_RO_ENT_SRC_ENABLE;
tegra_se_write_32(se_dev, SE_RNG_SRC_CONFIG_REG_OFFSET, val);
- /* Enable and lock the SE atomic context save setting */
- if (tegra_se_ctx_save_auto_enable(se_dev) != 0) {
- ERROR("%s: ERR: enable SE%d context save auto failed!\n",
- __func__, se_dev->se_num);
- }
-
/* Set a random value to SRK to initialize DRBG */
tegra_se_generate_srk(se_dev);
}
diff --git a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
index ed30ff4..f52d975 100644
--- a/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
+++ b/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c
@@ -104,41 +104,55 @@
if ((lvl == MPIDR_AFFLVL1) && (target == PSTATE_ID_CLUSTER_IDLE)) {
/* initialize the bpmp interface */
- (void)tegra_bpmp_init();
-
- /* Cluster idle */
- 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 idle entry is allowed */
- if ((ret != 0L) || (bpmp_reply != BPMP_CCx_ALLOWED)) {
+ ret = tegra_bpmp_init();
+ if (ret != 0U) {
/* Cluster idle not allowed */
target = PSCI_LOCAL_STATE_RUN;
+ } else {
+
+ /* Cluster idle */
+ 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 idle entry is allowed */
+ if ((ret != 0L) || (bpmp_reply != BPMP_CCx_ALLOWED)) {
+
+ /* Cluster idle not allowed */
+ target = PSCI_LOCAL_STATE_RUN;
+ }
}
} else if ((lvl == MPIDR_AFFLVL1) && (target == PSTATE_ID_CLUSTER_POWERDN)) {
/* initialize the bpmp interface */
- (void)tegra_bpmp_init();
-
- /* Cluster power-down */
- data[0] = (uint32_t)cpu;
- data[1] = TEGRA_PM_CC7;
- 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)) {
+ ret = tegra_bpmp_init();
+ if (ret != 0U) {
/* Cluster power down not allowed */
target = PSCI_LOCAL_STATE_RUN;
+ } else {
+
+ /* Cluster power-down */
+ data[0] = (uint32_t)cpu;
+ data[1] = TEGRA_PM_CC7;
+ 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)) &&
@@ -177,18 +191,8 @@
if (tegra_se_suspend() != 0) {
ret = PSCI_E_INTERN_FAIL;
}
-
- /* Save tzram contents */
- if (tegra_se_save_tzram() != 0) {
- ret = PSCI_E_INTERN_FAIL;
- }
}
- /* enter system suspend */
- if (ret == PSCI_E_SUCCESS) {
- tegra_fc_soc_powerdn(mpidr);
- }
-
} else if (stateid_afflvl1 == PSTATE_ID_CLUSTER_IDLE) {
assert(stateid_afflvl0 == PSTATE_ID_CORE_POWERDN);
@@ -217,6 +221,27 @@
return ret;
}
+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];
+
+ if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) {
+
+ if (tegra_chipid_is_t210_b01()) {
+ /* Save tzram contents */
+ tegra_se_save_tzram();
+ }
+
+ /* enter system suspend */
+ tegra_fc_soc_powerdn(mpidr);
+ }
+
+ return PSCI_E_SUCCESS;
+}
+
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();
diff --git a/plat/nvidia/tegra/soc/t210/platform_t210.mk b/plat/nvidia/tegra/soc/t210/platform_t210.mk
index a9ab0d8..e23d7e3 100644
--- a/plat/nvidia/tegra/soc/t210/platform_t210.mk
+++ b/plat/nvidia/tegra/soc/t210/platform_t210.mk
@@ -19,14 +19,15 @@
MAX_XLAT_TABLES := 10
$(eval $(call add_define,MAX_XLAT_TABLES))
-MAX_MMAP_REGIONS := 10
+MAX_MMAP_REGIONS := 15
$(eval $(call add_define,MAX_MMAP_REGIONS))
PLAT_INCLUDES += -I${SOC_DIR}/drivers/se
-BL31_SOURCES += lib/cpus/aarch64/cortex_a53.S \
+BL31_SOURCES += drivers/ti/uart/aarch64/16550_console.S \
+ lib/cpus/aarch64/cortex_a53.S \
lib/cpus/aarch64/cortex_a57.S \
- ${COMMON_DIR}/drivers/bpmp/bpmp.c \
+ ${COMMON_DIR}/drivers/bpmp/bpmp.c \
${COMMON_DIR}/drivers/flowctrl/flowctrl.c \
${COMMON_DIR}/drivers/memctrl/memctrl_v1.c \
${SOC_DIR}/plat_psci_handlers.c \
diff --git a/plat/socionext/synquacer/sq_bl31_setup.c b/plat/socionext/synquacer/sq_bl31_setup.c
index 2fac80f..fef84ef 100644
--- a/plat/socionext/synquacer/sq_bl31_setup.c
+++ b/plat/socionext/synquacer/sq_bl31_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -160,7 +160,7 @@
void bl31_plat_arch_setup(void)
{
static const mmap_region_t secure_partition_mmap[] = {
-#if ENABLE_SPM && SPM_DEPRECATED
+#if ENABLE_SPM && SPM_MM
MAP_REGION_FLAT(PLAT_SPM_BUF_BASE,
PLAT_SPM_BUF_SIZE,
MT_RW_DATA | MT_SECURE),
@@ -174,7 +174,7 @@
sq_mmap_setup(BL31_BASE, BL31_SIZE, secure_partition_mmap);
enable_mmu_el3(XLAT_TABLE_NC);
-#if ENABLE_SPM && SPM_DEPRECATED
+#if ENABLE_SPM && SPM_MM
memcpy((void *)SPM_SHIM_EXCEPTIONS_START,
(void *)SPM_SHIM_EXCEPTIONS_LMA,
(uintptr_t)SPM_SHIM_EXCEPTIONS_END -
diff --git a/plat/st/stm32mp1/bl2_io_storage.c b/plat/st/stm32mp1/bl2_io_storage.c
index 45a352e..8ccbc24 100644
--- a/plat/st/stm32mp1/bl2_io_storage.c
+++ b/plat/st/stm32mp1/bl2_io_storage.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -58,13 +58,26 @@
static uintptr_t storage_dev_handle;
static const io_dev_connector_t *mmc_dev_con;
-#define IMG_IDX_BL33 0
+static const io_block_spec_t bl32_block_spec = {
+ .offset = BL32_BASE,
+ .length = STM32MP1_BL32_SIZE
+};
+
+static const io_block_spec_t bl2_block_spec = {
+ .offset = BL2_BASE,
+ .length = STM32MP1_BL2_SIZE,
+};
static const struct stm32image_part_info bl33_partition_spec = {
.name = BL33_IMAGE_NAME,
.binary_type = BL33_BINARY_TYPE,
};
+enum {
+ IMG_IDX_BL33,
+ IMG_IDX_NUM
+};
+
static struct stm32image_device_info stm32image_dev_info_spec = {
.lba_size = MMC_BLOCK_SIZE,
.part_info[IMG_IDX_BL33] = {
@@ -73,19 +86,12 @@
},
};
-static io_block_spec_t stm32image_block_spec;
-
-static const io_dev_connector_t *stm32image_dev_con;
-
-static const io_block_spec_t bl32_block_spec = {
- .offset = BL32_BASE,
- .length = STM32MP1_BL32_SIZE
+static io_block_spec_t stm32image_block_spec = {
+ .offset = 0,
+ .length = 0,
};
-static const io_block_spec_t bl2_block_spec = {
- .offset = BL2_BASE,
- .length = STM32MP1_BL2_SIZE,
-};
+static const io_dev_connector_t *stm32image_dev_con;
static int open_dummy(const uintptr_t spec);
static int open_image(const uintptr_t spec);
@@ -158,85 +164,20 @@
if (boot_context->boot_interface_instance != 0U) {
INFO(" Instance %d\n", boot_context->boot_interface_instance);
}
-}
-
-static void print_reset_reason(void)
-{
- uint32_t rstsr = mmio_read_32(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 ((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_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 stm32mp1_io_setup(void)
{
int io_result __unused;
+ uint8_t idx;
+ struct stm32image_part_info *part;
struct stm32_sdmmc2_params params;
struct mmc_device_info device_info;
uintptr_t mmc_default_instance;
+ const partition_entry_t *entry;
boot_api_context_t *boot_context =
(boot_api_context_t *)stm32mp1_get_boot_ctx_address();
- print_reset_reason();
-
print_boot_device(boot_context);
if ((boot_context->boot_partition_used_toboot == 1U) ||
@@ -255,7 +196,7 @@
switch (boot_context->boot_interface_selected) {
case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_SD:
case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC:
- dmb();
+ dmbsy();
memset(¶ms, 0, sizeof(struct stm32_sdmmc2_params));
@@ -309,14 +250,19 @@
stm32image_dev_info_spec.device_size =
stm32_sdmmc2_mmc_get_device_size();
- stm32image_dev_info_spec.part_info[IMG_IDX_BL33].part_offset =
- get_partition_entry(BL33_IMAGE_NAME)->start;
- stm32image_dev_info_spec.part_info[IMG_IDX_BL33].bkp_offset =
- get_partition_entry(BL33_IMAGE_NAME)->length;
- stm32image_block_spec.offset = 0;
- stm32image_block_spec.length =
- get_partition_entry(BL33_IMAGE_NAME)->length;
+ 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;
+ }
/*
* Re-open MMC with io_mmc, for better perfs compared to
diff --git a/plat/st/stm32mp1/bl2_plat_setup.c b/plat/st/stm32mp1/bl2_plat_setup.c
index 6af65fd..a1ffd5a 100644
--- a/plat/st/stm32mp1/bl2_plat_setup.c
+++ b/plat/st/stm32mp1/bl2_plat_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -16,8 +16,8 @@
#include <drivers/delay_timer.h>
#include <drivers/generic_delay_timer.h>
#include <drivers/st/stm32_console.h>
+#include <drivers/st/stm32mp_pmic.h>
#include <drivers/st/stm32mp1_clk.h>
-#include <drivers/st/stm32mp1_pmic.h>
#include <drivers/st/stm32mp1_pwr.h>
#include <drivers/st/stm32mp1_ram.h>
#include <drivers/st/stm32mp1_rcc.h>
@@ -33,8 +33,95 @@
static struct console_stm32 console;
-void bl2_el3_early_platform_setup(u_register_t arg0, u_register_t arg1,
- u_register_t arg2, u_register_t arg3)
+static void print_reset_reason(void)
+{
+ uint32_t rstsr = mmio_read_32(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 ((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;
+ }
+
+ 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 ((rstsr & RCC_MP_RSTSCLRR_MPUP1RSTF) != 0U) {
+ INFO(" MPU Processor 1 Reset\n");
+ return;
+ }
+
+ 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)
{
stm32mp1_save_boot_ctx_address(arg0);
}
@@ -59,12 +146,38 @@
void bl2_el3_plat_arch_setup(void)
{
int32_t result;
- struct dt_node_info dt_dev_info;
+ struct dt_node_info dt_uart_info;
const char *board_model;
boot_api_context_t *boot_context =
(boot_api_context_t *)stm32mp1_get_boot_ctx_address();
uint32_t clk_rate;
+ mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
+ BL_CODE_END - BL_CODE_BASE,
+ MT_CODE | MT_SECURE);
+
+ /* Prevent corruption of preloaded BL32 */
+ mmap_add_region(BL32_BASE, BL32_BASE,
+ BL32_LIMIT - BL32_BASE,
+ MT_MEMORY | MT_RO | MT_SECURE);
+
+ /* Map non secure DDR for BL33 load and DDR training area restore */
+ mmap_add_region(STM32MP1_DDR_BASE,
+ STM32MP1_DDR_BASE,
+ STM32MP1_DDR_MAX_SIZE,
+ MT_MEMORY | MT_RW | MT_NS);
+
+ /* Prevent corruption of preloaded Device Tree */
+ mmap_add_region(DTB_BASE, DTB_BASE,
+ DTB_LIMIT - DTB_BASE,
+ MT_MEMORY | MT_RO | MT_SECURE);
+
+ configure_mmu();
+
+ if (dt_open_and_check() < 0) {
+ panic();
+ }
+
/*
* Disable the backup domain write protection.
* The protection is enable at each reset by hardware
@@ -88,28 +201,8 @@
mmio_clrbits_32(RCC_BASE + RCC_BDCR, RCC_BDCR_VSWRST);
}
- mmap_add_region(BL_CODE_BASE, BL_CODE_BASE,
- BL_CODE_END - BL_CODE_BASE,
- MT_CODE | MT_SECURE);
-
- /* Prevent corruption of preloaded BL32 */
- mmap_add_region(BL32_BASE, BL32_BASE,
- BL32_LIMIT - BL32_BASE,
- MT_MEMORY | MT_RO | MT_SECURE);
-
- /* Prevent corruption of preloaded Device Tree */
- mmap_add_region(DTB_BASE, DTB_BASE,
- DTB_LIMIT - DTB_BASE,
- MT_MEMORY | MT_RO | MT_SECURE);
-
- configure_mmu();
-
generic_delay_timer_init();
- if (dt_open_and_check() < 0) {
- panic();
- }
-
if (stm32mp1_clk_probe() < 0) {
panic();
}
@@ -118,12 +211,12 @@
panic();
}
- result = dt_get_stdout_uart_info(&dt_dev_info);
+ result = dt_get_stdout_uart_info(&dt_uart_info);
if ((result <= 0) ||
- (dt_dev_info.status == 0U) ||
- (dt_dev_info.clock < 0) ||
- (dt_dev_info.reset < 0)) {
+ (dt_uart_info.status == 0U) ||
+ (dt_uart_info.clock < 0) ||
+ (dt_uart_info.reset < 0)) {
goto skip_console_init;
}
@@ -131,25 +224,25 @@
goto skip_console_init;
}
- if (stm32mp1_clk_enable((unsigned long)dt_dev_info.clock) != 0) {
+ if (stm32mp1_clk_enable((unsigned long)dt_uart_info.clock) != 0) {
goto skip_console_init;
}
- stm32mp1_reset_assert((uint32_t)dt_dev_info.reset);
+ stm32mp1_reset_assert((uint32_t)dt_uart_info.reset);
udelay(2);
- stm32mp1_reset_deassert((uint32_t)dt_dev_info.reset);
+ stm32mp1_reset_deassert((uint32_t)dt_uart_info.reset);
mdelay(1);
- clk_rate = stm32mp1_clk_get_rate((unsigned long)dt_dev_info.clock);
+ clk_rate = stm32mp1_clk_get_rate((unsigned long)dt_uart_info.clock);
- if (console_stm32_register(dt_dev_info.base, clk_rate,
+ if (console_stm32_register(dt_uart_info.base, clk_rate,
STM32MP1_UART_BAUDRATE, &console) == 0) {
panic();
}
board_model = dt_get_board_model();
if (board_model != NULL) {
- NOTICE("%s\n", board_model);
+ NOTICE("Model: %s\n", board_model);
}
skip_console_init:
@@ -162,5 +255,7 @@
stm32mp1_arch_security_setup();
+ print_reset_reason();
+
stm32mp1_io_setup();
}
diff --git a/plat/st/stm32mp1/include/platform_def.h b/plat/st/stm32mp1/include/platform_def.h
index 1b4df16..6d3d36d 100644
--- a/plat/st/stm32mp1/include/platform_def.h
+++ b/plat/st/stm32mp1/include/platform_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -30,8 +30,8 @@
#define BL33_BINARY_TYPE U(0x0)
#define STM32MP1_PRIMARY_CPU U(0x0)
+#define STM32MP1_SECONDARY_CPU U(0x1)
-#define PLATFORM_CACHE_LINE_SIZE 64
#define PLATFORM_CLUSTER_COUNT ULL(1)
#define PLATFORM_CLUSTER0_CORE_COUNT U(2)
#define PLATFORM_CLUSTER1_CORE_COUNT U(0)
@@ -39,9 +39,9 @@
PLATFORM_CLUSTER0_CORE_COUNT)
#define PLATFORM_MAX_CPUS_PER_CLUSTER 2
-#define MAX_IO_DEVICES 4
-#define MAX_IO_HANDLES 4
-#define MAX_IO_BLOCK_DEVICES 1
+#define MAX_IO_DEVICES U(4)
+#define MAX_IO_HANDLES U(4)
+#define MAX_IO_BLOCK_DEVICES U(1)
/*******************************************************************************
* BL2 specific defines.
@@ -81,8 +81,8 @@
/*******************************************************************************
* 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 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
@@ -123,9 +123,6 @@
INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, \
GIC_HIGHEST_SEC_PRIORITY, \
grp, GIC_INTR_CFG_LEVEL), \
- INTR_PROP_DESC(STM32MP1_IRQ_TAMPSERRS, \
- GIC_HIGHEST_SEC_PRIORITY, \
- grp, GIC_INTR_CFG_LEVEL), \
INTR_PROP_DESC(STM32MP1_IRQ_AXIERRIRQ, \
GIC_HIGHEST_SEC_PRIORITY, \
grp, GIC_INTR_CFG_LEVEL), \
diff --git a/plat/st/stm32mp1/include/stm32mp1_dt.h b/plat/st/stm32mp1/include/stm32mp1_dt.h
index 19549ee..d5640c1 100644
--- a/plat/st/stm32mp1/include/stm32mp1_dt.h
+++ b/plat/st/stm32mp1/include/stm32mp1_dt.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -9,12 +9,16 @@
#include <stdbool.h>
+#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;
- bool status;
- bool sec_status;
+ uint32_t status;
};
/*******************************************************************************
@@ -23,13 +27,11 @@
int dt_open_and_check(void);
int fdt_get_address(void **fdt_addr);
bool fdt_check_node(int node);
-bool fdt_check_status(int node);
-bool fdt_check_secure_status(int node);
+uint32_t fdt_get_status(int node);
uint32_t fdt_read_uint32_default(int node, const char *prop_name,
uint32_t dflt_value);
int fdt_read_uint32_array(int node, const char *prop_name,
uint32_t *array, uint32_t count);
-int dt_set_pinctrl_config(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);
diff --git a/plat/st/stm32mp1/include/stm32mp1_private.h b/plat/st/stm32mp1/include/stm32mp1_private.h
index 3404bc6..04c9a9a 100644
--- a/plat/st/stm32mp1/include/stm32mp1_private.h
+++ b/plat/st/stm32mp1/include/stm32mp1_private.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -21,4 +21,8 @@
void stm32mp1_gic_pcpu_init(void);
void stm32mp1_gic_init(void);
+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);
+
#endif /* STM32MP1_PRIVATE_H */
diff --git a/plat/st/stm32mp1/include/stm32mp1_smc.h b/plat/st/stm32mp1/include/stm32mp1_smc.h
new file mode 100644
index 0000000..b872758
--- /dev/null
+++ b/plat/st/stm32mp1/include/stm32mp1_smc.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2016-2019, 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
+
+/* 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 4
+
+/* 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
+
+#endif /* STM32MP1_SMC_H */
diff --git a/plat/st/stm32mp1/platform.mk b/plat/st/stm32mp1/platform.mk
index 60852c6..4288f23 100644
--- a/plat/st/stm32mp1/platform.mk
+++ b/plat/st/stm32mp1/platform.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -24,8 +24,8 @@
PLAT_INCLUDES := -Iplat/st/stm32mp1/include/
# Device tree
-STM32_DTB_FILE_NAME ?= stm32mp157c-ev1.dtb
-FDT_SOURCES := $(addprefix fdts/, $(patsubst %.dtb,%.dts,$(STM32_DTB_FILE_NAME)))
+DTB_FILE_NAME ?= stm32mp157c-ev1.dtb
+FDT_SOURCES := $(addprefix fdts/, $(patsubst %.dtb,%.dts,$(DTB_FILE_NAME)))
DTC_FLAGS += -Wno-unit_address_vs_reg
include lib/libfdt/libfdt.mk
@@ -47,13 +47,14 @@
drivers/arm/tzc/tzc400.c \
drivers/delay_timer/delay_timer.c \
drivers/delay_timer/generic_delay_timer.c \
+ drivers/st/bsec/bsec.c \
drivers/st/clk/stm32mp1_clk.c \
drivers/st/clk/stm32mp1_clkfunc.c \
drivers/st/ddr/stm32mp1_ddr_helpers.c \
drivers/st/gpio/stm32_gpio.c \
- drivers/st/pmic/stm32_i2c.c \
- drivers/st/pmic/stm32mp1_pmic.c \
- drivers/st/pmic/stpmu1.c \
+ drivers/st/i2c/stm32_i2c.c \
+ drivers/st/pmic/stm32mp_pmic.c \
+ drivers/st/pmic/stpmic1.c \
drivers/st/reset/stm32mp1_reset.c \
plat/st/stm32mp1/stm32mp1_context.c \
plat/st/stm32mp1/stm32mp1_dt.c \
@@ -82,13 +83,13 @@
# Macros and rules to build TF binary
STM32_TF_ELF_LDFLAGS := --hash-style=gnu --as-needed
-STM32_DT_BASENAME := $(STM32_DTB_FILE_NAME:.dtb=)
+STM32_DT_BASENAME := $(DTB_FILE_NAME:.dtb=)
STM32_TF_STM32 := ${BUILD_PLAT}/tf-a-${STM32_DT_BASENAME}.stm32
STM32_TF_BINARY := $(STM32_TF_STM32:.stm32=.bin)
STM32_TF_MAPFILE := $(STM32_TF_STM32:.stm32=.map)
STM32_TF_LINKERFILE := $(STM32_TF_STM32:.stm32=.ld)
STM32_TF_ELF := $(STM32_TF_STM32:.stm32=.elf)
-STM32_TF_DTBFILE := ${BUILD_PLAT}/fdts/${STM32_DTB_FILE_NAME}
+STM32_TF_DTBFILE := ${BUILD_PLAT}/fdts/${DTB_FILE_NAME}
STM32_TF_OBJS := ${BUILD_PLAT}/stm32mp1.o
# Variables for use with stm32image
@@ -131,7 +132,7 @@
-DDTB_BIN_PATH=\"${STM32_TF_DTBFILE}\" \
-c plat/st/stm32mp1/stm32mp1.S -o $@
-${STM32_TF_LINKERFILE}: plat/st/stm32mp1/stm32mp1.ld.S
+${STM32_TF_LINKERFILE}: plat/st/stm32mp1/stm32mp1.ld.S ${BUILD_PLAT}
@echo " LDS $<"
${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} -P -E $< -o $@
diff --git a/plat/st/stm32mp1/services/bsec_svc.c b/plat/st/stm32mp1/services/bsec_svc.c
new file mode 100644
index 0000000..2a60e43
--- /dev/null
+++ b/plat/st/stm32mp1/services/bsec_svc.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform_def.h>
+
+#include <common/debug.h>
+#include <drivers/st/bsec.h>
+
+#include <stm32mp1_smc.h>
+
+#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 = 0;
+ result = bsec_write_otp(x3, x2);
+ break;
+ case STM32_SMC_READ_OTP:
+ *ret_otp_value = 0;
+ 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:
+ result = BSEC_ERROR;
+ break;
+ }
+
+ return result;
+}
diff --git a/plat/st/stm32mp1/services/bsec_svc.h b/plat/st/stm32mp1/services/bsec_svc.h
new file mode 100644
index 0000000..06752ef
--- /dev/null
+++ b/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 <stdint.h>
+
+/* 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/plat/st/stm32mp1/services/stm32mp1_svc_setup.c b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
new file mode 100644
index 0000000..72af9ff
--- /dev/null
+++ b/plat/st/stm32mp1/services/stm32mp1_svc_setup.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2014-2019, STMicroelectronics - All Rights Reserved
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#include <common/debug.h>
+#include <common/runtime_svc.h>
+#include <lib/psci/psci.h>
+#include <tools_share/uuid.h>
+
+#include <stm32mp1_smc.h>
+
+#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;
+
+ default:
+ WARN("Unimplemented STM32MP1 Service Call: 0x%x\n", smc_fid);
+ ret1 = SMC_UNK;
+ 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/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
index 9fde153..4188cc5 100644
--- a/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
+++ b/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk
@@ -1,5 +1,5 @@
#
-# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+# Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
@@ -19,3 +19,7 @@
# Generic PSCI
BL32_SOURCES += plat/common/plat_psci_common.c
+
+# stm32mp1 specific services
+BL32_SOURCES += plat/st/stm32mp1/services/bsec_svc.c \
+ plat/st/stm32mp1/services/stm32mp1_svc_setup.c
diff --git a/plat/st/stm32mp1/sp_min/sp_min_setup.c b/plat/st/stm32mp1/sp_min/sp_min_setup.c
index f541379..0d76fb7 100644
--- a/plat/st/stm32mp1/sp_min/sp_min_setup.c
+++ b/plat/st/stm32mp1/sp_min/sp_min_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -13,9 +13,12 @@
#include <common/bl_common.h>
#include <common/debug.h>
#include <context.h>
+#include <drivers/arm/gicv2.h>
#include <drivers/arm/tzc400.h>
#include <drivers/generic_delay_timer.h>
+#include <drivers/st/bsec.h>
#include <drivers/st/stm32_console.h>
+#include <drivers/st/stm32_gpio.h>
#include <drivers/st/stm32mp1_clk.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
#include <lib/el3_runtime/context_mgmt.h>
@@ -40,7 +43,7 @@
******************************************************************************/
void sp_min_plat_fiq_handler(uint32_t id)
{
- switch (id) {
+ switch (id & INT_ID_MASK) {
case STM32MP1_IRQ_TZC400:
ERROR("STM32MP1_IRQ_TZC400 generated\n");
panic();
@@ -50,7 +53,7 @@
panic();
break;
default:
- ERROR("SECURE IT handler not define for it : %i", id);
+ ERROR("SECURE IT handler not define for it : %u", id);
break;
}
}
@@ -80,7 +83,7 @@
void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1,
u_register_t arg2, u_register_t arg3)
{
- struct dt_node_info dt_dev_info;
+ struct dt_node_info dt_uart_info;
int result;
bl_params_t *params_from_bl2 = (bl_params_t *)arg0;
@@ -110,14 +113,18 @@
panic();
}
+ if (bsec_probe() != 0) {
+ panic();
+ }
+
if (stm32mp1_clk_probe() < 0) {
panic();
}
- result = dt_get_stdout_uart_info(&dt_dev_info);
+ result = dt_get_stdout_uart_info(&dt_uart_info);
- if ((result > 0) && dt_dev_info.status) {
- if (console_stm32_register(dt_dev_info.base, 0,
+ if ((result > 0) && (dt_uart_info.status != 0U)) {
+ if (console_stm32_register(dt_uart_info.base, 0,
STM32MP1_UART_BAUDRATE, &console) ==
0) {
panic();
@@ -142,6 +149,16 @@
generic_delay_timer_init();
stm32mp1_gic_init();
+
+ /* Unlock ETZPC securable peripherals */
+#define STM32MP1_ETZPC_BASE 0x5C007000U
+#define ETZPC_DECPROT0 0x010U
+ mmio_write_32(STM32MP1_ETZPC_BASE + ETZPC_DECPROT0, 0xFFFFFFFF);
+
+ /* Set GPIO bank Z as non secure */
+ for (uint32_t pin = 0U; pin < STM32MP_GPIOZ_PIN_MAX_COUNT; pin++) {
+ set_gpio_secure_cfg(GPIO_BANK_Z, pin, false);
+ }
}
void sp_min_plat_arch_setup(void)
diff --git a/plat/st/stm32mp1/stm32mp1_common.c b/plat/st/stm32mp1/stm32mp1_common.c
index b54f313..cd93d2e 100644
--- a/plat/st/stm32mp1/stm32mp1_common.c
+++ b/plat/st/stm32mp1/stm32mp1_common.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -12,6 +12,7 @@
#include <common/bl_common.h>
#include <common/debug.h>
#include <drivers/arm/gicv2.h>
+#include <dt-bindings/clock/stm32mp1-clks.h>
#include <lib/mmio.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat/common/platform.h>
@@ -39,26 +40,11 @@
MT_SECURE | \
MT_EXECUTE_NEVER)
-#define MAP_DDR MAP_REGION_FLAT(STM32MP1_DDR_BASE, \
- STM32MP1_DDR_MAX_SIZE, \
- MT_MEMORY | \
- MT_RW | \
- MT_SECURE | \
- MT_EXECUTE_NEVER)
-
-#define MAP_DDR_NS MAP_REGION_FLAT(STM32MP1_DDR_BASE, \
- STM32MP1_DDR_MAX_SIZE, \
- MT_MEMORY | \
- MT_RW | \
- MT_NS | \
- MT_EXECUTE_NEVER)
-
#if defined(IMAGE_BL2)
static const mmap_region_t stm32mp1_mmap[] = {
MAP_SRAM,
MAP_DEVICE1,
MAP_DEVICE2,
- MAP_DDR,
{0}
};
#endif
@@ -67,7 +53,6 @@
MAP_SRAM,
MAP_DEVICE1,
MAP_DEVICE2,
- MAP_DDR_NS,
{0}
};
#endif
@@ -102,3 +87,37 @@
{
return boot_ctx_address;
}
+
+uintptr_t stm32_get_gpio_bank_base(unsigned int bank)
+{
+ switch (bank) {
+ case GPIO_BANK_A ... GPIO_BANK_K:
+ return GPIOA_BASE + (bank * GPIO_BANK_OFFSET);
+ case GPIO_BANK_Z:
+ return GPIOZ_BASE;
+ default:
+ panic();
+ }
+}
+
+/* Return clock ID on success, negative value on error */
+unsigned long stm32_get_gpio_bank_clock(unsigned int bank)
+{
+ switch (bank) {
+ case GPIO_BANK_A ... GPIO_BANK_K:
+ return GPIOA + (bank - GPIO_BANK_A);
+ case GPIO_BANK_Z:
+ return GPIOZ;
+ default:
+ panic();
+ }
+}
+
+uint32_t stm32_get_gpio_bank_offset(unsigned int bank)
+{
+ if (bank == GPIO_BANK_Z) {
+ return 0;
+ } else {
+ return bank * GPIO_BANK_OFFSET;
+ }
+}
diff --git a/plat/st/stm32mp1/stm32mp1_def.h b/plat/st/stm32mp1/stm32mp1_def.h
index 15f0432..8cd5aeb 100644
--- a/plat/st/stm32mp1/stm32mp1_def.h
+++ b/plat/st/stm32mp1/stm32mp1_def.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -112,6 +112,39 @@
#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)
+#define GPIOJ_BASE U(0x5000B000)
+#define GPIOK_BASE U(0x5000C000)
+#define GPIOZ_BASE U(0x54004000)
+#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)
+#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
+
+/*******************************************************************************
* STM32MP1 UART
******************************************************************************/
#define USART1_BASE U(0x5C000000)
@@ -122,16 +155,21 @@
#define USART6_BASE U(0x44003000)
#define UART7_BASE U(0x40018000)
#define UART8_BASE U(0x40019000)
-#define STM32MP1_DEBUG_USART_BASE UART4_BASE
-#define STM32MP1_UART_BAUDRATE 115200
+#define STM32MP1_UART_BAUDRATE U(115200)
-/*******************************************************************************
- * STM32MP1 GIC-400
- ******************************************************************************/
-#define STM32MP1_GICD_BASE U(0xA0021000)
-#define STM32MP1_GICC_BASE U(0xA0022000)
-#define STM32MP1_GICH_BASE U(0xA0024000)
-#define STM32MP1_GICV_BASE U(0xA0026000)
+/* For UART crash console */
+#define STM32MP1_DEBUG_USART_BASE UART4_BASE
+/* UART4 on HSI@64MHz, TX on GPIOG11 Alternate 6 */
+#define STM32MP1_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
+#define DEBUG_UART_TX_EN_REG RCC_MP_APB1ENSETR
+#define DEBUG_UART_TX_EN RCC_MP_APB1ENSETR_UART4EN
/*******************************************************************************
* STM32MP1 TZC (TZ400)
@@ -149,10 +187,7 @@
#define STM32MP1_TZC_ETH_ID U(10)
#define STM32MP1_TZC_DAP_ID U(15)
-#define STM32MP1_MEMORY_NS 0
-#define STM32MP1_MEMORY_SECURE 1
-
-#define STM32MP1_FILTER_BIT_ALL 3
+#define STM32MP1_FILTER_BIT_ALL U(3)
/*******************************************************************************
* STM32MP1 SDMMC
@@ -168,6 +203,21 @@
#define STM32MP1_EMMC_HIGH_SPEED_MAX_FREQ 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 offsets */
+#define DATA0_OTP U(0)
+
+/* OTP mask */
+/* DATA0 */
+#define DATA0_OTP_SECURED BIT(6)
+
+/*******************************************************************************
* STM32MP1 TAMP
******************************************************************************/
#define TAMP_BASE U(0x5C00A000)
diff --git a/plat/st/stm32mp1/stm32mp1_dt.c b/plat/st/stm32mp1/stm32mp1_dt.c
index 29e936a..8493b87 100644
--- a/plat/st/stm32mp1/stm32mp1_dt.c
+++ b/plat/st/stm32mp1/stm32mp1_dt.c
@@ -1,10 +1,11 @@
/*
- * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
+#include <errno.h>
#include <libfdt.h>
@@ -17,135 +18,13 @@
#include <drivers/st/stm32mp1_ddr.h>
#include <drivers/st/stm32mp1_ram.h>
-#include <stm32mp1_dt.h>
-
-#define DT_GPIO_BANK_SHIFT 12
-#define DT_GPIO_BANK_MASK 0x1F000U
-#define DT_GPIO_PIN_SHIFT 8
-#define DT_GPIO_PIN_MASK 0xF00U
-#define DT_GPIO_MODE_MASK 0xFFU
-
static int fdt_checked;
static void *fdt = (void *)(uintptr_t)STM32MP1_DTB_BASE;
/*******************************************************************************
- * This function gets the pin settings from DT information.
- * When analyze and parsing is done, set the GPIO registers.
- * Return 0 on success, else return a negative FDT_ERR_xxx error code.
- ******************************************************************************/
-static int dt_set_gpio_config(int node)
-{
- const fdt32_t *cuint, *slewrate;
- int len, pinctrl_node, pinctrl_subnode;
- 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 = 0; 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;
-
- 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) {
- mode |= GPIO_OPEN_DRAIN;
- }
-
- fdt_for_each_subnode(pinctrl_subnode, fdt, pinctrl_node) {
- uint32_t bank_offset;
- const fdt32_t *cuint2;
-
- if (fdt_getprop(fdt, pinctrl_subnode,
- "gpio-controller", NULL) == NULL) {
- continue;
- }
-
- cuint2 = fdt_getprop(fdt, pinctrl_subnode, "reg", NULL);
- if (cuint2 == NULL) {
- continue;
- }
-
- if (bank == GPIO_BANK_Z) {
- bank_offset = 0;
- } else {
- bank_offset = bank * STM32_GPIO_BANK_OFFSET;
- }
-
- if (fdt32_to_cpu(*cuint2) == bank_offset) {
- int clk_id = fdt_get_clock_id(pinctrl_subnode);
-
- if (clk_id < 0) {
- return -FDT_ERR_NOTFOUND;
- }
-
- if (stm32mp1_clk_enable((unsigned long)clk_id) <
- 0) {
- return -FDT_ERR_BADVALUE;
- }
-
- break;
- }
- }
-
- set_gpio(bank, pin, mode, speed, pull, alternate);
- }
-
- return 0;
-}
-
-/*******************************************************************************
* This function checks device tree file with its header.
- * Returns 0 if success, and a negative value else.
+ * Returns 0 on success and a negative FDT error code on failure.
******************************************************************************/
int dt_open_and_check(void)
{
@@ -174,7 +53,7 @@
/*******************************************************************************
* This function check the presence of a node (generic use of fdt library).
- * Returns true if present, false else.
+ * Returns true if present, else return false.
******************************************************************************/
bool fdt_check_node(int node)
{
@@ -187,37 +66,30 @@
}
/*******************************************************************************
- * This function check the status of a node (generic use of fdt library).
- * Returns true if "okay" or missing, false else.
+ * This function return global node status (generic use of fdt library).
******************************************************************************/
-bool fdt_check_status(int node)
+uint32_t fdt_get_status(int node)
{
+ uint32_t status = DT_DISABLED;
int len;
const char *cchar;
cchar = fdt_getprop(fdt, node, "status", &len);
- if (cchar == NULL) {
- return true;
+ if ((cchar == NULL) ||
+ (strncmp(cchar, "okay", (size_t)len) == 0)) {
+ status |= DT_NON_SECURE;
}
- return strncmp(cchar, "okay", (size_t)len) == 0;
-}
-
-/*******************************************************************************
- * This function check the secure-status of a node (generic use of fdt library).
- * Returns true if "okay" or missing, false else.
- ******************************************************************************/
-bool fdt_check_secure_status(int node)
-{
- int len;
- const char *cchar;
-
cchar = fdt_getprop(fdt, node, "secure-status", &len);
if (cchar == NULL) {
- return true;
+ if (status == DT_NON_SECURE) {
+ status |= DT_SECURE;
+ }
+ } else if (strncmp(cchar, "okay", (size_t)len) == 0) {
+ status |= DT_SECURE;
}
- return strncmp(cchar, "okay", (size_t)len) == 0;
+ return status;
}
/*******************************************************************************
@@ -245,7 +117,7 @@
* (generic use of fdt library).
* It reads the values inside the device tree, from property name and node.
* The number of parameters is also indicated as entry parameter.
- * Returns 0 if success, and a negative value else.
+ * Returns 0 on success and a negative FDT error code on failure.
* If success, values are stored at the third parameter address.
******************************************************************************/
int fdt_read_uint32_array(int node, const char *prop_name, uint32_t *array,
@@ -274,52 +146,9 @@
}
/*******************************************************************************
- * This function gets the pin settings from DT information.
- * When analyze and parsing is done, set the GPIO registers.
- * Returns 0 if success, and a negative value else.
- ******************************************************************************/
-int dt_set_pinctrl_config(int node)
-{
- const fdt32_t *cuint;
- int lenp = 0;
- uint32_t i;
-
- if (!fdt_check_status(node)) {
- 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 phandle_node, phandle_subnode;
-
- phandle_node =
- fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint));
- if (phandle_node < 0) {
- return -FDT_ERR_NOTFOUND;
- }
-
- fdt_for_each_subnode(phandle_subnode, fdt, phandle_node) {
- int ret = dt_set_gpio_config(phandle_subnode);
-
- if (ret < 0) {
- return ret;
- }
- }
-
- cuint++;
- }
-
- return 0;
-}
-
-/*******************************************************************************
* 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 if success, and a negative value else.
+ * Returns 0 on success and a negative FDT error code on failure.
******************************************************************************/
int dt_set_stdout_pinctrl(void)
{
@@ -363,13 +192,12 @@
info->reset = -1;
}
- info->status = fdt_check_status(node);
- info->sec_status = fdt_check_secure_status(node);
+ info->status = fdt_get_status(node);
}
/*******************************************************************************
* This function retrieve the generic information from DT.
- * Returns node if success, and a negative value else.
+ * 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)
{
@@ -387,7 +215,7 @@
/*******************************************************************************
* This function gets the UART instance info of stdout from the DT.
- * Returns node if success, and a negative value else.
+ * Returns node on success and a negative FDT error code on failure.
******************************************************************************/
int dt_get_stdout_uart_info(struct dt_node_info *info)
{
@@ -448,7 +276,7 @@
/*******************************************************************************
* This function gets DDR size information from the DT.
- * Returns value in bytes if success, and STM32MP1_DDR_SIZE_DFLT else.
+ * Returns value in bytes on success, and 0 on failure.
******************************************************************************/
uint32_t dt_get_ddr_size(void)
{
@@ -457,11 +285,10 @@
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 STM32MP1_DDR_SIZE_DFLT;
+ return 0;
}
- return fdt_read_uint32_default(node, "st,mem-size",
- STM32MP1_DDR_SIZE_DFLT);
+ return fdt_read_uint32_default(node, "st,mem-size", 0);
}
/*******************************************************************************
diff --git a/plat/st/stm32mp1/stm32mp1_gic.c b/plat/st/stm32mp1/stm32mp1_gic.c
index fabed37..becb925 100644
--- a/plat/st/stm32mp1/stm32mp1_gic.c
+++ b/plat/st/stm32mp1/stm32mp1_gic.c
@@ -1,18 +1,28 @@
/*
- * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
+#include <libfdt.h>
+
#include <platform_def.h>
#include <common/bl_common.h>
+#include <common/debug.h>
#include <drivers/arm/gicv2.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <lib/utils.h>
#include <plat/common/platform.h>
+#include <stm32mp1_dt.h>
#include <stm32mp1_private.h>
+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.
@@ -22,19 +32,55 @@
PLATFORM_G0_PROPS(GICV2_INTR_GROUP0)
};
-static unsigned int target_mask_array[PLATFORM_CORE_COUNT];
+/* 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 const gicv2_driver_data_t platform_gic_data = {
- .gicd_base = STM32MP1_GICD_BASE,
- .gicc_base = STM32MP1_GICC_BASE,
+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();
diff --git a/plat/st/stm32mp1/stm32mp1_helper.S b/plat/st/stm32mp1/stm32mp1_helper.S
index 61c587f..8c2e1b6 100644
--- a/plat/st/stm32mp1/stm32mp1_helper.S
+++ b/plat/st/stm32mp1/stm32mp1_helper.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -12,11 +12,8 @@
#include <drivers/st/stm32_gpio.h>
#include <drivers/st/stm32mp1_rcc.h>
-#define GPIO_BANK_G_ADDRESS 0x50008000
-#define GPIO_TX_PORT 11
-#define GPIO_TX_SHIFT (GPIO_TX_PORT << 1)
-#define GPIO_TX_ALT_SHIFT ((GPIO_TX_PORT - GPIO_ALT_LOWER_LIMIT) << 2)
-#define STM32MP1_HSI_CLK 64000000
+#define GPIO_TX_SHIFT (DEBUG_UART_TX_GPIO_PORT << 1)
+#define GPIO_TX_ALT_SHIFT ((DEBUG_UART_TX_GPIO_PORT - GPIO_ALT_LOWER_LIMIT) << 2)
.globl platform_mem_init
.globl plat_report_exception
@@ -112,13 +109,13 @@
* ---------------------------------------------
*/
func plat_crash_console_init
- /* Enable GPIOs for UART4 TX */
- ldr r1, =(RCC_BASE + RCC_MP_AHB4ENSETR)
+ /* Enable GPIOs for UART TX */
+ ldr r1, =(RCC_BASE + DEBUG_UART_TX_GPIO_BANK_CLK_REG)
ldr r2, [r1]
- /* Configure GPIO G11 */
- orr r2, r2, #RCC_MP_AHB4ENSETR_GPIOGEN
+ /* Configure GPIO */
+ orr r2, r2, #DEBUG_UART_TX_GPIO_BANK_CLK_EN
str r2, [r1]
- ldr r1, =GPIO_BANK_G_ADDRESS
+ 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)
@@ -132,23 +129,22 @@
ldr r2, [r1, #GPIO_PUPD_OFFSET]
bic r2, r2, #(GPIO_PULL_MASK << GPIO_TX_SHIFT)
str r2, [r1, #GPIO_PUPD_OFFSET]
- /* Set alternate AF6 */
+ /* Set alternate */
ldr r2, [r1, #GPIO_AFRH_OFFSET]
bic r2, r2, #(GPIO_ALTERNATE_MASK << GPIO_TX_ALT_SHIFT)
- orr r2, r2, #(GPIO_ALTERNATE_6 << GPIO_TX_ALT_SHIFT)
+ orr r2, r2, #(DEBUG_UART_TX_GPIO_ALTERNATE << GPIO_TX_ALT_SHIFT)
str r2, [r1, #GPIO_AFRH_OFFSET]
-
- /* Enable UART clock, with HSI source */
- ldr r1, =(RCC_BASE + RCC_UART24CKSELR)
- mov r2, #RCC_UART24CKSELR_HSI
+ /* 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 + RCC_MP_APB1ENSETR)
+ ldr r1, =(RCC_BASE + DEBUG_UART_TX_EN_REG)
ldr r2, [r1]
- orr r2, r2, #RCC_MP_APB1ENSETR_UART4EN
+ orr r2, r2, #DEBUG_UART_TX_EN
str r2, [r1]
ldr r0, =STM32MP1_DEBUG_USART_BASE
- ldr r1, =STM32MP1_HSI_CLK
+ ldr r1, =STM32MP1_DEBUG_USART_CLK_FRQ
ldr r2, =STM32MP1_UART_BAUDRATE
b console_stm32_core_init
endfunc plat_crash_console_init
diff --git a/plat/st/stm32mp1/stm32mp1_pm.c b/plat/st/stm32mp1/stm32mp1_pm.c
index 85189ff..c0e9c4e 100644
--- a/plat/st/stm32mp1/stm32mp1_pm.c
+++ b/plat/st/stm32mp1/stm32mp1_pm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -23,11 +23,9 @@
#include <boot_api.h>
#include <stm32mp1_private.h>
-static uint32_t stm32_sec_entrypoint;
+static uintptr_t stm32_sec_entrypoint;
static uint32_t cntfrq_core0;
-#define SEND_SECURE_IT_TO_CORE_1 0x20000U
-
/*******************************************************************************
* STM32MP1 handler called when a CPU is about to enter standby.
* call by core 1 to enter in wfi
@@ -42,6 +40,7 @@
* Enter standby state
* dsb is good practice before using wfi to enter low power states
*/
+ isb();
dsb();
while (interrupt == GIC_SPURIOUS_INTERRUPT) {
wfi();
@@ -59,7 +58,7 @@
/*******************************************************************************
* 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
+ * call by core 0 to activate core 1
******************************************************************************/
static int stm32_pwr_domain_on(u_register_t mpidr)
{
@@ -102,8 +101,7 @@
}
/* Generate an IT to core 1 */
- mmio_write_32(STM32MP1_GICD_BASE + GICD_SGIR,
- SEND_SECURE_IT_TO_CORE_1 | ARM_IRQ_SEC_SGI_0);
+ gicv2_raise_sgi(ARM_IRQ_SEC_SGI_0, STM32MP1_SECONDARY_CPU);
return PSCI_E_SUCCESS;
}
diff --git a/plat/st/stm32mp1/stm32mp1_security.c b/plat/st/stm32mp1/stm32mp1_security.c
index 3992704..cfdbf31 100644
--- a/plat/st/stm32mp1/stm32mp1_security.c
+++ b/plat/st/stm32mp1/stm32mp1_security.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -65,22 +65,6 @@
******************************************************************************/
static void early_init_tzc400(void)
{
- uint32_t rstsr, rst_standby;
-
- rstsr = mmio_read_32(RCC_BASE + RCC_MP_RSTSCLRR);
-
- /* No warning if return from (C)STANDBY */
- rst_standby = rstsr &
- (RCC_MP_RSTSCLRR_STDBYRSTF | RCC_MP_RSTSCLRR_CSTDBYRSTF);
-
- if (stm32mp1_clk_is_enabled(TZC1) && (rst_standby == 0U)) {
- WARN("TZC400 port 1 clock already enable\n");
- }
-
- if (stm32mp1_clk_is_enabled(TZC2) && (rst_standby == 0U)) {
- WARN("TZC400 port 2 clock already enable\n");
- }
-
if (stm32mp1_clk_enable(TZC1) != 0) {
ERROR("Cannot enable TZC1 clock\n");
panic();
@@ -103,6 +87,7 @@
STM32MP1_DDR_BASE +
(STM32MP1_DDR_MAX_SIZE - 1U),
TZC_REGION_S_RDWR,
+ TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) |
TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID));
/* Raise an exception if a NS device tries to access secure memory */
diff --git a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c
index 5dd54d4..49cecd4 100644
--- a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c
+++ b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c
@@ -139,10 +139,10 @@
if ((mmio_read_32(spt->scfg + SCFG_THREAD_CTRL) & SCFG_THREAD_CTRL_DIR_MASK)
!= (dir << SCFG_THREAD_CTRL_DIR_SHIFT)) {
if (dir)
- ERROR("Trying to receive data on tx Thread %d\n",
+ ERROR("Trying to send data on RX Thread %d\n",
spt->id);
else
- ERROR("Trying to send data on rx Thread %d\n",
+ ERROR("Trying to receive data on TX Thread %d\n",
spt->id);
return -EINVAL;
}
@@ -163,6 +163,44 @@
}
/**
+ * 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 %d is corrupted, cannot send data\n", spt->id);
+ 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 %d\n", spt->id);
+ 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 %d\n", spt->id);
+ return -ETIMEDOUT;
+ }
+ WARN("Clearing message from thread %d\n", spt->id);
+ 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
diff --git a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h
index 2d987f8..6c4f5df 100644
--- a/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h
+++ b/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h
@@ -44,6 +44,15 @@
*
* 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);
/**
diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci.c b/plat/ti/k3/common/drivers/ti_sci/ti_sci.c
index b211bdf..4a33d34 100644
--- a/plat/ti/k3/common/drivers/ti_sci/ti_sci.c
+++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci.c
@@ -158,6 +158,13 @@
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) {
@@ -165,6 +172,7 @@
return ret;
}
+ /* Get the response */
ret = ti_sci_get_response(xfer, SP_RESPONSE);
if (ret) {
ERROR("Failed to get response (%d)\n", ret);
@@ -1455,6 +1463,169 @@
*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,
+ TI_SCI_FLAG_REQ_ACK_ON_PROCESSED,
+ &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;
+ }
+
+ if (!ti_sci_is_response_ack(&resp))
+ return -ENODEV;
+
+ return 0;
+}
+
+/**
+ * ti_sci_proc_shutdown() - Shutdown Processor without waiting for ACKs
+ *
+ * @proc_id: Processor ID this request is for
+ * @dev_id: Device identifier this request is for
+ *
+ * Return: 0 if all goes well, else appropriate error message
+ */
+int ti_sci_proc_shutdown(uint8_t proc_id, uint32_t dev_id)
+{
+ struct ti_sci_msg_req_wait_proc_boot_status wait_req;
+ struct ti_sci_msg_req_set_device_state set_req;
+ /*
+ * We will not be waiting for this response, but declare one anyway
+ * to pass to the setup function so the checks will still pass
+ */
+ struct ti_sci_msg_hdr resp;
+
+ struct ti_sci_xfer xfer;
+ int ret;
+
+ /* Start by sending wait command */
+
+ /* Setup with NORESPONSE flag to keep response queue clean */
+ ret = ti_sci_setup_one_xfer(TISCI_MSG_WAIT_PROC_BOOT_STATUS,
+ TI_SCI_FLAG_REQ_GENERIC_NORESPONSE,
+ &wait_req, sizeof(wait_req),
+ &resp, sizeof(resp),
+ &xfer);
+ if (ret) {
+ ERROR("Message alloc failed (%d)\n", ret);
+ return ret;
+ }
+
+ wait_req.processor_id = proc_id;
+ /*
+ * Wait maximum time to give us the best chance to get
+ * to WFI before this command timeouts
+ */
+ wait_req.delay_before_iterations_us = UINT8_MAX;
+ wait_req.num_wait_iterations = UINT8_MAX;
+ wait_req.delay_per_iteration_us = UINT8_MAX; /* TODO: optimize time */
+ wait_req.num_match_iterations = 2;
+ wait_req.status_flags_1_set_all_wait = 0;
+ /* Wait for either WFE or WFI */
+ wait_req.status_flags_1_set_any_wait = PROC_BOOT_STATUS_FLAG_ARMV8_WFE |
+ PROC_BOOT_STATUS_FLAG_ARMV8_WFI;
+ wait_req.status_flags_1_clr_all_wait = 0;
+ wait_req.status_flags_1_clr_any_wait = 0;
+
+ /* Send wait message */
+ ret = k3_sec_proxy_send(SP_HIGH_PRIORITY, &xfer.tx_message);
+ if (ret) {
+ ERROR("Message sending failed (%d)\n", ret);
+ return ret;
+ }
+
+ /* Now queue up the shutdown request */
+ ret = ti_sci_setup_one_xfer(TI_SCI_MSG_SET_DEVICE_STATE,
+ TI_SCI_FLAG_REQ_GENERIC_NORESPONSE,
+ &set_req, sizeof(set_req),
+ &resp, sizeof(resp),
+ &xfer);
+ if (ret) {
+ ERROR("Message alloc failed (%d)\n", ret);
+ return ret;
+ }
+
+ set_req.id = dev_id;
+ set_req.state = MSG_DEVICE_SW_STATE_AUTO_OFF;
+
+ /* Send shutdown message */
+ ret = k3_sec_proxy_send(SP_HIGH_PRIORITY, &xfer.tx_message);
+ if (ret) {
+ ERROR("Message sending failed (%d)\n", ret);
+ return ret;
+ }
+
+ /* Return without waiting for responses */
return 0;
}
diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci.h b/plat/ti/k3/common/drivers/ti_sci/ti_sci.h
index 1176b00..d07ee61 100644
--- a/plat/ti/k3/common/drivers/ti_sci/ti_sci.h
+++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci.h
@@ -179,6 +179,7 @@
* 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
*
* NOTE: for all these functions, the following are generic in nature:
* @proc_id: Processor ID
@@ -197,6 +198,15 @@
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_shutdown(uint8_t proc_id, uint32_t dev_id);
/**
* ti_sci_init() - Basic initialization
diff --git a/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h b/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h
index c6d76d7..a921e51 100644
--- a/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h
+++ b/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h
@@ -46,6 +46,7 @@
#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
@@ -647,4 +648,52 @@
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/plat/ti/k3/common/k3_bl31_setup.c b/plat/ti/k3/common/k3_bl31_setup.c
index 3fa11b2..78fb696 100644
--- a/plat/ti/k3/common/k3_bl31_setup.c
+++ b/plat/ti/k3/common/k3_bl31_setup.c
@@ -23,8 +23,7 @@
const mmap_region_t plat_k3_mmap[] = {
MAP_REGION_FLAT(SHARED_RAM_BASE, SHARED_RAM_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
MAP_REGION_FLAT(K3_USART_BASE_ADDRESS, K3_USART_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
- MAP_REGION_FLAT(K3_GICD_BASE, K3_GICD_SIZE, MT_DEVICE | MT_RW | MT_SECURE),
- MAP_REGION_FLAT(K3_GICR_BASE, K3_GICR_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(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),
@@ -116,7 +115,7 @@
void bl31_platform_setup(void)
{
- k3_gic_driver_init(K3_GICD_BASE, K3_GICR_BASE);
+ k3_gic_driver_init(K3_GIC_BASE);
k3_gic_init();
ti_sci_init();
diff --git a/plat/ti/k3/common/k3_gicv3.c b/plat/ti/k3/common/k3_gicv3.c
index b7c7880..1932eaa 100644
--- a/plat/ti/k3/common/k3_gicv3.c
+++ b/plat/ti/k3/common/k3_gicv3.c
@@ -6,10 +6,12 @@
#include <platform_def.h>
+#include <assert.h>
#include <common/bl_common.h>
#include <common/interrupt_props.h>
#include <drivers/arm/gicv3.h>
#include <lib/utils.h>
+#include <lib/mmio.h>
#include <plat/common/platform.h>
#include <k3_gicv3.h>
@@ -35,8 +37,25 @@
.mpidr_to_core_pos = k3_mpidr_to_core_pos,
};
-void k3_gic_driver_init(uintptr_t gicd_base, uintptr_t gicr_base)
+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
diff --git a/plat/ti/k3/common/k3_psci.c b/plat/ti/k3/common/k3_psci.c
index cb75bf6..235e639 100644
--- a/plat/ti/k3/common/k3_psci.c
+++ b/plat/ti/k3/common/k3_psci.c
@@ -81,15 +81,16 @@
void k3_pwr_domain_off(const psci_power_state_t *target_state)
{
- int core_id, device, ret;
+ int core_id, proc, device, ret;
/* Prevent interrupts from spuriously waking up this cpu */
k3_gic_cpuif_disable();
core_id = plat_my_core_pos();
+ proc = PLAT_PROC_START_ID + core_id;
device = PLAT_PROC_DEVICE_START_ID + core_id;
- ret = ti_sci_device_put(device);
+ ret = ti_sci_proc_shutdown(proc, device);
if (ret) {
ERROR("Request to stop core failed: %d\n", ret);
return;
diff --git a/plat/ti/k3/common/plat_common.mk b/plat/ti/k3/common/plat_common.mk
index 9b3e7d8..c91a035 100644
--- a/plat/ti/k3/common/plat_common.mk
+++ b/plat/ti/k3/common/plat_common.mk
@@ -30,6 +30,10 @@
TI_16550_MDR_QUIRK := 1
$(eval $(call add_define,TI_16550_MDR_QUIRK))
+# 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
diff --git a/plat/ti/k3/include/k3_gicv3.h b/plat/ti/k3/include/k3_gicv3.h
index 52f34ff..2329a16 100644
--- a/plat/ti/k3/include/k3_gicv3.h
+++ b/plat/ti/k3/include/k3_gicv3.h
@@ -9,7 +9,7 @@
#include <stdint.h>
-void k3_gic_driver_init(uintptr_t gicd_base, uintptr_t gicr_base);
+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);
diff --git a/plat/ti/k3/include/platform_def.h b/plat/ti/k3/include/platform_def.h
index 5d563b6..f1511c1 100644
--- a/plat/ti/k3/include/platform_def.h
+++ b/plat/ti/k3/include/platform_def.h
@@ -136,10 +136,6 @@
#define K3_USART_CLK_SPEED 48000000
#endif
-#ifndef K3_USART_BAUD
-#define K3_USART_BAUD 115200
-#endif
-
/* Crash console defaults */
#define CRASH_CONSOLE_BASE K3_USART_BASE_ADDRESS
#define CRASH_CONSOLE_CLK K3_USART_CLK_SPEED
@@ -189,10 +185,8 @@
INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, grp, \
GIC_INTR_CFG_EDGE)
-#define K3_GICD_BASE 0x01800000
-#define K3_GICD_SIZE 0x10000
-#define K3_GICR_BASE 0x01880000
-#define K3_GICR_SIZE 0x100000
+#define K3_GIC_BASE 0x01800000
+#define K3_GIC_SIZE 0x200000
#define SEC_PROXY_DATA_BASE 0x32C00000
#define SEC_PROXY_DATA_SIZE 0x80000
diff --git a/readme.rst b/readme.rst
index 1f02bf1..5404e74 100644
--- a/readme.rst
+++ b/readme.rst
@@ -194,19 +194,21 @@
- Allwinner sun50i_64 and sun50i_h6
- Amlogic Meson S905 (GXBB)
-- ARM SGI-575 and SGM-775
+- Arm SGI-575, SGI Clark.A, SGI Clark.H and SGM-775
+- Arm NeoVerse N1 System Development Platform
- HiKey, HiKey960 and Poplar boards
-- Marvell Armada 8K
+- Marvell Armada 3700 and 8K
- MediaTek MT6795 and MT8173 SoCs
-- NVidia T132, T186 and T210 SoCs
-- NXP QorIQ LS1043A, i.MX8QX, i.MX8QM and i.MX7Solo WaRP7
-- QEMU emulator
-- Raspberry Pi 3 board
+- NVIDIA T132, T186 and T210 SoCs
+- NXP QorIQ LS1043A, i.MX8MQ, i.MX8QX, i.MX8QM and i.MX7Solo WaRP7
+- QEMU
+- Raspberry Pi 3
+- R-Car Generation 3
- RockChip RK3328, RK3368 and RK3399 SoCs
- Socionext UniPhier SoC family and SynQuacer SC2A11 SoCs
- STMicroelectronics STM32MP1
- Texas Instruments K3 SoCs
-- Xilinx Zynq UltraScale + MPSoC
+- Xilinx Versal and Zynq UltraScale + MPSoC
Still to come
~~~~~~~~~~~~~
@@ -260,7 +262,7 @@
--------------
-*Copyright (c) 2013-2018, Arm Limited and Contributors. All rights reserved.*
+*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
diff --git a/services/spd/trusty/smcall.h b/services/spd/trusty/smcall.h
index 742c8c4..9c1c38c 100644
--- a/services/spd/trusty/smcall.h
+++ b/services/spd/trusty/smcall.h
@@ -7,69 +7,68 @@
#ifndef SMCALL_H
#define SMCALL_H
-#define SMC_NUM_ENTITIES 64
-#define SMC_NUM_ARGS 4
-#define SMC_NUM_PARAMS (SMC_NUM_ARGS - 1)
+#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) & 0x80000000)
-#define SMC_IS_SMC64(smc_nr) ((smc_nr) & 0x40000000)
-#define SMC_ENTITY(smc_nr) (((smc_nr) & 0x3F000000) >> 24)
-#define SMC_FUNCTION(smc_nr) ((smc_nr) & 0x0000FFFF)
+#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) \
- (((((unsigned int) (fastcall)) & 0x1) << 31) | \
- (((smc64) & 0x1) << 30) | \
- (((entity) & 0x3F) << 24) | \
- ((fn) & 0xFFFF) \
- )
+ (((((uint32_t)(fastcall)) & 0x1U) << 31U) | \
+ (((smc64) & 0x1U) << 30U) | \
+ (((entity) & 0x3FU) << 24U) | \
+ ((fn) & 0xFFFFU))
-#define SMC_FASTCALL_NR(entity, fn) SMC_NR((entity), (fn), 1, 0)
-#define SMC_FASTCALL64_NR(entity, fn) SMC_NR((entity), (fn), 1, 1)
-#define SMC_YIELDCALL_NR(entity, fn) SMC_NR((entity), (fn), 0, 0)
-#define SMC_YIELDCALL64_NR(entity, fn) SMC_NR((entity), (fn), 0, 1)
+#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 0 /* ARM Architecture calls */
-#define SMC_ENTITY_CPU 1 /* CPU Service calls */
-#define SMC_ENTITY_SIP 2 /* SIP Service calls */
-#define SMC_ENTITY_OEM 3 /* OEM Service calls */
-#define SMC_ENTITY_STD 4 /* Standard Service calls */
-#define SMC_ENTITY_RESERVED 5 /* Reserved for future use */
-#define SMC_ENTITY_TRUSTED_APP 48 /* Trusted Application calls */
-#define SMC_ENTITY_TRUSTED_OS 50 /* Trusted OS calls */
-#define SMC_ENTITY_LOGGING 51 /* Used for secure -> nonsecure logging */
-#define SMC_ENTITY_SECURE_MONITOR 60 /* Trusted OS calls internal to secure monitor */
+#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, 0)
-#define SMC_YC_NOP SMC_YIELDCALL_NR (SMC_ENTITY_SECURE_MONITOR, 1)
+#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, 0)
+#define SMC_YC_NS_RETURN SMC_YIELDCALL_NR (SMC_ENTITY_SECURE_MONITOR, 0U)
-#define SMC_FC_RESERVED SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 0)
-#define SMC_FC_FIQ_EXIT SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 1)
-#define SMC_FC_REQUEST_FIQ SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 2)
-#define SMC_FC_GET_NEXT_IRQ SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 3)
-#define SMC_FC_FIQ_ENTER SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 4)
+#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, 5)
-#define SMC_FC64_GET_FIQ_REGS SMC_FASTCALL64_NR (SMC_ENTITY_SECURE_MONITOR, 6)
+#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, 7)
-#define SMC_FC_CPU_RESUME SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 8)
+#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, 9)
-#define SMC_FC_GET_VERSION_STR SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 10)
+#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, 20)
-#define SMC_YC_VIRTIO_START SMC_YIELDCALL_NR(SMC_ENTITY_TRUSTED_OS, 21)
-#define SMC_YC_VIRTIO_STOP SMC_YIELDCALL_NR(SMC_ENTITY_TRUSTED_OS, 22)
+#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, 23)
-#define SMC_YC_VDEV_KICK_VQ SMC_YIELDCALL_NR(SMC_ENTITY_TRUSTED_OS, 24)
-#define SMC_YC_SET_ROT_PARAMS SMC_YIELDCALL_NR(SMC_ENTITY_TRUSTED_OS, 65535)
+#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)
#endif /* SMCALL_H */
diff --git a/services/spd/trusty/trusty.c b/services/spd/trusty/trusty.c
index c9d73f0..0305143 100644
--- a/services/spd/trusty/trusty.c
+++ b/services/spd/trusty/trusty.c
@@ -21,7 +21,10 @@
#include "smcall.h"
/* macro to check if Hypervisor is enabled in the HCR_EL2 register */
-#define HYP_ENABLE_FLAG 0x286001
+#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);
@@ -32,7 +35,7 @@
cpu_context_t cpu_ctx;
void *saved_sp;
uint32_t saved_security_state;
- int fiq_handler_active;
+ int32_t fiq_handler_active;
uint64_t fiq_handler_pc;
uint64_t fiq_handler_cpsr;
uint64_t fiq_handler_sp;
@@ -43,7 +46,7 @@
struct trusty_stack secure_stack;
};
-struct args {
+struct smc_args {
uint64_t r0;
uint64_t r1;
uint64_t r2;
@@ -56,8 +59,8 @@
static struct trusty_cpu_ctx trusty_cpu_ctx[PLATFORM_CORE_COUNT];
-struct args trusty_init_context_stack(void **sp, void *new_stack);
-struct args trusty_context_switch_helper(void **sp, void *smc_params);
+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;
@@ -66,37 +69,37 @@
return &trusty_cpu_ctx[plat_my_core_pos()];
}
-static uint32_t is_hypervisor_mode(void)
+static bool is_hypervisor_mode(void)
{
uint64_t hcr = read_hcr();
- return !!(hcr & HYP_ENABLE_FLAG);
+ return ((hcr & HYP_ENABLE_FLAG) != 0U) ? true : false;
}
-static struct args trusty_context_switch(uint32_t security_state, uint64_t r0,
+static struct smc_args trusty_context_switch(uint32_t security_state, uint64_t r0,
uint64_t r1, uint64_t r2, uint64_t r3)
{
- struct args ret;
+ 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);
- ret.r7 = 0;
+ 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);
- ret.r7 = SMC_GET_GP(ctx_smc, CTX_GPREG_X7);
+ assert(ctx_smc != NULL);
+ args.r7 = SMC_GET_GP(ctx_smc, CTX_GPREG_X7);
}
/* r4, r5, r6 reserved for future use. */
- ret.r6 = 0;
- ret.r5 = 0;
- ret.r4 = 0;
- ret.r3 = r3;
- ret.r2 = r2;
- ret.r1 = r1;
- ret.r0 = r0;
+ 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
@@ -109,9 +112,9 @@
cm_el1_sysregs_context_save(security_state);
ctx->saved_security_state = security_state;
- ret = trusty_context_switch_helper(&ctx->saved_sp, &ret);
+ ret_args = trusty_context_switch_helper(&ctx->saved_sp, &args);
- assert(ctx->saved_security_state == !security_state);
+ 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)
@@ -119,7 +122,7 @@
cm_set_next_eret_context(security_state);
- return ret;
+ return ret_args;
}
static uint64_t trusty_fiq_handler(uint32_t id,
@@ -127,29 +130,29 @@
void *handle,
void *cookie)
{
- struct args ret;
+ 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) {
+ if (ret.r0 != 0U) {
SMC_RET0(handle);
}
- if (ctx->fiq_handler_active) {
+ if (ctx->fiq_handler_active != 0) {
INFO("%s: fiq handler already active\n", __func__);
SMC_RET0(handle);
}
ctx->fiq_handler_active = 1;
- memcpy(&ctx->fiq_gpregs, get_gpregs_ctx(handle), sizeof(ctx->fiq_gpregs));
+ (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_sysregs_ctx(handle), CTX_SP_EL1);
write_ctx_reg(get_sysregs_ctx(handle), CTX_SP_EL1, ctx->fiq_handler_sp);
- cm_set_elr_spsr_el3(NON_SECURE, ctx->fiq_handler_pc, ctx->fiq_handler_cpsr);
+ cm_set_elr_spsr_el3(NON_SECURE, ctx->fiq_handler_pc, (uint32_t)ctx->fiq_handler_cpsr);
SMC_RET0(handle);
}
@@ -159,9 +162,9 @@
{
struct trusty_cpu_ctx *ctx;
- if (cpu >= PLATFORM_CORE_COUNT) {
+ if (cpu >= (uint64_t)PLATFORM_CORE_COUNT) {
ERROR("%s: cpu %lld >= %d\n", __func__, cpu, PLATFORM_CORE_COUNT);
- return SM_ERR_INVALID_PARAMETERS;
+ return (uint64_t)SM_ERR_INVALID_PARAMETERS;
}
ctx = &trusty_cpu_ctx[cpu];
@@ -182,16 +185,16 @@
static uint64_t trusty_fiq_exit(void *handle, uint64_t x1, uint64_t x2, uint64_t x3)
{
- struct args ret;
+ struct smc_args ret;
struct trusty_cpu_ctx *ctx = get_trusty_ctx();
- if (!ctx->fiq_handler_active) {
+ if (ctx->fiq_handler_active == 0) {
NOTICE("%s: fiq handler not active\n", __func__);
- SMC_RET1(handle, SM_ERR_INVALID_PARAMETERS);
+ 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 != 1) {
+ if (ret.r0 != 1U) {
INFO("%s(%p) SMC_FC_FIQ_EXIT returned unexpected value, %lld\n",
__func__, handle, ret.r0);
}
@@ -205,10 +208,10 @@
* x1-x4 and x8-x17 need to be restored here because smc_handler64
* corrupts them (el1 code also restored them).
*/
- memcpy(get_gpregs_ctx(handle), &ctx->fiq_gpregs, sizeof(ctx->fiq_gpregs));
+ (void)memcpy(get_gpregs_ctx(handle), &ctx->fiq_gpregs, sizeof(ctx->fiq_gpregs));
ctx->fiq_handler_active = 0;
write_ctx_reg(get_sysregs_ctx(handle), CTX_SP_EL1, ctx->fiq_sp_el1);
- cm_set_elr_spsr_el3(NON_SECURE, ctx->fiq_pc, ctx->fiq_cpsr);
+ cm_set_elr_spsr_el3(NON_SECURE, ctx->fiq_pc, (uint32_t)ctx->fiq_cpsr);
SMC_RET0(handle);
}
@@ -222,8 +225,8 @@
void *handle,
u_register_t flags)
{
- struct args ret;
- uint32_t vmid = 0;
+ struct smc_args ret;
+ uint32_t vmid = 0U;
entry_point_info_t *ep_info = bl31_plat_get_next_image_ep_info(SECURE);
/*
@@ -231,10 +234,12 @@
* Verified Boot is not even supported and returning success here
* would not compromise the boot process.
*/
- if (!ep_info && (smc_fid == SMC_YC_SET_ROT_PARAMS)) {
+ if ((ep_info == NULL) && (smc_fid == SMC_YC_SET_ROT_PARAMS)) {
SMC_RET1(handle, 0);
- } else if (!ep_info) {
+ } else if (ep_info == NULL) {
SMC_RET1(handle, SMC_UNK);
+ } else {
+ ; /* do nothing */
}
if (is_caller_secure(flags)) {
@@ -279,12 +284,11 @@
static int32_t trusty_init(void)
{
- void el3_exit(void);
entry_point_info_t *ep_info;
- struct args zero_args = {0};
+ struct smc_args zero_args = {0};
struct trusty_cpu_ctx *ctx = get_trusty_ctx();
uint32_t cpu = plat_my_core_pos();
- int reg_width = GET_RW(read_ctx_reg(get_el3state_ctx(&ctx->cpu_ctx),
+ uint64_t reg_width = GET_RW(read_ctx_reg(get_el3state_ctx(&ctx->cpu_ctx),
CTX_SPSR_EL3));
/*
@@ -292,7 +296,7 @@
* failure.
*/
ep_info = bl31_plat_get_next_image_ep_info(SECURE);
- assert(ep_info);
+ assert(ep_info != NULL);
fpregs_context_save(get_fpregs_ctx(cm_get_context(NON_SECURE)));
cm_el1_sysregs_context_save(NON_SECURE);
@@ -304,7 +308,7 @@
* Adjust secondary cpu entry point for 32 bit images to the
* end of exception vectors
*/
- if ((cpu != 0) && (reg_width == MODE_RW_32)) {
+ 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));
@@ -314,10 +318,10 @@
fpregs_context_restore(get_fpregs_ctx(cm_get_context(SECURE)));
cm_set_next_eret_context(SECURE);
- ctx->saved_security_state = ~0; /* initial saved state is invalid */
- trusty_init_context_stack(&ctx->saved_sp, &ctx->secure_stack.end);
+ ctx->saved_security_state = ~0U; /* initial saved state is invalid */
+ (void)trusty_init_context_stack(&ctx->saved_sp, &ctx->secure_stack.end);
- trusty_context_switch_helper(&ctx->saved_sp, &zero_args);
+ (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)));
@@ -328,10 +332,10 @@
static void trusty_cpu_suspend(uint32_t off)
{
- struct args ret;
+ struct smc_args ret;
ret = trusty_context_switch(NON_SECURE, SMC_FC_CPU_SUSPEND, off, 0, 0);
- if (ret.r0 != 0) {
+ if (ret.r0 != 0U) {
INFO("%s: cpu %d, SMC_FC_CPU_SUSPEND returned unexpected value, %lld\n",
__func__, plat_my_core_pos(), ret.r0);
}
@@ -339,10 +343,10 @@
static void trusty_cpu_resume(uint32_t on)
{
- struct args ret;
+ struct smc_args ret;
ret = trusty_context_switch(NON_SECURE, SMC_FC_CPU_RESUME, on, 0, 0);
- if (ret.r0 != 0) {
+ if (ret.r0 != 0U) {
INFO("%s: cpu %d, SMC_FC_CPU_RESUME returned unexpected value, %lld\n",
__func__, plat_my_core_pos(), ret.r0);
}
@@ -359,8 +363,8 @@
{
struct trusty_cpu_ctx *ctx = get_trusty_ctx();
- if (!ctx->saved_sp) {
- trusty_init();
+ if (ctx->saved_sp == NULL) {
+ (void)trusty_init();
} else {
trusty_cpu_resume(1);
}
@@ -398,12 +402,12 @@
entry_point_info_t *ep_info;
uint32_t instr;
uint32_t flags;
- int ret;
+ 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) {
+ if (ep_info == NULL) {
INFO("Trusty image missing.\n");
return -1;
}
@@ -444,8 +448,9 @@
ret = register_interrupt_type_handler(INTR_TYPE_S_EL1,
trusty_fiq_handler,
flags);
- if (ret)
+ if (ret != 0) {
ERROR("trusty: failed to register fiq handler, ret = %d\n", ret);
+ }
if (aarch32) {
entry_point_info_t *ns_ep_info;
diff --git a/services/std_svc/spm_deprecated/aarch64/spm_helpers.S b/services/std_svc/spm_mm/aarch64/spm_helpers.S
similarity index 100%
rename from services/std_svc/spm_deprecated/aarch64/spm_helpers.S
rename to services/std_svc/spm_mm/aarch64/spm_helpers.S
diff --git a/services/std_svc/spm_deprecated/aarch64/spm_shim_exceptions.S b/services/std_svc/spm_mm/aarch64/spm_shim_exceptions.S
similarity index 100%
rename from services/std_svc/spm_deprecated/aarch64/spm_shim_exceptions.S
rename to services/std_svc/spm_mm/aarch64/spm_shim_exceptions.S
diff --git a/services/std_svc/spm_deprecated/spm.mk b/services/std_svc/spm_mm/spm.mk
similarity index 90%
rename from services/std_svc/spm_deprecated/spm.mk
rename to services/std_svc/spm_mm/spm.mk
index 3503020..3aa10ee 100644
--- a/services/std_svc/spm_deprecated/spm.mk
+++ b/services/std_svc/spm_mm/spm.mk
@@ -11,7 +11,7 @@
$(error "Error: SPM is only supported on aarch64.")
endif
-SPM_SOURCES := $(addprefix services/std_svc/spm_deprecated/, \
+SPM_SOURCES := $(addprefix services/std_svc/spm_mm/, \
${ARCH}/spm_helpers.S \
${ARCH}/spm_shim_exceptions.S \
spm_main.c \
diff --git a/services/std_svc/spm_deprecated/spm_main.c b/services/std_svc/spm_mm/spm_main.c
similarity index 100%
rename from services/std_svc/spm_deprecated/spm_main.c
rename to services/std_svc/spm_mm/spm_main.c
diff --git a/services/std_svc/spm_deprecated/spm_private.h b/services/std_svc/spm_mm/spm_private.h
similarity index 100%
rename from services/std_svc/spm_deprecated/spm_private.h
rename to services/std_svc/spm_mm/spm_private.h
diff --git a/services/std_svc/spm_deprecated/spm_setup.c b/services/std_svc/spm_mm/spm_setup.c
similarity index 100%
rename from services/std_svc/spm_deprecated/spm_setup.c
rename to services/std_svc/spm_mm/spm_setup.c
diff --git a/services/std_svc/spm_deprecated/spm_shim_private.h b/services/std_svc/spm_mm/spm_shim_private.h
similarity index 100%
rename from services/std_svc/spm_deprecated/spm_shim_private.h
rename to services/std_svc/spm_mm/spm_shim_private.h
diff --git a/services/std_svc/spm_deprecated/spm_xlat.c b/services/std_svc/spm_mm/spm_xlat.c
similarity index 100%
rename from services/std_svc/spm_deprecated/spm_xlat.c
rename to services/std_svc/spm_mm/spm_xlat.c
diff --git a/services/std_svc/std_svc_setup.c b/services/std_svc/std_svc_setup.c
index 7a34655..1d80fa3 100644
--- a/services/std_svc/std_svc_setup.c
+++ b/services/std_svc/std_svc_setup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved.
+ * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -103,7 +103,7 @@
SMC_RET1(handle, ret);
}
-#if ENABLE_SPM && SPM_DEPRECATED
+#if ENABLE_SPM && SPM_MM
/*
* Dispatch SPM calls to SPM SMC handler and return its return
* value