From ea6dec5db62f2b3b9709f26bcf1c8afc71bd011c Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Fri, 10 Mar 2017 09:53:37 -0800 Subject: [PATCH 01/26] Tegra: public interfaces to get the chip's major/minor versions This patch opens up the interfaces to read the chip's major/minor versions for all Tegra drivers to use. Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/common/tegra_platform.c | 4 ++-- plat/nvidia/tegra/include/tegra_platform.h | 6 ++++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/plat/nvidia/tegra/common/tegra_platform.c b/plat/nvidia/tegra/common/tegra_platform.c index 5b96459cd..0724b18ee 100644 --- a/plat/nvidia/tegra/common/tegra_platform.c +++ b/plat/nvidia/tegra/common/tegra_platform.c @@ -82,7 +82,7 @@ static uint32_t tegra_get_chipid(void) /* * Read the chip's major version from chip ID value */ -static uint32_t tegra_get_chipid_major(void) +uint32_t tegra_get_chipid_major(void) { return (tegra_get_chipid() >> MAJOR_VERSION_SHIFT) & MAJOR_VERSION_MASK; } @@ -90,7 +90,7 @@ static uint32_t tegra_get_chipid_major(void) /* * Read the chip's minor version from the chip ID value */ -static uint32_t tegra_get_chipid_minor(void) +uint32_t tegra_get_chipid_minor(void) { return (tegra_get_chipid() >> MINOR_VERSION_SHIFT) & MINOR_VERSION_MASK; } diff --git a/plat/nvidia/tegra/include/tegra_platform.h b/plat/nvidia/tegra/include/tegra_platform.h index f9d7b60c9..a2813a832 100644 --- a/plat/nvidia/tegra/include/tegra_platform.h +++ b/plat/nvidia/tegra/include/tegra_platform.h @@ -33,6 +33,12 @@ #include +/* + * Tegra chip major/minor version + */ +uint32_t tegra_get_chipid_major(void); +uint32_t tegra_get_chipid_minor(void); + /* * Tegra chip identifiers */ From 412dd5c503ac0ca26009b8f4bc1c1b6e2610e7fb Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Sun, 20 Sep 2015 15:08:22 +0530 Subject: [PATCH 02/26] Tegra: memctrl_v2: Memory Controller Driver (v2) This patch adds driver for the Memory Controller (v2) in the newer Tegra SoCs. The newer hardware uses ARM's SMMU hardware instead of the proprietary block in the past. Change-Id: I78359da780dc840213b6e99954e45e34428d4fff Signed-off-by: Varun Wadekar --- .../tegra/common/drivers/memctrl/memctrl_v2.c | 314 ++++++++++++++++++ .../nvidia/tegra/include/drivers/memctrl_v2.h | 297 +++++++++++++++++ 2 files changed, 611 insertions(+) create mode 100644 plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c create mode 100644 plat/nvidia/tegra/include/drivers/memctrl_v2.h diff --git a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c new file mode 100644 index 000000000..c82ddd422 --- /dev/null +++ b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Video Memory base and size (live values) */ +static uint64_t video_mem_base; +static uint64_t video_mem_size; + +/* array to hold stream_id override config register offsets */ +const static uint32_t streamid_overrides[] = { + MC_STREAMID_OVERRIDE_CFG_PTCR, + MC_STREAMID_OVERRIDE_CFG_AFIR, + MC_STREAMID_OVERRIDE_CFG_HDAR, + MC_STREAMID_OVERRIDE_CFG_HOST1XDMAR, + MC_STREAMID_OVERRIDE_CFG_NVENCSRD, + MC_STREAMID_OVERRIDE_CFG_SATAR, + MC_STREAMID_OVERRIDE_CFG_MPCORER, + MC_STREAMID_OVERRIDE_CFG_NVENCSWR, + MC_STREAMID_OVERRIDE_CFG_AFIW, + MC_STREAMID_OVERRIDE_CFG_SATAW, + MC_STREAMID_OVERRIDE_CFG_MPCOREW, + MC_STREAMID_OVERRIDE_CFG_SATAW, + MC_STREAMID_OVERRIDE_CFG_HDAW, + MC_STREAMID_OVERRIDE_CFG_ISPRA, + MC_STREAMID_OVERRIDE_CFG_ISPWA, + MC_STREAMID_OVERRIDE_CFG_ISPWB, + MC_STREAMID_OVERRIDE_CFG_XUSB_HOSTR, + MC_STREAMID_OVERRIDE_CFG_XUSB_HOSTW, + MC_STREAMID_OVERRIDE_CFG_XUSB_DEVR, + MC_STREAMID_OVERRIDE_CFG_XUSB_DEVW, + MC_STREAMID_OVERRIDE_CFG_TSECSRD, + MC_STREAMID_OVERRIDE_CFG_TSECSWR, + MC_STREAMID_OVERRIDE_CFG_GPUSRD, + MC_STREAMID_OVERRIDE_CFG_GPUSWR, + MC_STREAMID_OVERRIDE_CFG_SDMMCRA, + MC_STREAMID_OVERRIDE_CFG_SDMMCRAA, + MC_STREAMID_OVERRIDE_CFG_SDMMCR, + MC_STREAMID_OVERRIDE_CFG_SDMMCRAB, + MC_STREAMID_OVERRIDE_CFG_SDMMCWA, + MC_STREAMID_OVERRIDE_CFG_SDMMCWAA, + MC_STREAMID_OVERRIDE_CFG_SDMMCW, + MC_STREAMID_OVERRIDE_CFG_SDMMCWAB, + MC_STREAMID_OVERRIDE_CFG_VICSRD, + MC_STREAMID_OVERRIDE_CFG_VICSWR, + MC_STREAMID_OVERRIDE_CFG_VIW, + MC_STREAMID_OVERRIDE_CFG_NVDECSRD, + MC_STREAMID_OVERRIDE_CFG_NVDECSWR, + MC_STREAMID_OVERRIDE_CFG_APER, + MC_STREAMID_OVERRIDE_CFG_APEW, + MC_STREAMID_OVERRIDE_CFG_NVJPGSRD, + MC_STREAMID_OVERRIDE_CFG_NVJPGSWR, + MC_STREAMID_OVERRIDE_CFG_SESRD, + MC_STREAMID_OVERRIDE_CFG_SESWR, + MC_STREAMID_OVERRIDE_CFG_ETRR, + MC_STREAMID_OVERRIDE_CFG_ETRW, + MC_STREAMID_OVERRIDE_CFG_TSECSRDB, + MC_STREAMID_OVERRIDE_CFG_TSECSWRB, + MC_STREAMID_OVERRIDE_CFG_GPUSRD2, + MC_STREAMID_OVERRIDE_CFG_GPUSWR2, + MC_STREAMID_OVERRIDE_CFG_AXISR, + MC_STREAMID_OVERRIDE_CFG_AXISW, + MC_STREAMID_OVERRIDE_CFG_EQOSR, + MC_STREAMID_OVERRIDE_CFG_EQOSW, + MC_STREAMID_OVERRIDE_CFG_UFSHCR, + MC_STREAMID_OVERRIDE_CFG_UFSHCW, + MC_STREAMID_OVERRIDE_CFG_NVDISPLAYR, + MC_STREAMID_OVERRIDE_CFG_BPMPR, + MC_STREAMID_OVERRIDE_CFG_BPMPW, + MC_STREAMID_OVERRIDE_CFG_BPMPDMAR, + MC_STREAMID_OVERRIDE_CFG_BPMPDMAW, + MC_STREAMID_OVERRIDE_CFG_AONR, + MC_STREAMID_OVERRIDE_CFG_AONW, + MC_STREAMID_OVERRIDE_CFG_AONDMAR, + MC_STREAMID_OVERRIDE_CFG_AONDMAW, + MC_STREAMID_OVERRIDE_CFG_SCER, + MC_STREAMID_OVERRIDE_CFG_SCEW, + MC_STREAMID_OVERRIDE_CFG_SCEDMAR, + MC_STREAMID_OVERRIDE_CFG_SCEDMAW, + MC_STREAMID_OVERRIDE_CFG_APEDMAR, + MC_STREAMID_OVERRIDE_CFG_APEDMAW, + MC_STREAMID_OVERRIDE_CFG_NVDISPLAYR1, + MC_STREAMID_OVERRIDE_CFG_VICSRD1, + MC_STREAMID_OVERRIDE_CFG_NVDECSRD1 +}; + +/* array to hold the security configs for stream IDs */ +const static mc_streamid_security_cfg_t sec_cfgs[] = { + mc_make_sec_cfg(SCEW, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(AFIR, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(NVDISPLAYR1, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(XUSB_DEVR, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(VICSRD1, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(NVENCSWR, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(TSECSRDB, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(AXISW, SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(SDMMCWAB, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(AONDMAW, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(GPUSWR2, SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(SATAW, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(UFSHCW, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(AFIW, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(SDMMCR, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(SCEDMAW, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(UFSHCR, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(SDMMCWAA, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(APEDMAW, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(SESWR, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(MPCORER, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(PTCR, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(BPMPW, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(ETRW, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(GPUSRD, SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(VICSWR, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(SCEDMAR, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(HDAW, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(ISPWA, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(EQOSW, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(XUSB_HOSTW, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(TSECSWR, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(SDMMCRAA, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(APER, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(VIW, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(APEW, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(AXISR, SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(SDMMCW, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(BPMPDMAW, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(ISPRA, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(NVDECSWR, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(XUSB_DEVW, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(NVDECSRD, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(MPCOREW, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(NVDISPLAYR, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(BPMPDMAR, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(NVJPGSWR, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(NVDECSRD1, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(TSECSRD, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(NVJPGSRD, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(SDMMCWA, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(SCER, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(XUSB_HOSTR, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(VICSRD, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(AONDMAR, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(AONW, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(SDMMCRA, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(HOST1XDMAR, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(EQOSR, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(SATAR, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(BPMPR, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(HDAR, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(SDMMCRAB, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(ETRR, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(AONR, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(APEDMAR, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(SESRD, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(NVENCSRD, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(GPUSWR, SECURE, NO_OVERRIDE, DISABLE), + mc_make_sec_cfg(TSECSWRB, NON_SECURE, NO_OVERRIDE, ENABLE), + mc_make_sec_cfg(ISPWB, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(GPUSRD2, SECURE, NO_OVERRIDE, DISABLE), +}; + +/* + * Init SMMU. + */ +void tegra_memctrl_setup(void) +{ + uint32_t val; + uint32_t num_overrides = sizeof(streamid_overrides) / sizeof(uint32_t); + uint32_t num_sec_cfgs = sizeof(sec_cfgs) / sizeof(mc_streamid_security_cfg_t); + int i; + + INFO("Tegra Memory Controller (v2)\n"); + + /* Program the SMMU pagesize */ + val = tegra_smmu_read_32(ARM_SMMU_GSR0_SECURE_ACR); + val |= ARM_SMMU_GSR0_PGSIZE_64K; + tegra_smmu_write_32(ARM_SMMU_GSR0_SECURE_ACR, val); + + /* Program all the Stream ID overrides */ + for (i = 0; i < num_overrides; i++) + tegra_mc_streamid_write_32(streamid_overrides[i], + MC_STREAM_ID_MAX); + + /* Program the security config settings for all Stream IDs */ + for (i = 0; i < num_sec_cfgs; i++) { + val = sec_cfgs[i].override_enable << 16 | + sec_cfgs[i].override_client_inputs << 8 | + sec_cfgs[i].override_client_ns_flag << 0; + tegra_mc_streamid_write_32(sec_cfgs[i].offset, val); + } + + /* + * All requests at boot time, and certain requests during + * normal run time, are physically addressed and must bypass + * the SMMU. The client hub logic implements a hardware bypass + * path around the Translation Buffer Units (TBU). During + * boot-time, the SMMU_BYPASS_CTRL register (which defaults to + * TBU_BYPASS mode) will be used to steer all requests around + * the uninitialized TBUs. During normal operation, this register + * is locked into TBU_BYPASS_SID config, which routes requests + * with special StreamID 0x7f on the bypass path and all others + * through the selected TBU. This is done to disable SMMU Bypass + * mode, as it could be used to circumvent SMMU security checks. + */ + tegra_mc_write_32(MC_SMMU_BYPASS_CONFIG, + MC_SMMU_BYPASS_CONFIG_SETTINGS); + + /* video memory carveout region */ + if (video_mem_base) { + tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, + (uint32_t)video_mem_base); + tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI, + (uint32_t)(video_mem_base >> 32)); + tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, video_mem_size); + + /* + * MCE propogates the VideoMem configuration values across the + * CCPLEX. + */ + mce_update_gsc_videomem(); + } +} + +/* + * Secure the BL31 DRAM aperture. + * + * phys_base = physical base of TZDRAM aperture + * size_in_bytes = size of aperture in bytes + */ +void tegra_memctrl_tzdram_setup(uint64_t phys_base, uint32_t size_in_bytes) +{ + /* + * 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); + + /* + * MCE propogates the security configuration values across the + * CCPLEX. + */ + mce_update_gsc_tzdram(); +} + +/* + * Program the Video Memory carveout region + * + * phys_base = physical base of aperture + * size_in_bytes = size of aperture in bytes + */ +void tegra_memctrl_videomem_setup(uint64_t phys_base, uint32_t size_in_bytes) +{ + /* + * Setup the Memory controller to restrict CPU accesses to the Video + * Memory region + */ + INFO("Configuring Video Memory Carveout\n"); + + tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, (uint32_t)phys_base); + tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_HI, + (uint32_t)(phys_base >> 32)); + tegra_mc_write_32(MC_VIDEO_PROTECT_SIZE_MB, size_in_bytes); + + /* store new values */ + video_mem_base = phys_base; + video_mem_size = size_in_bytes >> 20; + + /* + * MCE propogates the VideoMem configuration values across the + * CCPLEX. + */ + mce_update_gsc_videomem(); +} diff --git a/plat/nvidia/tegra/include/drivers/memctrl_v2.h b/plat/nvidia/tegra/include/drivers/memctrl_v2.h new file mode 100644 index 000000000..1d5ba0e99 --- /dev/null +++ b/plat/nvidia/tegra/include/drivers/memctrl_v2.h @@ -0,0 +1,297 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MEMCTRLV2_H__ +#define __MEMCTRLV2_H__ + +#include +#include + +/******************************************************************************* + * 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 0x0 +#define MC_STREAMID_OVERRIDE_CFG_AFIR 0x70 +#define MC_STREAMID_OVERRIDE_CFG_HDAR 0xA8 +#define MC_STREAMID_OVERRIDE_CFG_HOST1XDMAR 0xB0 +#define MC_STREAMID_OVERRIDE_CFG_NVENCSRD 0xE0 +#define MC_STREAMID_OVERRIDE_CFG_SATAR 0xF8 +#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_SATAW 0x1E8 +#define MC_STREAMID_OVERRIDE_CFG_MPCOREW 0x1C8 +#define MC_STREAMID_OVERRIDE_CFG_SATAW 0x1E8 +#define MC_STREAMID_OVERRIDE_CFG_HDAW 0x1A8 +#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 + +/******************************************************************************* + * Stream ID Security Config registers + ******************************************************************************/ +#define MC_STREAMID_SECURITY_CFG_PTCR 0x4 +#define MC_STREAMID_SECURITY_CFG_AFIR 0x74 +#define MC_STREAMID_SECURITY_CFG_HDAR 0xAC +#define MC_STREAMID_SECURITY_CFG_HOST1XDMAR 0xB4 +#define MC_STREAMID_SECURITY_CFG_NVENCSRD 0xE4 +#define MC_STREAMID_SECURITY_CFG_SATAR 0xFC +#define MC_STREAMID_SECURITY_CFG_HDAW 0x1AC +#define MC_STREAMID_SECURITY_CFG_MPCORER 0x13C +#define MC_STREAMID_SECURITY_CFG_NVENCSWR 0x15C +#define MC_STREAMID_SECURITY_CFG_AFIW 0x18C +#define MC_STREAMID_SECURITY_CFG_MPCOREW 0x1CC +#define MC_STREAMID_SECURITY_CFG_SATAW 0x1EC +#define MC_STREAMID_SECURITY_CFG_ISPRA 0x224 +#define MC_STREAMID_SECURITY_CFG_ISPWA 0x234 +#define MC_STREAMID_SECURITY_CFG_ISPWB 0x23C +#define MC_STREAMID_SECURITY_CFG_XUSB_HOSTR 0x254 +#define MC_STREAMID_SECURITY_CFG_XUSB_HOSTW 0x25C +#define MC_STREAMID_SECURITY_CFG_XUSB_DEVR 0x264 +#define MC_STREAMID_SECURITY_CFG_XUSB_DEVW 0x26C +#define MC_STREAMID_SECURITY_CFG_TSECSRD 0x2A4 +#define MC_STREAMID_SECURITY_CFG_TSECSWR 0x2AC +#define MC_STREAMID_SECURITY_CFG_GPUSRD 0x2C4 +#define MC_STREAMID_SECURITY_CFG_GPUSWR 0x2CC +#define MC_STREAMID_SECURITY_CFG_SDMMCRA 0x304 +#define MC_STREAMID_SECURITY_CFG_SDMMCRAA 0x30C +#define MC_STREAMID_SECURITY_CFG_SDMMCR 0x314 +#define MC_STREAMID_SECURITY_CFG_SDMMCRAB 0x31C +#define MC_STREAMID_SECURITY_CFG_SDMMCWA 0x324 +#define MC_STREAMID_SECURITY_CFG_SDMMCWAA 0x32C +#define MC_STREAMID_SECURITY_CFG_SDMMCW 0x334 +#define MC_STREAMID_SECURITY_CFG_SDMMCWAB 0x33C +#define MC_STREAMID_SECURITY_CFG_VICSRD 0x364 +#define MC_STREAMID_SECURITY_CFG_VICSWR 0x36C +#define MC_STREAMID_SECURITY_CFG_VIW 0x394 +#define MC_STREAMID_SECURITY_CFG_NVDECSRD 0x3C4 +#define MC_STREAMID_SECURITY_CFG_NVDECSWR 0x3CC +#define MC_STREAMID_SECURITY_CFG_APER 0x3D4 +#define MC_STREAMID_SECURITY_CFG_APEW 0x3DC +#define MC_STREAMID_SECURITY_CFG_NVJPGSRD 0x3F4 +#define MC_STREAMID_SECURITY_CFG_NVJPGSWR 0x3FC +#define MC_STREAMID_SECURITY_CFG_SESRD 0x404 +#define MC_STREAMID_SECURITY_CFG_SESWR 0x40C +#define MC_STREAMID_SECURITY_CFG_ETRR 0x424 +#define MC_STREAMID_SECURITY_CFG_ETRW 0x42C +#define MC_STREAMID_SECURITY_CFG_TSECSRDB 0x434 +#define MC_STREAMID_SECURITY_CFG_TSECSWRB 0x43C +#define MC_STREAMID_SECURITY_CFG_GPUSRD2 0x444 +#define MC_STREAMID_SECURITY_CFG_GPUSWR2 0x44C +#define MC_STREAMID_SECURITY_CFG_AXISR 0x464 +#define MC_STREAMID_SECURITY_CFG_AXISW 0x46C +#define MC_STREAMID_SECURITY_CFG_EQOSR 0x474 +#define MC_STREAMID_SECURITY_CFG_EQOSW 0x47C +#define MC_STREAMID_SECURITY_CFG_UFSHCR 0x484 +#define MC_STREAMID_SECURITY_CFG_UFSHCW 0x48C +#define MC_STREAMID_SECURITY_CFG_NVDISPLAYR 0x494 +#define MC_STREAMID_SECURITY_CFG_BPMPR 0x49C +#define MC_STREAMID_SECURITY_CFG_BPMPW 0x4A4 +#define MC_STREAMID_SECURITY_CFG_BPMPDMAR 0x4AC +#define MC_STREAMID_SECURITY_CFG_BPMPDMAW 0x4B4 +#define MC_STREAMID_SECURITY_CFG_AONR 0x4BC +#define MC_STREAMID_SECURITY_CFG_AONW 0x4C4 +#define MC_STREAMID_SECURITY_CFG_AONDMAR 0x4CC +#define MC_STREAMID_SECURITY_CFG_AONDMAW 0x4D4 +#define MC_STREAMID_SECURITY_CFG_SCER 0x4DC +#define MC_STREAMID_SECURITY_CFG_SCEW 0x4E4 +#define MC_STREAMID_SECURITY_CFG_SCEDMAR 0x4EC +#define MC_STREAMID_SECURITY_CFG_SCEDMAW 0x4F4 +#define MC_STREAMID_SECURITY_CFG_APEDMAR 0x4FC +#define MC_STREAMID_SECURITY_CFG_APEDMAW 0x504 +#define MC_STREAMID_SECURITY_CFG_NVDISPLAYR1 0x50C +#define MC_STREAMID_SECURITY_CFG_VICSRD1 0x514 +#define MC_STREAMID_SECURITY_CFG_NVDECSRD1 0x51C + +/******************************************************************************* + * 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) + +/******************************************************************************* + * Memory Controller SMMU Global Secure Aux. Configuration Register + ******************************************************************************/ +#define ARM_SMMU_GSR0_SECURE_ACR 0x10 +#define ARM_SMMU_GSR0_PGSIZE_SHIFT 16 +#define ARM_SMMU_GSR0_PGSIZE_4K (0 << ARM_SMMU_GSR0_PGSIZE_SHIFT) +#define ARM_SMMU_GSR0_PGSIZE_64K (1 << ARM_SMMU_GSR0_PGSIZE_SHIFT) + +/******************************************************************************* + * Structure to hold the Stream ID to use to override client inputs + ******************************************************************************/ +typedef struct mc_streamid_override_cfg { + uint32_t offset; + uint8_t stream_id; +} mc_streamid_override_cfg_t; + +/******************************************************************************* + * Structure to hold the Stream ID Security Configuration settings + ******************************************************************************/ +typedef struct mc_streamid_security_cfg { + char *name; + uint32_t offset; + int override_enable; + int override_client_inputs; + int override_client_ns_flag; +} mc_streamid_security_cfg_t; + +#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 + +#define mc_make_sec_cfg(off, ns, ovrrd, access) \ + { \ + .name = # off, \ + .offset = MC_STREAMID_SECURITY_CFG_ ## off, \ + .override_client_ns_flag = CLIENT_FLAG_ ## ns, \ + .override_client_inputs = CLIENT_INPUTS_ ## ovrrd, \ + .override_enable = OVERRIDE_ ## access \ + } + +/******************************************************************************* + * TZDRAM carveout configuration registers + ******************************************************************************/ +#define MC_SECURITY_CFG0_0 0x70 +#define MC_SECURITY_CFG1_0 0x74 +#define MC_SECURITY_CFG3_0 0x9BC + +/******************************************************************************* + * Video Memory carveout configuration registers + ******************************************************************************/ +#define MC_VIDEO_PROTECT_BASE_HI 0x978 +#define MC_VIDEO_PROTECT_BASE_LO 0x648 +#define MC_VIDEO_PROTECT_SIZE_MB 0x64c + +static inline uint32_t tegra_mc_read_32(uint32_t off) +{ + return mmio_read_32(TEGRA_MC_BASE + off); +} + +static inline void tegra_mc_write_32(uint32_t off, uint32_t val) +{ + mmio_write_32(TEGRA_MC_BASE + off, val); +} + +static inline uint32_t tegra_mc_streamid_read_32(uint32_t off) +{ + return mmio_read_32(TEGRA_MC_STREAMID_BASE + off); +} + +static inline void tegra_mc_streamid_write_32(uint32_t off, uint32_t val) +{ + mmio_write_32(TEGRA_MC_STREAMID_BASE + off, val); +} + +static inline uint32_t tegra_smmu_read_32(uint32_t off) +{ + return mmio_read_32(TEGRA_SMMU_BASE + off); +} + +static inline void tegra_smmu_write_32(uint32_t off, uint32_t val) +{ + mmio_write_32(TEGRA_SMMU_BASE + off, val); +} + +#endif /* __MEMCTRLV2_H__ */ From 3cf3183fc2382e88f8f831921a09003883fba67f Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Tue, 25 Aug 2015 17:03:14 +0530 Subject: [PATCH 03/26] Tegra186: platform support for Tegra "T186" SoC Tegra186 is the newest SoC in the Tegra family which consists of two CPU clusters - Denver and A57. The Denver cluster hosts two next gen Denver15 CPUs while the A57 cluster hosts four ARM Cortex-A57 CPUs. Unlike previous Tegra generations, all the six cores on this SoC would be available to the system at the same time and individual clusters can be powered down to conserve power. Change-Id: Id0c9919dbf5186d2938603e0b11e821b5892985e Signed-off-by: Wayne Lin Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/include/t186/tegra_def.h | 114 ++++++++++++++++++ .../tegra/soc/t186/plat_psci_handlers.c | 47 ++++++++ plat/nvidia/tegra/soc/t186/plat_secondary.c | 37 ++++++ plat/nvidia/tegra/soc/t186/plat_setup.c | 103 ++++++++++++++++ plat/nvidia/tegra/soc/t186/plat_sip_calls.c | 114 ++++++++++++++++++ plat/nvidia/tegra/soc/t186/platform_t186.mk | 60 +++++++++ 6 files changed, 475 insertions(+) create mode 100644 plat/nvidia/tegra/include/t186/tegra_def.h create mode 100644 plat/nvidia/tegra/soc/t186/plat_psci_handlers.c create mode 100644 plat/nvidia/tegra/soc/t186/plat_secondary.c create mode 100644 plat/nvidia/tegra/soc/t186/plat_setup.c create mode 100644 plat/nvidia/tegra/soc/t186/plat_sip_calls.c create mode 100644 plat/nvidia/tegra/soc/t186/platform_t186.mk diff --git a/plat/nvidia/tegra/include/t186/tegra_def.h b/plat/nvidia/tegra/include/t186/tegra_def.h new file mode 100644 index 000000000..10fea1158 --- /dev/null +++ b/plat/nvidia/tegra/include/t186/tegra_def.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __TEGRA_DEF_H__ +#define __TEGRA_DEF_H__ + +#include + +/******************************************************************************* + * This value is used by the PSCI implementation during the `SYSTEM_SUSPEND` + * call as the `state-id` field in the 'power state' parameter. + ******************************************************************************/ +#define PLAT_SYS_SUSPEND_STATE_ID 0 + +/******************************************************************************* + * Implementation defined ACTLR_EL3 bit definitions + ******************************************************************************/ +#define ACTLR_EL3_L2ACTLR_BIT (1 << 6) +#define ACTLR_EL3_L2ECTLR_BIT (1 << 5) +#define ACTLR_EL3_L2CTLR_BIT (1 << 4) +#define ACTLR_EL3_CPUECTLR_BIT (1 << 1) +#define ACTLR_EL3_CPUACTLR_BIT (1 << 0) +#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) + +/******************************************************************************* + * Tegra Miscellanous register constants + ******************************************************************************/ +#define TEGRA_MISC_BASE 0x00100000 + +/******************************************************************************* + * Tegra Memory Controller constants + ******************************************************************************/ +#define TEGRA_MC_STREAMID_BASE 0x02C00000 +#define TEGRA_MC_BASE 0x02C10000 + +/******************************************************************************* + * Tegra UART Controller constants + ******************************************************************************/ +#define TEGRA_UARTA_BASE 0x03100000 +#define TEGRA_UARTB_BASE 0x03110000 +#define TEGRA_UARTC_BASE 0x0C280000 +#define TEGRA_UARTD_BASE 0x03130000 +#define TEGRA_UARTE_BASE 0x03140000 +#define TEGRA_UARTF_BASE 0x03150000 +#define TEGRA_UARTG_BASE 0x0C290000 + +/******************************************************************************* + * GICv2 & interrupt handling related constants + ******************************************************************************/ +#define TEGRA_GICD_BASE 0x03881000 +#define TEGRA_GICC_BASE 0x03882000 + +/******************************************************************************* + * Tegra Clock and Reset Controller constants + ******************************************************************************/ +#define TEGRA_CAR_RESET_BASE 0x05000000 + +/******************************************************************************* + * Tegra micro-seconds timer constants + ******************************************************************************/ +#define TEGRA_TMRUS_BASE 0x0C2E0000 + +/******************************************************************************* + * Tegra Power Mgmt Controller constants + ******************************************************************************/ +#define TEGRA_PMC_BASE 0x0C360000 + +/******************************************************************************* + * Tegra scratch registers constants + ******************************************************************************/ +#define TEGRA_SCRATCH_BASE 0x0C390000 + +/******************************************************************************* + * Tegra Memory Mapped Control Register Access Bus constants + ******************************************************************************/ +#define TEGRA_MMCRAB_BASE 0x0E000000 + +/******************************************************************************* + * Tegra SMMU Controller constants + ******************************************************************************/ +#define TEGRA_SMMU_BASE 0x12000000 + +#endif /* __TEGRA_DEF_H__ */ diff --git a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c new file mode 100644 index 000000000..012385483 --- /dev/null +++ b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + +int32_t tegra_soc_validate_power_state(unsigned int power_state) +{ + /* Sanity check the requested afflvl */ + if (psci_get_pstate_type(power_state) == PSTATE_TYPE_STANDBY) { + /* + * It's possible to enter standby only on affinity level 0 i.e. + * a cpu on Tegra. Ignore any other affinity level. + */ + if (psci_get_pstate_afflvl(power_state) != MPIDR_AFFLVL0) + return PSCI_E_INVALID_PARAMS; + } + + return PSCI_E_SUCCESS; +} diff --git a/plat/nvidia/tegra/soc/t186/plat_secondary.c b/plat/nvidia/tegra/soc/t186/plat_secondary.c new file mode 100644 index 000000000..85cc32c84 --- /dev/null +++ b/plat/nvidia/tegra/soc/t186/plat_secondary.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/******************************************************************************* + * Setup secondary CPU vectors + ******************************************************************************/ +void plat_secondary_setup(void) +{ + ; /* do nothing */ +} diff --git a/plat/nvidia/tegra/soc/t186/plat_setup.c b/plat/nvidia/tegra/soc/t186/plat_setup.c new file mode 100644 index 000000000..99329e3ac --- /dev/null +++ b/plat/nvidia/tegra/soc/t186/plat_setup.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +/* + * Table of regions to map using the MMU. + */ +static const mmap_region_t tegra_mmap[] = { + MAP_REGION_FLAT(TEGRA_MISC_BASE, 0x10000, /* 64KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_MC_STREAMID_BASE, 0x10000, /* 64KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_MC_BASE, 0x10000, /* 64KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_UARTA_BASE, 0x20000, /* 128KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_GICD_BASE, 0x20000, /* 128KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_PMC_BASE, 0x40000, /* 256KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_MMCRAB_BASE, 0x60000, /* 384KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_SMMU_BASE, 0x10000, /* 64KB */ + MT_DEVICE | MT_RW | MT_SECURE), + {0} +}; + +/******************************************************************************* + * Set up the pagetables as per the platform memory map & initialize the MMU + ******************************************************************************/ +const mmap_region_t *plat_get_mmio_map(void) +{ + /* MMIO space */ + return tegra_mmap; +} + +/******************************************************************************* + * Handler to get the System Counter Frequency + ******************************************************************************/ +unsigned int plat_get_syscnt_freq2(void) +{ + return 38400000; +} + +/******************************************************************************* + * Maximum supported UART controllers + ******************************************************************************/ +#define TEGRA186_MAX_UART_PORTS 7 + +/******************************************************************************* + * This variable holds the UART port base addresses + ******************************************************************************/ +static uint32_t tegra186_uart_addresses[TEGRA186_MAX_UART_PORTS + 1] = { + 0, /* undefined - treated as an error case */ + TEGRA_UARTA_BASE, + TEGRA_UARTB_BASE, + TEGRA_UARTC_BASE, + TEGRA_UARTD_BASE, + TEGRA_UARTE_BASE, + TEGRA_UARTF_BASE, + TEGRA_UARTG_BASE, +}; + +/******************************************************************************* + * Retrieve the UART controller base to be used as the console + ******************************************************************************/ +uint32_t plat_get_console_from_id(int id) +{ + if (id > TEGRA186_MAX_UART_PORTS) + return 0; + + return tegra186_uart_addresses[id]; +} diff --git a/plat/nvidia/tegra/soc/t186/plat_sip_calls.c b/plat/nvidia/tegra/soc/t186/plat_sip_calls.c new file mode 100644 index 000000000..496edf3cb --- /dev/null +++ b/plat/nvidia/tegra/soc/t186/plat_sip_calls.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * Tegra186 SiP SMCs + ******************************************************************************/ +#define TEGRA_SIP_NEW_VIDEOMEM_REGION 0x82000003 + +/******************************************************************************* + * This function is responsible for handling all SiP calls from the NS world + ******************************************************************************/ +uint64_t tegra186_sip_handler(uint32_t smc_fid, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + void *cookie, + void *handle, + uint64_t flags) +{ + uint32_t ns; + int err; + + /* Determine which security state this SMC originated from */ + ns = is_caller_non_secure(flags); + if (!ns) + SMC_RET1(handle, SMC_UNK); + + switch (smc_fid) { + + case TEGRA_SIP_NEW_VIDEOMEM_REGION: + + /* clean up the high bits */ + x1 = (uint32_t)x1; + 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); + if (err) + SMC_RET1(handle, err); + + /* + * Check if Video Memory is aligned to 1MB. + */ + if ((x1 & 0xFFFFF) || (x2 & 0xFFFFF)) { + ERROR("Unaligned Video Memory base address!\n"); + SMC_RET1(handle, -ENOTSUP); + } + + /* new video memory carveout settings */ + tegra_memctrl_videomem_setup(x1, x2); + + SMC_RET1(handle, 0); + break; + + default: + ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); + break; + } + + SMC_RET1(handle, SMC_UNK); +} + +/* Define a runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + tegra186_sip_fast, + + OEN_SIP_START, + OEN_SIP_END, + SMC_TYPE_FAST, + NULL, + tegra186_sip_handler +); diff --git a/plat/nvidia/tegra/soc/t186/platform_t186.mk b/plat/nvidia/tegra/soc/t186/platform_t186.mk new file mode 100644 index 000000000..374b6e617 --- /dev/null +++ b/plat/nvidia/tegra/soc/t186/platform_t186.mk @@ -0,0 +1,60 @@ +# +# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# Neither the name of ARM nor the names of its contributors may be used +# to endorse or promote products derived from this software without specific +# prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +# platform configs +ENABLE_NS_L2_CPUECTRL_RW_ACCESS := 1 +$(eval $(call add_define,ENABLE_NS_L2_CPUECTRL_RW_ACCESS)) + +# platform settings +TZDRAM_BASE := 0xEA800000 +$(eval $(call add_define,TZDRAM_BASE)) + +PLATFORM_CLUSTER_COUNT := 2 +$(eval $(call add_define,PLATFORM_CLUSTER_COUNT)) + +PLATFORM_MAX_CPUS_PER_CLUSTER := 4 +$(eval $(call add_define,PLATFORM_MAX_CPUS_PER_CLUSTER)) + +MAX_XLAT_TABLES := 10 +$(eval $(call add_define,MAX_XLAT_TABLES)) + +MAX_MMAP_REGIONS := 10 +$(eval $(call add_define,MAX_MMAP_REGIONS)) + +# platform files +PLAT_INCLUDES += -I${SOC_DIR}/drivers/include + +BL31_SOURCES += lib/cpus/aarch64/denver.S \ + lib/cpus/aarch64/cortex_a57.S \ + ${COMMON_DIR}/drivers/memctrl/memctrl_v2.c \ + ${SOC_DIR}/plat_psci_handlers.c \ + ${SOC_DIR}/plat_setup.c \ + ${SOC_DIR}/plat_secondary.c \ + ${SOC_DIR}/plat_sip_calls.c From 7808b06b991905e58228c8c4df7026be637b0c00 Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Tue, 14 Mar 2017 14:24:35 -0700 Subject: [PATCH 04/26] Tegra186: mce: driver for the CPU complex power manager block The CPU Complex (CCPLEX) Power Manager (Denver MCE, or DMCE) is an offload engine for BPMP to do voltage related sequencing and for hardware requests to be handled in a better latency than BPMP-firmware. There are two interfaces to the MCEs - Abstract Request Interface (ARI) and the traditional NVGINDEX/NVGDATA interface. MCE supports various commands which can be used by CPUs - ARM as well as Denver, for power management and reset functionality. Since the linux kernel is the master for all these scenarios, each MCE command can be issued by a corresponding SMC. These SMCs have been moved to SiP SMC space as they are specific to the Tegra186 SoC. Change-Id: I67bee83d2289a8ab63bc5556e5744e5043803e51 Signed-off-by: Varun Wadekar Signed-off-by: Varun Wadekar --- .../tegra/soc/t186/drivers/include/mce.h | 358 ++++++++++++++ .../tegra/soc/t186/drivers/include/t18x_ari.h | 450 ++++++++++++++++++ .../t186/drivers/mce/aarch64/nvg_helpers.S | 56 +++ plat/nvidia/tegra/soc/t186/drivers/mce/ari.c | 391 +++++++++++++++ plat/nvidia/tegra/soc/t186/drivers/mce/mce.c | 432 +++++++++++++++++ plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c | 239 ++++++++++ plat/nvidia/tegra/soc/t186/platform_t186.mk | 4 + 7 files changed, 1930 insertions(+) create mode 100644 plat/nvidia/tegra/soc/t186/drivers/include/mce.h create mode 100644 plat/nvidia/tegra/soc/t186/drivers/include/t18x_ari.h create mode 100644 plat/nvidia/tegra/soc/t186/drivers/mce/aarch64/nvg_helpers.S create mode 100644 plat/nvidia/tegra/soc/t186/drivers/mce/ari.c create mode 100644 plat/nvidia/tegra/soc/t186/drivers/mce/mce.c create mode 100644 plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c diff --git a/plat/nvidia/tegra/soc/t186/drivers/include/mce.h b/plat/nvidia/tegra/soc/t186/drivers/include/mce.h new file mode 100644 index 000000000..7078b8bb2 --- /dev/null +++ b/plat/nvidia/tegra/soc/t186/drivers/include/mce.h @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __MCE_H__ +#define __MCE_H__ + +#include +#include + +/******************************************************************************* + * MCE apertures used by the ARI interface + * + * Aperture 0 - Cpu0 (ARM Cortex A-57) + * Aperture 1 - Cpu1 (ARM Cortex A-57) + * Aperture 2 - Cpu2 (ARM Cortex A-57) + * Aperture 3 - Cpu3 (ARM Cortex A-57) + * Aperture 4 - Cpu4 (Denver15) + * Aperture 5 - Cpu5 (Denver15) + ******************************************************************************/ +#define MCE_ARI_APERTURE_0_OFFSET 0x0 +#define MCE_ARI_APERTURE_1_OFFSET 0x10000 +#define MCE_ARI_APERTURE_2_OFFSET 0x20000 +#define MCE_ARI_APERTURE_3_OFFSET 0x30000 +#define MCE_ARI_APERTURE_4_OFFSET 0x40000 +#define MCE_ARI_APERTURE_5_OFFSET 0x50000 +#define MCE_ARI_APERTURE_OFFSET_MAX MCE_APERTURE_5_OFFSET + +/* number of apertures */ +#define MCE_ARI_APERTURES_MAX 6 + +/* each ARI aperture is 64KB */ +#define MCE_ARI_APERTURE_SIZE 0x10000 + +/******************************************************************************* + * CPU core ids - used by the MCE_ONLINE_CORE ARI + ******************************************************************************/ +typedef enum mce_core_id { + MCE_CORE_ID_DENVER_15_0, + MCE_CORE_ID_DENVER_15_1, + /* 2 and 3 are reserved */ + MCE_CORE_ID_A57_0 = 4, + MCE_CORE_ID_A57_1, + MCE_CORE_ID_A57_2, + MCE_CORE_ID_A57_3, + MCE_CORE_ID_MAX +} mce_core_id_t; + +#define MCE_CORE_ID_MASK 0x7 + +/******************************************************************************* + * MCE commands + ******************************************************************************/ +typedef enum mce_cmd { + MCE_CMD_ENTER_CSTATE = 0, + MCE_CMD_UPDATE_CSTATE_INFO, + MCE_CMD_UPDATE_CROSSOVER_TIME, + MCE_CMD_READ_CSTATE_STATS, + MCE_CMD_WRITE_CSTATE_STATS, + MCE_CMD_IS_SC7_ALLOWED, + MCE_CMD_ONLINE_CORE, + MCE_CMD_CC3_CTRL, + MCE_CMD_ECHO_DATA, + MCE_CMD_READ_VERSIONS, + MCE_CMD_ENUM_FEATURES, + MCE_CMD_ROC_FLUSH_CACHE_TRBITS, + MCE_CMD_ENUM_READ_MCA, + MCE_CMD_ENUM_WRITE_MCA, + MCE_CMD_ROC_FLUSH_CACHE, + MCE_CMD_ROC_CLEAN_CACHE, + MCE_CMD_IS_CCX_ALLOWED = 0xFE, + MCE_CMD_MAX = 0xFF, +} mce_cmd_t; + +#define MCE_CMD_MASK 0xFF + +/******************************************************************************* + * Macros to prepare CSTATE info request + ******************************************************************************/ +/* Description of the parameters for UPDATE_CSTATE_INFO request */ +#define CLUSTER_CSTATE_MASK 0x7 +#define CLUSTER_CSTATE_SHIFT 0 +#define CLUSTER_CSTATE_UPDATE_BIT (1 << 7) +#define CCPLEX_CSTATE_MASK 0x3 +#define CCPLEX_CSTATE_SHIFT 8 +#define CCPLEX_CSTATE_UPDATE_BIT (1 << 15) +#define SYSTEM_CSTATE_MASK 0xF +#define SYSTEM_CSTATE_SHIFT 16 +#define SYSTEM_CSTATE_FORCE_UPDATE_SHIFT 22 +#define SYSTEM_CSTATE_FORCE_UPDATE_BIT (1 << 22) +#define SYSTEM_CSTATE_UPDATE_BIT (1 << 23) +#define CSTATE_WAKE_MASK_UPDATE_BIT (1 << 31) +#define CSTATE_WAKE_MASK_SHIFT 32 +#define CSTATE_WAKE_MASK_CLEAR 0xFFFFFFFF + +/******************************************************************************* + * Auto-CC3 control macros + ******************************************************************************/ +#define MCE_AUTO_CC3_FREQ_MASK 0x1FF +#define MCE_AUTO_CC3_FREQ_SHIFT 0 +#define MCE_AUTO_CC3_VTG_MASK 0x7F +#define MCE_AUTO_CC3_VTG_SHIFT 16 +#define MCE_AUTO_CC3_ENABLE_BIT (1 << 31) + +/******************************************************************************* + * Macros for the 'IS_SC7_ALLOWED' command + ******************************************************************************/ +#define MCE_SC7_ALLOWED_MASK 0x7 +#define MCE_SC7_WAKE_TIME_SHIFT 32 + +/******************************************************************************* + * Macros for 'read/write ctats' commands + ******************************************************************************/ +#define MCE_CSTATE_STATS_TYPE_SHIFT 32 +#define MCE_CSTATE_WRITE_DATA_LO_MASK 0xF + +/******************************************************************************* + * Macros for 'update crossover threshold' command + ******************************************************************************/ +#define MCE_CROSSOVER_THRESHOLD_TIME_SHIFT 32 + +/******************************************************************************* + * Timeout value used to powerdown a core + ******************************************************************************/ +#define MCE_CORE_SLEEP_TIME_INFINITE 0xFFFFFFFF + +/******************************************************************************* + * MCA command struct + ******************************************************************************/ +typedef union mca_cmd { + struct command { + uint8_t cmd; + uint8_t idx; + uint8_t subidx; + } command; + struct input { + uint32_t low; + uint32_t high; + } input; + uint64_t data; +} mca_cmd_t; + +/******************************************************************************* + * MCA argument struct + ******************************************************************************/ +typedef union mca_arg { + struct err { + uint64_t error:8; + uint64_t unused:48; + uint64_t finish:8; + } err; + struct arg { + uint32_t low; + uint32_t high; + } arg; + uint64_t data; +} mca_arg_t; + +/******************************************************************************* + * Structure populated by arch specific code to export routines which perform + * common low level MCE functions + ******************************************************************************/ +typedef struct arch_mce_ops { + /* + * This ARI request sets up the MCE to start execution on assertion + * of STANDBYWFI, update the core power state and expected wake time, + * then determine the proper power state to enter. + */ + int (*enter_cstate)(uint32_t ari_base, uint32_t state, + uint32_t wake_time); + /* + * This ARI request allows updating of the CLUSTER_CSTATE, + * CCPLEX_CSTATE, and SYSTEM_CSTATE register values. + */ + int (*update_cstate_info)(uint32_t ari_base, + uint32_t cluster, + uint32_t ccplex, + uint32_t system, + uint8_t sys_state_force, + uint32_t wake_mask, + uint8_t update_wake_mask); + /* + * This ARI request allows updating of power state crossover + * threshold times. An index value specifies which crossover + * state is being updated. + */ + int (*update_crossover_time)(uint32_t ari_base, + uint32_t type, + uint32_t time); + /* + * This ARI request allows read access to statistical information + * related to power states. + */ + uint64_t (*read_cstate_stats)(uint32_t ari_base, + uint32_t state); + /* + * This ARI request allows write access to statistical information + * related to power states. + */ + int (*write_cstate_stats)(uint32_t ari_base, + uint32_t state, + uint32_t stats); + /* + * This ARI request allows the CPU to understand the features + * supported by the MCE firmware. + */ + uint64_t (*call_enum_misc)(uint32_t ari_base, uint32_t cmd, + uint32_t data); + /* + * This ARI request allows querying the CCPLEX to determine if + * the CCx state is allowed given a target core C-state and wake + * time. If the CCx state is allowed, the response indicates CCx + * must be entered. If the CCx state is not allowed, the response + * indicates CC6/CC7 can't be entered + */ + int (*is_ccx_allowed)(uint32_t ari_base, uint32_t state, + uint32_t wake_time); + /* + * This ARI request allows querying the CCPLEX to determine if + * the SC7 state is allowed given a target core C-state and wake + * time. If the SC7 state is allowed, all cores but the associated + * core are offlined (WAKE_EVENTS are set to 0) and the response + * indicates SC7 must be entered. If the SC7 state is not allowed, + * the response indicates SC7 can't be entered + */ + int (*is_sc7_allowed)(uint32_t ari_base, uint32_t state, + uint32_t wake_time); + /* + * This ARI request allows a core to bring another offlined core + * back online to the C0 state. Note that a core is offlined by + * entering a C-state where the WAKE_MASK is all 0. + */ + int (*online_core)(uint32_t ari_base, uint32_t cpuid); + /* + * This ARI request allows the CPU to enable/disable Auto-CC3 idle + * state. + */ + int (*cc3_ctrl)(uint32_t ari_base, + uint32_t freq, + uint32_t volt, + uint8_t enable); + /* + * This ARI request allows updating the reset vector register for + * D15 and A57 CPUs. + */ + int (*update_reset_vector)(uint32_t ari_base, + uint32_t addr_low, + uint32_t addr_high); + /* + * This ARI request instructs the ROC to flush A57 data caches in + * order to maintain coherency with the Denver cluster. + */ + int (*roc_flush_cache)(uint32_t ari_base); + /* + * This ARI request instructs the ROC to flush A57 data caches along + * with the caches covering ARM code in order to maintain coherency + * with the Denver cluster. + */ + int (*roc_flush_cache_trbits)(uint32_t ari_base); + /* + * This ARI request instructs the ROC to clean A57 data caches along + * with the caches covering ARM code in order to maintain coherency + * with the Denver cluster. + */ + int (*roc_clean_cache)(uint32_t ari_base); + /* + * This ARI request reads/writes the Machine Check Arch. (MCA) + * registers. + */ + uint64_t (*read_write_mca)(uint32_t ari_base, + mca_cmd_t cmd, + uint64_t *data); + /* + * Some MC GSC (General Security Carveout) register values are + * expected to be changed by TrustZone secure ARM code after boot. + * Since there is no hardware mechanism for the CCPLEX to know + * that an MC GSC register has changed to allow it to update its + * own internal GSC register, there needs to be a mechanism that + * can be used by ARM code to cause the CCPLEX to update its GSC + * register value. This ARI request allows updating the GSC register + * value for a certain carveout in the CCPLEX. + */ + int (*update_ccplex_gsc)(uint32_t ari_base, uint32_t gsc_idx); + /* + * This ARI request instructs the CCPLEX to either shutdown or + * reset the entire system + */ + void (*enter_ccplex_state)(uint32_t ari_base, uint32_t state_idx); +} arch_mce_ops_t; + +int mce_command_handler(mce_cmd_t cmd, uint64_t arg0, uint64_t arg1, + uint64_t arg2); +int mce_update_reset_vector(uint32_t addr_lo, uint32_t addr_hi); +int mce_update_gsc_videomem(void); +int mce_update_gsc_tzdram(void); +int mce_update_gsc_tzram(void); +__dead2 void mce_enter_ccplex_state(uint32_t state_idx); + +/* declarations for ARI/NVG handler functions */ +int ari_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time); +int ari_update_cstate_info(uint32_t ari_base, uint32_t cluster, uint32_t ccplex, + uint32_t system, uint8_t sys_state_force, uint32_t wake_mask, + uint8_t update_wake_mask); +int ari_update_crossover_time(uint32_t ari_base, uint32_t type, uint32_t time); +uint64_t ari_read_cstate_stats(uint32_t ari_base, uint32_t state); +int ari_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t stats); +uint64_t ari_enumeration_misc(uint32_t ari_base, uint32_t cmd, uint32_t data); +int ari_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time); +int ari_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time); +int ari_online_core(uint32_t ari_base, uint32_t core); +int ari_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable); +int ari_reset_vector_update(uint32_t ari_base, uint32_t lo, uint32_t hi); +int ari_roc_flush_cache_trbits(uint32_t ari_base); +int ari_roc_flush_cache(uint32_t ari_base); +int ari_roc_clean_cache(uint32_t ari_base); +uint64_t ari_read_write_mca(uint32_t ari_base, mca_cmd_t cmd, uint64_t *data); +int ari_update_ccplex_gsc(uint32_t ari_base, uint32_t gsc_idx); +void ari_enter_ccplex_state(uint32_t ari_base, uint32_t state_idx); + +int nvg_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time); +int nvg_update_cstate_info(uint32_t ari_base, uint32_t cluster, uint32_t ccplex, + uint32_t system, uint8_t sys_state_force, uint32_t wake_mask, + uint8_t update_wake_mask); +int nvg_update_crossover_time(uint32_t ari_base, uint32_t type, uint32_t time); +uint64_t nvg_read_cstate_stats(uint32_t ari_base, uint32_t state); +int nvg_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t val); +int nvg_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time); +int nvg_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time); +int nvg_online_core(uint32_t ari_base, uint32_t core); +int nvg_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable); + +#endif /* __MCE_H__ */ diff --git a/plat/nvidia/tegra/soc/t186/drivers/include/t18x_ari.h b/plat/nvidia/tegra/soc/t186/drivers/include/t18x_ari.h new file mode 100644 index 000000000..3e6054bd0 --- /dev/null +++ b/plat/nvidia/tegra/soc/t186/drivers/include/t18x_ari.h @@ -0,0 +1,450 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef T18X_TEGRA_ARI_H +#define T18X_TEGRA_ARI_H + +/* + * ---------------------------------------------------------------------------- + * t18x_ari.h + * + * Global ARI definitions. + * ---------------------------------------------------------------------------- + */ + +enum { + TEGRA_ARI_VERSION_MAJOR = 2, + TEGRA_ARI_VERSION_MINOR = 19, +}; + +typedef enum { + /* indexes below get the core lock */ + TEGRA_ARI_MISC = 0, + /* index 1 is deprecated */ + /* index 2 is deprecated */ + /* index 3 is deprecated */ + TEGRA_ARI_ONLINE_CORE = 4, + + /* indexes below need cluster lock */ + TEGRA_ARI_MISC_CLUSTER = 41, + TEGRA_ARI_IS_CCX_ALLOWED = 42, + TEGRA_ARI_CC3_CTRL = 43, + + /* indexes below need ccplex lock */ + TEGRA_ARI_ENTER_CSTATE = 80, + TEGRA_ARI_UPDATE_CSTATE_INFO = 81, + TEGRA_ARI_IS_SC7_ALLOWED = 82, + /* index 83 is deprecated */ + TEGRA_ARI_PERFMON = 84, + TEGRA_ARI_UPDATE_CCPLEX_GSC = 85, + /* index 86 is depracated */ + /* index 87 is deprecated */ + TEGRA_ARI_ROC_FLUSH_CACHE_ONLY = 88, + TEGRA_ARI_ROC_FLUSH_CACHE_TRBITS = 89, + TEGRA_ARI_MISC_CCPLEX = 90, + TEGRA_ARI_MCA = 91, + TEGRA_ARI_UPDATE_CROSSOVER = 92, + TEGRA_ARI_CSTATE_STATS = 93, + TEGRA_ARI_WRITE_CSTATE_STATS = 94, + TEGRA_ARI_COPY_MISCREG_AA64_RST = 95, + TEGRA_ARI_ROC_CLEAN_CACHE_ONLY = 96, +} tegra_ari_req_id_t; + +typedef enum { + TEGRA_ARI_MISC_ECHO = 0, + TEGRA_ARI_MISC_VERSION = 1, + TEGRA_ARI_MISC_FEATURE_LEAF_0 = 2, +} tegra_ari_misc_index_t; + +typedef enum { + TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF = 0, + TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT = 1, + TEGRA_ARI_MISC_CCPLEX_CORESIGHT_CG_CTRL = 2, +} tegra_ari_misc_ccplex_index_t; + +typedef enum { + TEGRA_ARI_CORE_C0 = 0, + TEGRA_ARI_CORE_C1 = 1, + TEGRA_ARI_CORE_C6 = 6, + TEGRA_ARI_CORE_C7 = 7, + TEGRA_ARI_CORE_WARMRSTREQ = 8, +} tegra_ari_core_sleep_state_t; + +typedef enum { + TEGRA_ARI_CLUSTER_CC0 = 0, + TEGRA_ARI_CLUSTER_CC1 = 1, + TEGRA_ARI_CLUSTER_CC6 = 6, + TEGRA_ARI_CLUSTER_CC7 = 7, +} tegra_ari_cluster_sleep_state_t; + +typedef enum { + TEGRA_ARI_CCPLEX_CCP0 = 0, + TEGRA_ARI_CCPLEX_CCP1 = 1, + TEGRA_ARI_CCPLEX_CCP3 = 3, +} tegra_ari_ccplex_sleep_state_t; + +typedef enum { + TEGRA_ARI_SYSTEM_SC0 = 0, + TEGRA_ARI_SYSTEM_SC1 = 1, + TEGRA_ARI_SYSTEM_SC2 = 2, + TEGRA_ARI_SYSTEM_SC3 = 3, + TEGRA_ARI_SYSTEM_SC4 = 4, + TEGRA_ARI_SYSTEM_SC7 = 7, + TEGRA_ARI_SYSTEM_SC8 = 8, +} tegra_ari_system_sleep_state_t; + +typedef enum { + TEGRA_ARI_CROSSOVER_C1_C6 = 0, + TEGRA_ARI_CROSSOVER_CC1_CC6 = 1, + TEGRA_ARI_CROSSOVER_CC1_CC7 = 2, + TEGRA_ARI_CROSSOVER_CCP1_CCP3 = 3, + TEGRA_ARI_CROSSOVER_CCP3_SC2 = 4, + TEGRA_ARI_CROSSOVER_CCP3_SC3 = 5, + TEGRA_ARI_CROSSOVER_CCP3_SC4 = 6, + TEGRA_ARI_CROSSOVER_CCP3_SC7 = 7, + TEGRA_ARI_CROSSOVER_CCP3_SC1 = 8, +} tegra_ari_crossover_index_t; + +typedef enum { + TEGRA_ARI_CSTATE_STATS_CLEAR = 0, + TEGRA_ARI_CSTATE_STATS_SC7_ENTRIES = 1, + TEGRA_ARI_CSTATE_STATS_SC4_ENTRIES, + TEGRA_ARI_CSTATE_STATS_SC3_ENTRIES, + TEGRA_ARI_CSTATE_STATS_SC2_ENTRIES, + TEGRA_ARI_CSTATE_STATS_CCP3_ENTRIES, + TEGRA_ARI_CSTATE_STATS_A57_CC6_ENTRIES, + TEGRA_ARI_CSTATE_STATS_A57_CC7_ENTRIES, + TEGRA_ARI_CSTATE_STATS_D15_CC6_ENTRIES, + TEGRA_ARI_CSTATE_STATS_D15_CC7_ENTRIES, + TEGRA_ARI_CSTATE_STATS_D15_0_C6_ENTRIES, + TEGRA_ARI_CSTATE_STATS_D15_1_C6_ENTRIES, + TEGRA_ARI_CSTATE_STATS_D15_0_C7_ENTRIES = 14, + TEGRA_ARI_CSTATE_STATS_D15_1_C7_ENTRIES, + TEGRA_ARI_CSTATE_STATS_A57_0_C7_ENTRIES = 18, + TEGRA_ARI_CSTATE_STATS_A57_1_C7_ENTRIES, + TEGRA_ARI_CSTATE_STATS_A57_2_C7_ENTRIES, + TEGRA_ARI_CSTATE_STATS_A57_3_C7_ENTRIES, + TEGRA_ARI_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_0, + TEGRA_ARI_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_1, + TEGRA_ARI_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_0 = 26, + TEGRA_ARI_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_1, + TEGRA_ARI_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_2, + TEGRA_ARI_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_3, +} tegra_ari_cstate_stats_index_t; + +typedef enum { + TEGRA_ARI_GSC_ALL = 0, + + TEGRA_ARI_GSC_BPMP = 6, + TEGRA_ARI_GSC_APE = 7, + TEGRA_ARI_GSC_SPE = 8, + TEGRA_ARI_GSC_SCE = 9, + TEGRA_ARI_GSC_APR = 10, + TEGRA_ARI_GSC_TZRAM = 11, + TEGRA_ARI_GSC_SE = 12, + + TEGRA_ARI_GSC_BPMP_TO_SPE = 16, + TEGRA_ARI_GSC_SPE_TO_BPMP = 17, + TEGRA_ARI_GSC_CPU_TZ_TO_BPMP = 18, + TEGRA_ARI_GSC_BPMP_TO_CPU_TZ = 19, + TEGRA_ARI_GSC_CPU_NS_TO_BPMP = 20, + TEGRA_ARI_GSC_BPMP_TO_CPU_NS = 21, + TEGRA_ARI_GSC_IPC_SE_SPE_SCE_BPMP = 22, + TEGRA_ARI_GSC_SC7_RESUME_FW = 23, + + TEGRA_ARI_GSC_TZ_DRAM_IDX = 34, + TEGRA_ARI_GSC_VPR_IDX = 35, +} tegra_ari_gsc_index_t; + +/* This macro will produce enums for __name##_LSB, __name##_MSB and __name##_MSK */ +#define TEGRA_ARI_ENUM_MASK_LSB_MSB(__name, __lsb, __msb) __name##_LSB = __lsb, __name##_MSB = __msb + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__CLUSTER_CSTATE, 0, 2), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__CLUSTER_CSTATE_PRESENT, 7, 7), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__CCPLEX_CSTATE, 8, 9), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__CCPLEX_CSTATE_PRESENT, 15, 15), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__SYSTEM_CSTATE, 16, 19), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__IGNORE_CROSSOVERS, 22, 22), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__SYSTEM_CSTATE_PRESENT, 23, 23), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_UPDATE_CSTATE_INFO__WAKE_MASK_PRESENT, 31, 31), +} tegra_ari_update_cstate_info_bitmasks_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MISC_CCPLEX_CORESIGHT_CG_CTRL__EN, 0, 0), +} tegra_ari_misc_ccplex_bitmasks_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_CC3_CTRL__IDLE_FREQ, 0, 8), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_CC3_CTRL__IDLE_VOLT, 16, 23), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_CC3_CTRL__ENABLE, 31, 31), +} tegra_ari_cc3_ctrl_bitmasks_t; + +typedef enum { + TEGRA_ARI_MCA_NOP = 0, + TEGRA_ARI_MCA_READ_SERR = 1, + TEGRA_ARI_MCA_WRITE_SERR = 2, + TEGRA_ARI_MCA_CLEAR_SERR = 4, + TEGRA_ARI_MCA_REPORT_SERR = 5, + TEGRA_ARI_MCA_READ_INTSTS = 6, + TEGRA_ARI_MCA_WRITE_INTSTS = 7, + TEGRA_ARI_MCA_READ_PREBOOT_SERR = 8, +} tegra_ari_mca_commands_t; + +typedef enum { + TEGRA_ARI_MCA_RD_WR_DPMU = 0, + TEGRA_ARI_MCA_RD_WR_IOB = 1, + TEGRA_ARI_MCA_RD_WR_MCB = 2, + TEGRA_ARI_MCA_RD_WR_CCE = 3, + TEGRA_ARI_MCA_RD_WR_CQX = 4, + TEGRA_ARI_MCA_RD_WR_CTU = 5, + TEGRA_ARI_MCA_RD_BANK_INFO = 0x0f, + TEGRA_ARI_MCA_RD_BANK_TEMPLATE = 0x10, + TEGRA_ARI_MCA_RD_WR_SECURE_ACCESS_REGISTER = 0x11, + TEGRA_ARI_MCA_RD_WR_GLOBAL_CONFIG_REGISTER = 0x12, +} tegra_ari_mca_rd_wr_indexes_t; + +typedef enum { + TEGRA_ARI_MCA_RD_WR_ASERRX_CTRL = 0, + TEGRA_ARI_MCA_RD_WR_ASERRX_STATUS = 1, + TEGRA_ARI_MCA_RD_WR_ASERRX_ADDR = 2, + TEGRA_ARI_MCA_RD_WR_ASERRX_MISC1 = 3, + TEGRA_ARI_MCA_RD_WR_ASERRX_MISC2 = 4, +} tegra_ari_mca_read_asserx_subindexes_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SECURE_REGISTER_SETTING_ENABLES_NS_PERMITTED, 0, 0), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SECURE_REGISTER_READING_STATUS_NS_PERMITTED, 1, 1), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SECURE_REGISTER_PENDING_MCA_ERRORS_NS_PERMITTED, 2, 2), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_SECURE_REGISTER_CLEARING_MCA_INTERRUPTS_NS_PERMITTED, 3, 3), +} tegra_ari_mca_secure_register_bitmasks_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_SERR_ERR_CODE, 0, 15), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_PWM_ERR, 16, 16), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_CRAB_ERR, 17, 17), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_RD_WR_N, 18, 18), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_UCODE_ERR, 19, 19), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_PWM, 20, 23), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_AV, 58, 58), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_MV, 59, 59), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_EN, 60, 60), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_UC, 61, 61), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_OVF, 62, 62), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_STAT_VAL, 63, 63), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_ADDR_ADDR, 0, 41), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_ADDR_UCODE_ERRCD, 42, 52), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_CTRL_EN_PWM_ERR, 0, 0), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_CTRL_EN_CRAB_ERR, 1, 1), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR0_CTRL_EN_UCODE_ERR, 3, 3), +} tegra_ari_mca_aserr0_bitmasks_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_SERR_ERR_CODE, 0, 15), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_MSI_ERR, 16, 16), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_IHI_ERR, 17, 17), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_CRI_ERR, 18, 18), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_MMCRAB_ERR, 19, 19), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_CSI_ERR, 20, 20), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_RD_WR_N, 21, 21), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_REQ_ERRT, 22, 23), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_RESP_ERRT, 24, 25), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_AV, 58, 58), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_MV, 59, 59), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_EN, 60, 60), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_UC, 61, 61), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_OVF, 62, 62), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_VAL, 63, 63), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_AXI_ID, 0, 7), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_CQX_ID, 8, 27), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_CQX_CID, 28, 31), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_STAT_CQX_CMD, 32, 35), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_CTRL_EN_MSI_ERR, 0, 0), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_CTRL_EN_IHI_ERR, 1, 1), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_CTRL_EN_CRI_ERR, 2, 2), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_CTRL_EN_MMCRAB_ERR, 3, 3), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_CTRL_EN_CSI_ERR, 4, 4), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR1_MISC_ADDR, 0, 41), +} tegra_ari_mca_aserr1_bitmasks_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_SERR_ERR_CODE, 0, 15), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_MC_ERR, 16, 16), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_SYSRAM_ERR, 17, 17), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_CLIENT_ID, 18, 19), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_AV, 58, 58), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_MV, 59, 59), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_EN, 60, 60), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_UC, 61, 61), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_OVF, 62, 62), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_STAT_VAL, 63, 63), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_ADDR_ID, 0, 17), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_ADDR_CMD, 18, 21), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_ADDR_ADDR, 22, 53), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR2_CTRL_EN_MC_ERR, 0, 0), +} tegra_ari_mca_aserr2_bitmasks_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_SERR_ERR_CODE, 0, 15), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_TO_ERR, 16, 16), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_STAT_ERR, 17, 17), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_DST_ERR, 18, 18), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_UNC_ERR, 19, 19), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_MH_ERR, 20, 20), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_PERR, 21, 21), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_PSN_ERR, 22, 22), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_AV, 58, 58), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_MV, 59, 59), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_EN, 60, 60), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_UC, 61, 61), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_OVF, 62, 62), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_STAT_VAL, 63, 63), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_ADDR_CMD, 0, 5), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_ADDR_ADDR, 6, 47), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC1_TO, 0, 0), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC1_DIV4, 1, 1), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC1_TLIMIT, 2, 11), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC1_PSN_ERR_CORR_MSK, 12, 25), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC2_MORE_INFO, 0, 17), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC2_TO_INFO, 18, 43), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC2_SRC, 44, 45), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_MISC2_TID, 46, 52), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_TO_ERR, 0, 0), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_STAT_ERR, 1, 1), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_DST_ERR, 2, 2), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_UNC_ERR, 3, 3), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_MH_ERR, 4, 4), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_PERR, 5, 5), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR3_CTRL_EN_PSN_ERR, 6, 19), +} tegra_ari_mca_aserr3_bitmasks_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_SERR_ERR_CODE, 0, 15), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_SRC_ERR, 16, 16), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_DST_ERR, 17, 17), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_REQ_ERR, 18, 18), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_RSP_ERR, 19, 19), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_AV, 58, 58), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_MV, 59, 59), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_EN, 60, 60), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_UC, 61, 61), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_OVF, 62, 62), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_STAT_VAL, 63, 63), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR4_CTRL_EN_CPE_ERR, 0, 0), +} tegra_ari_mca_aserr4_bitmasks_t; + +typedef enum { + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_SERR_ERR_CODE, 0, 15), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_CTUPAR, 16, 16), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_MULTI, 17, 17), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_AV, 58, 58), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_MV, 59, 59), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_EN, 60, 60), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_UC, 61, 61), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_OVF, 62, 62), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_STAT_VAL, 63, 63), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_ADDR_SRC, 0, 7), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_ADDR_ID, 8, 15), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_ADDR_DATA, 16, 26), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_ADDR_CMD, 32, 35), + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_ADDR_ADDR, 36, 45), + + TEGRA_ARI_ENUM_MASK_LSB_MSB(TEGRA_ARI_MCA_ASERR5_CTRL_EN_CTUPAR, 0, 0), +} tegra_ari_mca_aserr5_bitmasks_t; + +#undef TEGRA_ARI_ENUM_MASK_LSB_MSB + +typedef enum { + TEGRA_NVG_CHANNEL_PMIC = 0, + TEGRA_NVG_CHANNEL_POWER_PERF = 1, + TEGRA_NVG_CHANNEL_POWER_MODES = 2, + TEGRA_NVG_CHANNEL_WAKE_TIME = 3, + TEGRA_NVG_CHANNEL_CSTATE_INFO = 4, + TEGRA_NVG_CHANNEL_CROSSOVER_C1_C6 = 5, + TEGRA_NVG_CHANNEL_CROSSOVER_CC1_CC6 = 6, + TEGRA_NVG_CHANNEL_CROSSOVER_CC1_CC7 = 7, + TEGRA_NVG_CHANNEL_CROSSOVER_CCP1_CCP3 = 8, + TEGRA_NVG_CHANNEL_CROSSOVER_CCP3_SC2 = 9, + TEGRA_NVG_CHANNEL_CROSSOVER_CCP3_SC3 = 10, + TEGRA_NVG_CHANNEL_CROSSOVER_CCP3_SC4 = 11, + TEGRA_NVG_CHANNEL_CROSSOVER_CCP3_SC7 = 12, + TEGRA_NVG_CHANNEL_CSTATE_STATS_CLEAR = 13, + TEGRA_NVG_CHANNEL_CSTATE_STATS_SC7_ENTRIES = 14, + TEGRA_NVG_CHANNEL_CSTATE_STATS_SC4_ENTRIES = 15, + TEGRA_NVG_CHANNEL_CSTATE_STATS_SC3_ENTRIES = 16, + TEGRA_NVG_CHANNEL_CSTATE_STATS_SC2_ENTRIES = 17, + TEGRA_NVG_CHANNEL_CSTATE_STATS_CCP3_ENTRIES = 18, + TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_CC6_ENTRIES = 19, + TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_CC7_ENTRIES = 20, + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_CC6_ENTRIES = 21, + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_CC7_ENTRIES = 22, + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_0_C6_ENTRIES = 23, + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_1_C6_ENTRIES = 24, + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_2_C6_ENTRIES = 25, /* Reserved (for Denver15 core 2) */ + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_3_C6_ENTRIES = 26, /* Reserved (for Denver15 core 3) */ + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_0_C7_ENTRIES = 27, + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_1_C7_ENTRIES = 28, + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_2_C7_ENTRIES = 29, /* Reserved (for Denver15 core 2) */ + TEGRA_NVG_CHANNEL_CSTATE_STATS_D15_3_C7_ENTRIES = 30, /* Reserved (for Denver15 core 3) */ + TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_0_C7_ENTRIES = 31, + TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_1_C7_ENTRIES = 32, + TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_2_C7_ENTRIES = 33, + TEGRA_NVG_CHANNEL_CSTATE_STATS_A57_3_C7_ENTRIES = 34, + TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_0 = 35, + TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_1 = 36, + TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_2 = 37, /* Reserved (for Denver15 core 2) */ + TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_D15_3 = 38, /* Reserved (for Denver15 core 3) */ + TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_0 = 39, + TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_1 = 40, + TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_2 = 41, + TEGRA_NVG_CHANNEL_CSTATE_STATS_LAST_CSTATE_ENTRY_A57_3 = 42, + TEGRA_NVG_CHANNEL_IS_SC7_ALLOWED = 43, + TEGRA_NVG_CHANNEL_ONLINE_CORE = 44, + TEGRA_NVG_CHANNEL_CC3_CTRL = 45, + TEGRA_NVG_CHANNEL_CROSSOVER_CCP3_SC1 = 46, + TEGRA_NVG_CHANNEL_LAST_INDEX, +} tegra_nvg_channel_id_t; + +#endif /* T18X_TEGRA_ARI_H */ + + diff --git a/plat/nvidia/tegra/soc/t186/drivers/mce/aarch64/nvg_helpers.S b/plat/nvidia/tegra/soc/t186/drivers/mce/aarch64/nvg_helpers.S new file mode 100644 index 000000000..e1398ccee --- /dev/null +++ b/plat/nvidia/tegra/soc/t186/drivers/mce/aarch64/nvg_helpers.S @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include + + .globl nvg_set_request_data + .globl nvg_set_request + .globl nvg_get_result + +/* void nvg_set_request_data(uint64_t req, uint64_t data) */ +func nvg_set_request_data + msr s3_0_c15_c1_2, x0 + msr s3_0_c15_c1_3, x1 + isb + ret +endfunc nvg_set_request_data + +/* void nvg_set_request(uint64_t req) */ +func nvg_set_request + msr s3_0_c15_c1_2, x0 + ret +endfunc nvg_set_request + +/* uint64_t nvg_get_result(void) */ +func nvg_get_result + mrs x0, s3_0_c15_c1_3 + ret +endfunc nvg_get_result diff --git a/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c b/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c new file mode 100644 index 000000000..147a358ae --- /dev/null +++ b/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c @@ -0,0 +1,391 @@ +/* + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * Register offsets for ARI request/results + ******************************************************************************/ +#define ARI_REQUEST 0x0 +#define ARI_REQUEST_EVENT_MASK 0x4 +#define ARI_STATUS 0x8 +#define ARI_REQUEST_DATA_LO 0xC +#define ARI_REQUEST_DATA_HI 0x10 +#define ARI_RESPONSE_DATA_LO 0x14 +#define ARI_RESPONSE_DATA_HI 0x18 + +/* Status values for the current request */ +#define ARI_REQ_PENDING 1 +#define ARI_REQ_ONGOING 3 +#define ARI_REQUEST_VALID_BIT (1 << 8) +#define ARI_EVT_MASK_STANDBYWFI_BIT (1 << 7) + +/******************************************************************************* + * ARI helper functions + ******************************************************************************/ +static inline uint32_t ari_read_32(uint32_t ari_base, uint32_t reg) +{ + return mmio_read_32(ari_base + reg); +} + +static inline void ari_write_32(uint32_t ari_base, uint32_t val, uint32_t reg) +{ + mmio_write_32(ari_base + reg, val); +} + +static inline uint32_t ari_get_request_low(uint32_t ari_base) +{ + return ari_read_32(ari_base, ARI_REQUEST_DATA_LO); +} + +static inline uint32_t ari_get_request_high(uint32_t ari_base) +{ + return ari_read_32(ari_base, ARI_REQUEST_DATA_HI); +} + +static inline uint32_t ari_get_response_low(uint32_t ari_base) +{ + return ari_read_32(ari_base, ARI_RESPONSE_DATA_LO); +} + +static inline uint32_t ari_get_response_high(uint32_t ari_base) +{ + return ari_read_32(ari_base, ARI_RESPONSE_DATA_HI); +} + +static inline void ari_clobber_response(uint32_t ari_base) +{ + ari_write_32(ari_base, 0, ARI_RESPONSE_DATA_LO); + ari_write_32(ari_base, 0, ARI_RESPONSE_DATA_HI); +} + +static int ari_request_wait(uint32_t ari_base, uint32_t evt_mask, uint32_t req, + uint32_t lo, uint32_t hi) +{ + int status; + + /* program the request, event_mask, hi and lo registers */ + ari_write_32(ari_base, lo, ARI_REQUEST_DATA_LO); + ari_write_32(ari_base, hi, ARI_REQUEST_DATA_HI); + ari_write_32(ari_base, evt_mask, ARI_REQUEST_EVENT_MASK); + ari_write_32(ari_base, req | ARI_REQUEST_VALID_BIT, ARI_REQUEST); + + /* + * For commands that have an event trigger, we should bypass + * ARI_STATUS polling, since MCE is waiting for SW to trigger + * the event. + */ + if (evt_mask) + return 0; + + /* NOTE: add timeout check if needed */ + status = ari_read_32(ari_base, ARI_STATUS); + while (status & (ARI_REQ_ONGOING | ARI_REQ_PENDING)) + status = ari_read_32(ari_base, ARI_STATUS); + + return 0; +} + +int ari_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time) +{ + /* check for allowed power state */ + if (state != TEGRA_ARI_CORE_C0 && state != TEGRA_ARI_CORE_C1 && + state != TEGRA_ARI_CORE_C6 && state != TEGRA_ARI_CORE_C7) { + ERROR("%s: unknown cstate (%d)\n", __func__, state); + return EINVAL; + } + + /* Enter the cstate, to be woken up after wake_time (TSC ticks) */ + return ari_request_wait(ari_base, ARI_EVT_MASK_STANDBYWFI_BIT, + TEGRA_ARI_ENTER_CSTATE, state, wake_time); +} + +int ari_update_cstate_info(uint32_t ari_base, uint32_t cluster, uint32_t ccplex, + uint32_t system, uint8_t sys_state_force, uint32_t wake_mask, + uint8_t update_wake_mask) +{ + uint32_t val = 0; + + /* update CLUSTER_CSTATE? */ + if (cluster) + val |= (cluster & CLUSTER_CSTATE_MASK) | + CLUSTER_CSTATE_UPDATE_BIT; + + /* update CCPLEX_CSTATE? */ + if (ccplex) + val |= (ccplex & CCPLEX_CSTATE_MASK) << CCPLEX_CSTATE_SHIFT | + CCPLEX_CSTATE_UPDATE_BIT; + + /* update SYSTEM_CSTATE? */ + if (system) + val |= ((system & SYSTEM_CSTATE_MASK) << SYSTEM_CSTATE_SHIFT) | + ((sys_state_force << SYSTEM_CSTATE_FORCE_UPDATE_SHIFT) | + SYSTEM_CSTATE_UPDATE_BIT); + + /* update wake mask value? */ + if (update_wake_mask) + val |= CSTATE_WAKE_MASK_UPDATE_BIT; + + /* set the updated cstate info */ + return ari_request_wait(ari_base, 0, TEGRA_ARI_UPDATE_CSTATE_INFO, val, + wake_mask); +} + +int ari_update_crossover_time(uint32_t ari_base, uint32_t type, uint32_t time) +{ + /* sanity check crossover type */ + if ((type == TEGRA_ARI_CROSSOVER_C1_C6) || + (type > TEGRA_ARI_CROSSOVER_CCP3_SC1)) + return EINVAL; + + /* update crossover threshold time */ + return ari_request_wait(ari_base, 0, TEGRA_ARI_UPDATE_CROSSOVER, + type, time); +} + +uint64_t ari_read_cstate_stats(uint32_t ari_base, uint32_t state) +{ + int ret; + + /* sanity check crossover type */ + if (state == 0) + return EINVAL; + + ret = ari_request_wait(ari_base, 0, TEGRA_ARI_CSTATE_STATS, state, 0); + if (ret != 0) + return EINVAL; + + return (uint64_t)ari_get_response_low(ari_base); +} + +int ari_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t stats) +{ + /* write the cstate stats */ + return ari_request_wait(ari_base, 0, TEGRA_ARI_WRITE_CSTATE_STATS, state, + stats); +} + +uint64_t ari_enumeration_misc(uint32_t ari_base, uint32_t cmd, uint32_t data) +{ + uint64_t resp; + int ret; + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + /* ARI_REQUEST_DATA_HI is reserved for commands other than 'ECHO' */ + if (cmd != TEGRA_ARI_MISC_ECHO) + data = 0; + + ret = ari_request_wait(ari_base, 0, TEGRA_ARI_MISC, cmd, data); + if (ret) + return (uint64_t)ret; + + /* get the command response */ + resp = ari_get_response_low(ari_base); + resp |= ((uint64_t)ari_get_response_high(ari_base) << 32); + + return resp; +} + +int ari_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time) +{ + int ret; + + ret = ari_request_wait(ari_base, 0, TEGRA_ARI_IS_CCX_ALLOWED, state & 0x7, + wake_time); + if (ret) { + ERROR("%s: failed (%d)\n", __func__, ret); + return 0; + } + + /* 1 = CCx allowed, 0 = CCx not allowed */ + return (ari_get_response_low(ari_base) & 0x1); +} + +int ari_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time) +{ + int ret; + + /* check for allowed power state */ + if (state != TEGRA_ARI_CORE_C0 && state != TEGRA_ARI_CORE_C1 && + state != TEGRA_ARI_CORE_C6 && state != TEGRA_ARI_CORE_C7) { + ERROR("%s: unknown cstate (%d)\n", __func__, state); + return EINVAL; + } + + ret = ari_request_wait(ari_base, 0, TEGRA_ARI_IS_SC7_ALLOWED, state, + wake_time); + if (ret) { + ERROR("%s: failed (%d)\n", __func__, ret); + return 0; + } + + /* 1 = SC7 allowed, 0 = SC7 not allowed */ + return !!ari_get_response_low(ari_base); +} + +int ari_online_core(uint32_t ari_base, uint32_t core) +{ + int cpu = read_mpidr() & MPIDR_CPU_MASK; + int cluster = (read_mpidr() & MPIDR_CLUSTER_MASK) >> + MPIDR_AFFINITY_BITS; + int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; + + /* construct the current CPU # */ + cpu |= (cluster << 2); + + /* sanity check target core id */ + if ((core >= MCE_CORE_ID_MAX) || (cpu == core)) { + ERROR("%s: unsupported core id (%d)\n", __func__, core); + return EINVAL; + } + + /* + * The Denver cluster has 2 CPUs only - 0, 1. + */ + if (impl == DENVER_IMPL && ((core == 2) || (core == 3))) { + ERROR("%s: unknown core id (%d)\n", __func__, core); + return EINVAL; + } + + return ari_request_wait(ari_base, 0, TEGRA_ARI_ONLINE_CORE, core, 0); +} + +int ari_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable) +{ + int val; + + /* + * If the enable bit is cleared, Auto-CC3 will be disabled by setting + * the SW visible voltage/frequency request registers for all non + * floorswept cores valid independent of StandbyWFI and disabling + * the IDLE voltage/frequency request register. If set, Auto-CC3 + * will be enabled by setting the ARM SW visible voltage/frequency + * request registers for all non floorswept cores to be enabled by + * StandbyWFI or the equivalent signal, and always keeping the IDLE + * voltage/frequency request register enabled. + */ + val = (((freq & MCE_AUTO_CC3_FREQ_MASK) << MCE_AUTO_CC3_FREQ_SHIFT) |\ + ((volt & MCE_AUTO_CC3_VTG_MASK) << MCE_AUTO_CC3_VTG_SHIFT) |\ + (enable ? MCE_AUTO_CC3_ENABLE_BIT : 0)); + + return ari_request_wait(ari_base, 0, TEGRA_ARI_CC3_CTRL, val, 0); +} + +int ari_reset_vector_update(uint32_t ari_base, uint32_t lo, uint32_t hi) +{ + /* + * Need to program the CPU reset vector one time during cold boot + * and SC7 exit + */ + ari_request_wait(ari_base, 0, TEGRA_ARI_COPY_MISCREG_AA64_RST, lo, hi); + + return 0; +} + +int ari_roc_flush_cache_trbits(uint32_t ari_base) +{ + return ari_request_wait(ari_base, 0, TEGRA_ARI_ROC_FLUSH_CACHE_TRBITS, + 0, 0); +} + +int ari_roc_flush_cache(uint32_t ari_base) +{ + return ari_request_wait(ari_base, 0, TEGRA_ARI_ROC_FLUSH_CACHE_ONLY, + 0, 0); +} + +int ari_roc_clean_cache(uint32_t ari_base) +{ + return ari_request_wait(ari_base, 0, TEGRA_ARI_ROC_CLEAN_CACHE_ONLY, + 0, 0); +} + +uint64_t ari_read_write_mca(uint32_t ari_base, mca_cmd_t cmd, uint64_t *data) +{ + mca_arg_t mca_arg; + int ret; + + /* Set data (write) */ + mca_arg.data = data ? *data : 0ull; + + /* Set command */ + ari_write_32(ari_base, cmd.input.low, ARI_RESPONSE_DATA_LO); + ari_write_32(ari_base, cmd.input.high, ARI_RESPONSE_DATA_HI); + + ret = ari_request_wait(ari_base, 0, TEGRA_ARI_MCA, mca_arg.arg.low, + mca_arg.arg.high); + if (!ret) { + mca_arg.arg.low = ari_get_response_low(ari_base); + mca_arg.arg.high = ari_get_response_high(ari_base); + if (!mca_arg.err.finish) + return (uint64_t)mca_arg.err.error; + + if (data) { + mca_arg.arg.low = ari_get_request_low(ari_base); + mca_arg.arg.high = ari_get_request_high(ari_base); + *data = mca_arg.data; + } + } + + return 0; +} + +int ari_update_ccplex_gsc(uint32_t ari_base, uint32_t gsc_idx) +{ + /* sanity check GSC ID */ + if (gsc_idx > TEGRA_ARI_GSC_VPR_IDX) + return EINVAL; + + /* + * The MCE code will read the GSC carveout value, corrseponding to + * the ID, from the MC registers and update the internal GSC registers + * of the CCPLEX. + */ + ari_request_wait(ari_base, 0, TEGRA_ARI_UPDATE_CCPLEX_GSC, gsc_idx, 0); + + return 0; +} + +void ari_enter_ccplex_state(uint32_t ari_base, uint32_t state_idx) +{ + /* + * The MCE will shutdown or restart the entire system + */ + (void)ari_request_wait(ari_base, 0, TEGRA_ARI_MISC_CCPLEX, state_idx, 0); +} diff --git a/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c b/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c new file mode 100644 index 000000000..981510708 --- /dev/null +++ b/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c @@ -0,0 +1,432 @@ +/* + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* NVG functions handlers */ +static arch_mce_ops_t nvg_mce_ops = { + .enter_cstate = nvg_enter_cstate, + .update_cstate_info = nvg_update_cstate_info, + .update_crossover_time = nvg_update_crossover_time, + .read_cstate_stats = nvg_read_cstate_stats, + .write_cstate_stats = nvg_write_cstate_stats, + .call_enum_misc = ari_enumeration_misc, + .is_ccx_allowed = nvg_is_ccx_allowed, + .is_sc7_allowed = nvg_is_sc7_allowed, + .online_core = nvg_online_core, + .cc3_ctrl = nvg_cc3_ctrl, + .update_reset_vector = ari_reset_vector_update, + .roc_flush_cache = ari_roc_flush_cache, + .roc_flush_cache_trbits = ari_roc_flush_cache_trbits, + .roc_clean_cache = ari_roc_clean_cache, + .read_write_mca = ari_read_write_mca, + .update_ccplex_gsc = ari_update_ccplex_gsc, + .enter_ccplex_state = ari_enter_ccplex_state +}; + +/* ARI functions handlers */ +static arch_mce_ops_t ari_mce_ops = { + .enter_cstate = ari_enter_cstate, + .update_cstate_info = ari_update_cstate_info, + .update_crossover_time = ari_update_crossover_time, + .read_cstate_stats = ari_read_cstate_stats, + .write_cstate_stats = ari_write_cstate_stats, + .call_enum_misc = ari_enumeration_misc, + .is_ccx_allowed = ari_is_ccx_allowed, + .is_sc7_allowed = ari_is_sc7_allowed, + .online_core = ari_online_core, + .cc3_ctrl = ari_cc3_ctrl, + .update_reset_vector = ari_reset_vector_update, + .roc_flush_cache = ari_roc_flush_cache, + .roc_flush_cache_trbits = ari_roc_flush_cache_trbits, + .roc_clean_cache = ari_roc_clean_cache, + .read_write_mca = ari_read_write_mca, + .update_ccplex_gsc = ari_update_ccplex_gsc, + .enter_ccplex_state = ari_enter_ccplex_state +}; + +typedef struct mce_config { + uint32_t ari_base; + arch_mce_ops_t *ops; +} mce_config_t; + +/* Table to hold the per-CPU ARI base address and function handlers */ +static mce_config_t mce_cfg_table[MCE_ARI_APERTURES_MAX] = { + { + /* A57 Core 0 */ + .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_0_OFFSET, + .ops = &ari_mce_ops, + }, + { + /* A57 Core 1 */ + .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_1_OFFSET, + .ops = &ari_mce_ops, + }, + { + /* A57 Core 2 */ + .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_2_OFFSET, + .ops = &ari_mce_ops, + }, + { + /* A57 Core 3 */ + .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_3_OFFSET, + .ops = &ari_mce_ops, + }, + { + /* D15 Core 0 */ + .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_4_OFFSET, + .ops = &nvg_mce_ops, + }, + { + /* D15 Core 1 */ + .ari_base = TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_5_OFFSET, + .ops = &nvg_mce_ops, + } +}; + +static uint32_t mce_get_curr_cpu_ari_base(void) +{ + uint32_t mpidr = read_mpidr(); + int cpuid = mpidr & MPIDR_CPU_MASK; + int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; + + /* + * T186 has 2 CPU clusters, one with Denver CPUs and the other with + * ARM CortexA-57 CPUs. Each cluster consists of 4 CPUs and the CPU + * numbers start from 0. In order to get the proper arch_mce_ops_t + * struct, we have to convert the Denver CPU ids to the corresponding + * indices in the mce_ops_table array. + */ + if (impl == DENVER_IMPL) + cpuid |= 0x4; + + return mce_cfg_table[cpuid].ari_base; +} + +static arch_mce_ops_t *mce_get_curr_cpu_ops(void) +{ + uint32_t mpidr = read_mpidr(); + int cpuid = mpidr & MPIDR_CPU_MASK; + int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; + + /* + * T186 has 2 CPU clusters, one with Denver CPUs and the other with + * ARM CortexA-57 CPUs. Each cluster consists of 4 CPUs and the CPU + * numbers start from 0. In order to get the proper arch_mce_ops_t + * struct, we have to convert the Denver CPU ids to the corresponding + * indices in the mce_ops_table array. + */ + if (impl == DENVER_IMPL) + cpuid |= 0x4; + + return mce_cfg_table[cpuid].ops; +} + +/******************************************************************************* + * Common handler for all MCE commands + ******************************************************************************/ +int mce_command_handler(mce_cmd_t cmd, uint64_t arg0, uint64_t arg1, + uint64_t arg2) +{ + arch_mce_ops_t *ops; + uint32_t cpu_ari_base; + uint64_t ret64 = 0, arg3, arg4, arg5; + int ret = 0; + mca_cmd_t mca_cmd; + cpu_context_t *ctx = cm_get_context(NON_SECURE); + gp_regs_t *gp_regs = get_gpregs_ctx(ctx); + + assert(ctx); + assert(gp_regs); + + /* get a pointer to the CPU's arch_mce_ops_t struct */ + ops = mce_get_curr_cpu_ops(); + + /* get the CPU's ARI base address */ + cpu_ari_base = mce_get_curr_cpu_ari_base(); + + switch (cmd) { + case MCE_CMD_ENTER_CSTATE: + ret = ops->enter_cstate(cpu_ari_base, arg0, arg1); + if (ret < 0) + ERROR("%s: enter_cstate failed(%d)\n", __func__, ret); + + break; + + case MCE_CMD_UPDATE_CSTATE_INFO: + /* + * get the parameters required for the update cstate info + * command + */ + arg3 = read_ctx_reg(gp_regs, CTX_GPREG_X4); + arg4 = read_ctx_reg(gp_regs, CTX_GPREG_X5); + arg5 = read_ctx_reg(gp_regs, CTX_GPREG_X6); + + ret = ops->update_cstate_info(cpu_ari_base, (uint32_t)arg0, + (uint32_t)arg1, (uint32_t)arg2, (uint8_t)arg3, + (uint32_t)arg4, (uint8_t)arg5); + if (ret < 0) + ERROR("%s: update_cstate_info failed(%d)\n", + __func__, ret); + + write_ctx_reg(gp_regs, CTX_GPREG_X4, 0); + write_ctx_reg(gp_regs, CTX_GPREG_X5, 0); + write_ctx_reg(gp_regs, CTX_GPREG_X6, 0); + + break; + + case MCE_CMD_UPDATE_CROSSOVER_TIME: + ret = ops->update_crossover_time(cpu_ari_base, arg0, arg1); + if (ret < 0) + ERROR("%s: update_crossover_time failed(%d)\n", + __func__, ret); + + break; + + case MCE_CMD_READ_CSTATE_STATS: + ret64 = ops->read_cstate_stats(cpu_ari_base, arg0); + + /* update context to return cstate stats value */ + write_ctx_reg(gp_regs, CTX_GPREG_X1, ret64); + write_ctx_reg(gp_regs, CTX_GPREG_X2, ret64); + + break; + + case MCE_CMD_WRITE_CSTATE_STATS: + ret = ops->write_cstate_stats(cpu_ari_base, arg0, arg1); + if (ret < 0) + ERROR("%s: write_cstate_stats failed(%d)\n", + __func__, ret); + + break; + + case MCE_CMD_IS_CCX_ALLOWED: + ret = ops->is_ccx_allowed(cpu_ari_base, arg0, arg1); + if (ret < 0) { + ERROR("%s: is_ccx_allowed failed(%d)\n", __func__, ret); + break; + } + + /* update context to return CCx status value */ + write_ctx_reg(gp_regs, CTX_GPREG_X1, ret); + + break; + + case MCE_CMD_IS_SC7_ALLOWED: + ret = ops->is_sc7_allowed(cpu_ari_base, arg0, arg1); + if (ret < 0) { + ERROR("%s: is_sc7_allowed failed(%d)\n", __func__, ret); + break; + } + + /* update context to return SC7 status value */ + write_ctx_reg(gp_regs, CTX_GPREG_X1, ret); + write_ctx_reg(gp_regs, CTX_GPREG_X3, ret); + ret = 0; + + break; + + case MCE_CMD_ONLINE_CORE: + ret = ops->online_core(cpu_ari_base, arg0); + if (ret < 0) + ERROR("%s: online_core failed(%d)\n", __func__, ret); + + break; + + case MCE_CMD_CC3_CTRL: + ret = ops->cc3_ctrl(cpu_ari_base, arg0, arg1, arg2); + if (ret < 0) + ERROR("%s: cc3_ctrl failed(%d)\n", __func__, ret); + + break; + + case MCE_CMD_ECHO_DATA: + ret64 = ops->call_enum_misc(cpu_ari_base, TEGRA_ARI_MISC_ECHO, + arg0); + + /* update context to return if echo'd data matched source */ + write_ctx_reg(gp_regs, CTX_GPREG_X1, ret64 == arg0); + write_ctx_reg(gp_regs, CTX_GPREG_X2, ret64 == arg0); + + break; + + case MCE_CMD_READ_VERSIONS: + ret64 = ops->call_enum_misc(cpu_ari_base, TEGRA_ARI_MISC_VERSION, + arg0); + + /* + * version = minor(63:32) | major(31:0). Update context + * to return major and minor version number. + */ + write_ctx_reg(gp_regs, CTX_GPREG_X1, (uint32_t)ret64); + write_ctx_reg(gp_regs, CTX_GPREG_X2, (uint32_t)(ret64 >> 32)); + + break; + + case MCE_CMD_ENUM_FEATURES: + ret = ops->call_enum_misc(cpu_ari_base, + TEGRA_ARI_MISC_FEATURE_LEAF_0, arg0); + + /* update context to return features value */ + write_ctx_reg(gp_regs, CTX_GPREG_X1, ret64); + + ret = 0; + + break; + + case MCE_CMD_ROC_FLUSH_CACHE_TRBITS: + ret = ops->roc_flush_cache_trbits(cpu_ari_base); + if (ret < 0) + ERROR("%s: flush cache_trbits failed(%d)\n", __func__, + ret); + + break; + + case MCE_CMD_ROC_FLUSH_CACHE: + ret = ops->roc_flush_cache(cpu_ari_base); + if (ret < 0) + ERROR("%s: flush cache failed(%d)\n", __func__, ret); + + break; + + case MCE_CMD_ROC_CLEAN_CACHE: + ret = ops->roc_clean_cache(cpu_ari_base); + if (ret < 0) + ERROR("%s: clean cache failed(%d)\n", __func__, ret); + + break; + + case MCE_CMD_ENUM_READ_MCA: + memcpy(&mca_cmd, &arg0, sizeof(arg0)); + ret64 = ops->read_write_mca(cpu_ari_base, mca_cmd, &arg1); + + /* update context to return MCA data/error */ + write_ctx_reg(gp_regs, CTX_GPREG_X1, ret64); + write_ctx_reg(gp_regs, CTX_GPREG_X2, arg1); + write_ctx_reg(gp_regs, CTX_GPREG_X3, ret64); + + break; + + case MCE_CMD_ENUM_WRITE_MCA: + memcpy(&mca_cmd, &arg0, sizeof(arg0)); + ret64 = ops->read_write_mca(cpu_ari_base, mca_cmd, &arg1); + + /* update context to return MCA error */ + write_ctx_reg(gp_regs, CTX_GPREG_X1, ret64); + write_ctx_reg(gp_regs, CTX_GPREG_X3, ret64); + + break; + + default: + ERROR("unknown MCE command (%d)\n", cmd); + return EINVAL; + } + + return ret; +} + +/******************************************************************************* + * Handler to update the reset vector for CPUs + ******************************************************************************/ +int mce_update_reset_vector(uint32_t addr_lo, uint32_t addr_hi) +{ + arch_mce_ops_t *ops = mce_get_curr_cpu_ops(); + + ops->update_reset_vector(mce_get_curr_cpu_ari_base(), addr_lo, addr_hi); + + return 0; +} + +static int mce_update_ccplex_gsc(tegra_ari_gsc_index_t gsc_idx) +{ + arch_mce_ops_t *ops = mce_get_curr_cpu_ops(); + + ops->update_ccplex_gsc(mce_get_curr_cpu_ari_base(), gsc_idx); + + return 0; +} + +/******************************************************************************* + * Handler to update carveout values for Video Memory Carveout region + ******************************************************************************/ +int mce_update_gsc_videomem(void) +{ + return mce_update_ccplex_gsc(TEGRA_ARI_GSC_VPR_IDX); +} + +/******************************************************************************* + * Handler to update carveout values for TZDRAM aperture + ******************************************************************************/ +int mce_update_gsc_tzdram(void) +{ + return mce_update_ccplex_gsc(TEGRA_ARI_GSC_TZ_DRAM_IDX); +} + +/******************************************************************************* + * Handler to update carveout values for TZ SysRAM aperture + ******************************************************************************/ +int mce_update_gsc_tzram(void) +{ + return mce_update_ccplex_gsc(TEGRA_ARI_GSC_TZRAM); +} + +/******************************************************************************* + * Handler to shutdown/reset the entire system + ******************************************************************************/ +__dead2 void mce_enter_ccplex_state(uint32_t state_idx) +{ + arch_mce_ops_t *ops = mce_get_curr_cpu_ops(); + + /* sanity check state value */ + if (state_idx != TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF && + state_idx != TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT) + panic(); + + ops->enter_ccplex_state(mce_get_curr_cpu_ari_base(), state_idx); + + /* wait till the CCPLEX powers down */ + for (;;) + ; + + panic(); +} diff --git a/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c b/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c new file mode 100644 index 000000000..25479a24b --- /dev/null +++ b/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +extern void nvg_set_request_data(uint64_t req, uint64_t data); +extern void nvg_set_request(uint64_t req); +extern uint64_t nvg_get_result(void); + +int nvg_enter_cstate(uint32_t ari_base, uint32_t state, uint32_t wake_time) +{ + /* check for allowed power state */ + if (state != TEGRA_ARI_CORE_C0 && state != TEGRA_ARI_CORE_C1 && + state != TEGRA_ARI_CORE_C6 && state != TEGRA_ARI_CORE_C7) { + ERROR("%s: unknown cstate (%d)\n", __func__, state); + return EINVAL; + } + + /* time (TSC ticks) until the core is expected to get a wake event */ + nvg_set_request_data(TEGRA_NVG_CHANNEL_WAKE_TIME, wake_time); + + /* set the core cstate */ + write_actlr_el1(state); + + return 0; +} + +/* + * This request allows updating of CLUSTER_CSTATE, CCPLEX_CSTATE and + * SYSTEM_CSTATE values. + */ +int nvg_update_cstate_info(uint32_t ari_base, uint32_t cluster, uint32_t ccplex, + uint32_t system, uint8_t sys_state_force, uint32_t wake_mask, + uint8_t update_wake_mask) +{ + uint64_t val = 0; + + /* update CLUSTER_CSTATE? */ + if (cluster) + val |= (cluster & CLUSTER_CSTATE_MASK) | + CLUSTER_CSTATE_UPDATE_BIT; + + /* update CCPLEX_CSTATE? */ + if (ccplex) + val |= (ccplex & CCPLEX_CSTATE_MASK) << CCPLEX_CSTATE_SHIFT | + CCPLEX_CSTATE_UPDATE_BIT; + + /* update SYSTEM_CSTATE? */ + if (system) + val |= ((system & SYSTEM_CSTATE_MASK) << SYSTEM_CSTATE_SHIFT) | + ((sys_state_force << SYSTEM_CSTATE_FORCE_UPDATE_SHIFT) | + SYSTEM_CSTATE_UPDATE_BIT); + + /* update wake mask value? */ + if (update_wake_mask) + val |= CSTATE_WAKE_MASK_UPDATE_BIT; + + /* set the wake mask */ + val &= CSTATE_WAKE_MASK_CLEAR; + val |= ((uint64_t)wake_mask << CSTATE_WAKE_MASK_SHIFT); + + /* set the updated cstate info */ + nvg_set_request_data(TEGRA_NVG_CHANNEL_CSTATE_INFO, val); + + return 0; +} + +int nvg_update_crossover_time(uint32_t ari_base, uint32_t type, uint32_t time) +{ + /* sanity check crossover type */ + if (type > TEGRA_ARI_CROSSOVER_CCP3_SC1) + return EINVAL; + + /* + * The crossover threshold limit types start from + * TEGRA_CROSSOVER_TYPE_C1_C6 to TEGRA_CROSSOVER_TYPE_CCP3_SC7. The + * command indices for updating the threshold can be generated + * by adding the type to the NVG_SET_THRESHOLD_CROSSOVER_C1_C6 + * command index. + */ + nvg_set_request_data(TEGRA_NVG_CHANNEL_CROSSOVER_C1_C6 + type, + (uint64_t)time); + + return 0; +} + +uint64_t nvg_read_cstate_stats(uint32_t ari_base, uint32_t state) +{ + /* sanity check state */ + if (state == 0) + return EINVAL; + + /* + * The cstate types start from NVG_READ_CSTATE_STATS_SC7_ENTRIES + * to NVG_GET_LAST_CSTATE_ENTRY_A57_3. The command indices for + * reading the threshold can be generated by adding the type to + * the NVG_CLEAR_CSTATE_STATS command index. + */ + nvg_set_request(TEGRA_NVG_CHANNEL_CSTATE_STATS_CLEAR + state); + + return (int64_t)nvg_get_result(); +} + +int nvg_write_cstate_stats(uint32_t ari_base, uint32_t state, uint32_t stats) +{ + uint64_t val; + + /* + * The only difference between a CSTATE_STATS_WRITE and + * CSTATE_STATS_READ is the usage of the 63:32 in the request. + * 63:32 are set to '0' for a read, while a write contains the + * actual stats value to be written. + */ + val = ((uint64_t)stats << MCE_CSTATE_STATS_TYPE_SHIFT) | state; + + /* + * The cstate types start from NVG_READ_CSTATE_STATS_SC7_ENTRIES + * to NVG_GET_LAST_CSTATE_ENTRY_A57_3. The command indices for + * reading the threshold can be generated by adding the type to + * the NVG_CLEAR_CSTATE_STATS command index. + */ + nvg_set_request_data(TEGRA_NVG_CHANNEL_CSTATE_STATS_CLEAR + state, val); + + return 0; +} + +int nvg_is_ccx_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time) +{ + /* This does not apply to the Denver cluster */ + return 0; +} + +int nvg_is_sc7_allowed(uint32_t ari_base, uint32_t state, uint32_t wake_time) +{ + uint64_t val; + + /* check for allowed power state */ + if (state != TEGRA_ARI_CORE_C0 && state != TEGRA_ARI_CORE_C1 && + state != TEGRA_ARI_CORE_C6 && state != TEGRA_ARI_CORE_C7) { + ERROR("%s: unknown cstate (%d)\n", __func__, state); + return EINVAL; + } + + /* + * Request format - + * 63:32 = wake time + * 31:0 = C-state for this core + */ + val = ((uint64_t)wake_time << MCE_SC7_WAKE_TIME_SHIFT) | + (state & MCE_SC7_ALLOWED_MASK); + + /* issue command to check if SC7 is allowed */ + nvg_set_request_data(TEGRA_NVG_CHANNEL_IS_SC7_ALLOWED, val); + + /* 1 = SC7 allowed, 0 = SC7 not allowed */ + return !!nvg_get_result(); +} + +int nvg_online_core(uint32_t ari_base, uint32_t core) +{ + int cpu = read_mpidr() & MPIDR_CPU_MASK; + int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; + + /* sanity check code id */ + if ((core >= MCE_CORE_ID_MAX) || (cpu == core)) { + ERROR("%s: unsupported core id (%d)\n", __func__, core); + return EINVAL; + } + + /* + * The Denver cluster has 2 CPUs only - 0, 1. + */ + if (impl == DENVER_IMPL && ((core == 2) || (core == 3))) { + ERROR("%s: unknown core id (%d)\n", __func__, core); + return EINVAL; + } + + /* get a core online */ + nvg_set_request_data(TEGRA_NVG_CHANNEL_ONLINE_CORE, core & MCE_CORE_ID_MASK); + + return 0; +} + +int nvg_cc3_ctrl(uint32_t ari_base, uint32_t freq, uint32_t volt, uint8_t enable) +{ + int val; + + /* + * If the enable bit is cleared, Auto-CC3 will be disabled by setting + * the SW visible voltage/frequency request registers for all non + * floorswept cores valid independent of StandbyWFI and disabling + * the IDLE voltage/frequency request register. If set, Auto-CC3 + * will be enabled by setting the ARM SW visible voltage/frequency + * request registers for all non floorswept cores to be enabled by + * StandbyWFI or the equivalent signal, and always keeping the IDLE + * voltage/frequency request register enabled. + */ + val = (((freq & MCE_AUTO_CC3_FREQ_MASK) << MCE_AUTO_CC3_FREQ_SHIFT) |\ + ((volt & MCE_AUTO_CC3_VTG_MASK) << MCE_AUTO_CC3_VTG_SHIFT) |\ + (enable ? MCE_AUTO_CC3_ENABLE_BIT : 0)); + + nvg_set_request_data(TEGRA_NVG_CHANNEL_CC3_CTRL, val); + + return 0; +} diff --git a/plat/nvidia/tegra/soc/t186/platform_t186.mk b/plat/nvidia/tegra/soc/t186/platform_t186.mk index 374b6e617..e29282a39 100644 --- a/plat/nvidia/tegra/soc/t186/platform_t186.mk +++ b/plat/nvidia/tegra/soc/t186/platform_t186.mk @@ -54,6 +54,10 @@ PLAT_INCLUDES += -I${SOC_DIR}/drivers/include BL31_SOURCES += lib/cpus/aarch64/denver.S \ lib/cpus/aarch64/cortex_a57.S \ ${COMMON_DIR}/drivers/memctrl/memctrl_v2.c \ + ${SOC_DIR}/drivers/mce/mce.c \ + ${SOC_DIR}/drivers/mce/ari.c \ + ${SOC_DIR}/drivers/mce/nvg.c \ + ${SOC_DIR}/drivers/mce/aarch64/nvg_helpers.S \ ${SOC_DIR}/plat_psci_handlers.c \ ${SOC_DIR}/plat_setup.c \ ${SOC_DIR}/plat_secondary.c \ From bb844c1f0dc3d9cd65fc43391ded6a3eb5975f46 Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Wed, 9 Sep 2015 11:33:08 +0530 Subject: [PATCH 05/26] Tegra186: SiP calls to interact with the MCE driver This patch adds the new SiP SMC calls to allow the NS world to interact with the MCE hardware block on Tegra186 chips. Change-Id: I79c6b9f76d68a87abd57a940613ec070562d2eac Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/soc/t186/plat_sip_calls.c | 107 ++++++++++---------- 1 file changed, 54 insertions(+), 53 deletions(-) diff --git a/plat/nvidia/tegra/soc/t186/plat_sip_calls.c b/plat/nvidia/tegra/soc/t186/plat_sip_calls.c index 496edf3cb..8c462f7f1 100644 --- a/plat/nvidia/tegra/soc/t186/plat_sip_calls.c +++ b/plat/nvidia/tegra/soc/t186/plat_sip_calls.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -35,80 +35,81 @@ #include #include #include -#include +#include #include +#include #include /******************************************************************************* * Tegra186 SiP SMCs ******************************************************************************/ #define TEGRA_SIP_NEW_VIDEOMEM_REGION 0x82000003 +#define TEGRA_SIP_MCE_CMD_ENTER_CSTATE 0x82FFFF00 +#define TEGRA_SIP_MCE_CMD_UPDATE_CSTATE_INFO 0x82FFFF01 +#define TEGRA_SIP_MCE_CMD_UPDATE_CROSSOVER_TIME 0x82FFFF02 +#define TEGRA_SIP_MCE_CMD_READ_CSTATE_STATS 0x82FFFF03 +#define TEGRA_SIP_MCE_CMD_WRITE_CSTATE_STATS 0x82FFFF04 +#define TEGRA_SIP_MCE_CMD_IS_SC7_ALLOWED 0x82FFFF05 +#define TEGRA_SIP_MCE_CMD_ONLINE_CORE 0x82FFFF06 +#define TEGRA_SIP_MCE_CMD_CC3_CTRL 0x82FFFF07 +#define TEGRA_SIP_MCE_CMD_ECHO_DATA 0x82FFFF08 +#define TEGRA_SIP_MCE_CMD_READ_VERSIONS 0x82FFFF09 +#define TEGRA_SIP_MCE_CMD_ENUM_FEATURES 0x82FFFF0A +#define TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE_TRBITS 0x82FFFF0B +#define TEGRA_SIP_MCE_CMD_ENUM_READ_MCA 0x82FFFF0C +#define TEGRA_SIP_MCE_CMD_ENUM_WRITE_MCA 0x82FFFF0D +#define TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE 0x82FFFF0E +#define TEGRA_SIP_MCE_CMD_ROC_CLEAN_CACHE 0x82FFFF0F /******************************************************************************* - * This function is responsible for handling all SiP calls from the NS world + * This function is responsible for handling all T186 SiP calls ******************************************************************************/ -uint64_t tegra186_sip_handler(uint32_t smc_fid, - uint64_t x1, - uint64_t x2, - uint64_t x3, - uint64_t x4, - void *cookie, - void *handle, - uint64_t flags) +int plat_sip_handler(uint32_t smc_fid, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + void *cookie, + void *handle, + uint64_t flags) { - uint32_t ns; - int err; - - /* Determine which security state this SMC originated from */ - ns = is_caller_non_secure(flags); - if (!ns) - SMC_RET1(handle, SMC_UNK); + int mce_ret; switch (smc_fid) { - case TEGRA_SIP_NEW_VIDEOMEM_REGION: + /* + * Micro Coded Engine (MCE) commands reside in the 0x82FFFF00 - + * 0x82FFFFFF SiP SMC space + */ + case TEGRA_SIP_MCE_CMD_ENTER_CSTATE: + case TEGRA_SIP_MCE_CMD_UPDATE_CSTATE_INFO: + case TEGRA_SIP_MCE_CMD_UPDATE_CROSSOVER_TIME: + case TEGRA_SIP_MCE_CMD_READ_CSTATE_STATS: + case TEGRA_SIP_MCE_CMD_WRITE_CSTATE_STATS: + case TEGRA_SIP_MCE_CMD_IS_SC7_ALLOWED: + case TEGRA_SIP_MCE_CMD_CC3_CTRL: + case TEGRA_SIP_MCE_CMD_ECHO_DATA: + case TEGRA_SIP_MCE_CMD_READ_VERSIONS: + case TEGRA_SIP_MCE_CMD_ENUM_FEATURES: + case TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE_TRBITS: + case TEGRA_SIP_MCE_CMD_ENUM_READ_MCA: + case TEGRA_SIP_MCE_CMD_ENUM_WRITE_MCA: + case TEGRA_SIP_MCE_CMD_ROC_FLUSH_CACHE: + case TEGRA_SIP_MCE_CMD_ROC_CLEAN_CACHE: /* clean up the high bits */ - x1 = (uint32_t)x1; - x2 = (uint32_t)x2; + smc_fid &= MCE_CMD_MASK; - /* - * Check if Video Memory overlaps TZDRAM (contains bl31/bl32) - * or falls outside of the valid DRAM range - */ - err = bl31_check_ns_address(x1, x2); - if (err) - SMC_RET1(handle, err); + /* 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, mce_ret); - /* - * Check if Video Memory is aligned to 1MB. - */ - if ((x1 & 0xFFFFF) || (x2 & 0xFFFFF)) { - ERROR("Unaligned Video Memory base address!\n"); - SMC_RET1(handle, -ENOTSUP); - } - - /* new video memory carveout settings */ - tegra_memctrl_videomem_setup(x1, x2); - - SMC_RET1(handle, 0); - break; + return 0; default: ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); break; } - SMC_RET1(handle, SMC_UNK); + return -ENOTSUP; } - -/* Define a runtime service descriptor for fast SMC calls */ -DECLARE_RT_SVC( - tegra186_sip_fast, - - OEN_SIP_START, - OEN_SIP_END, - SMC_TYPE_FAST, - NULL, - tegra186_sip_handler -); From b47d97b39588bd7b3b455980fd51acf6d316750c Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Mon, 14 Sep 2015 09:31:39 +0530 Subject: [PATCH 06/26] Tegra186: power on/off secondary CPUs This patch add code to power on/off the secondary CPUs on the Tegra186 chip. The MCE block is the actual hardware that takes care of the power on/off sequence. We pass the constructed CPU #, depending on the MIDR_IMPL field, to the MCE CPU handlers. This patch also programs the reset vector addresses to allow the CPUs to power on through the monitor and then jump to the linux world. Change-Id: Idc164586cda91c2009d66f3e09bf4464de9662db Signed-off-by: Varun Wadekar --- .../tegra/soc/t186/plat_psci_handlers.c | 48 +++++++++++++++++++ plat/nvidia/tegra/soc/t186/plat_secondary.c | 37 +++++++++++++- 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c index 012385483..35b7ee915 100644 --- a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c +++ b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c @@ -28,6 +28,10 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include +#include +#include +#include #include #include @@ -45,3 +49,47 @@ int32_t tegra_soc_validate_power_state(unsigned int power_state) return PSCI_E_SUCCESS; } + +int tegra_soc_prepare_cpu_on(unsigned long mpidr) +{ + int target_cpu = mpidr & MPIDR_CPU_MASK; + int target_cluster = (mpidr & MPIDR_CLUSTER_MASK) >> + MPIDR_AFFINITY_BITS; + + if (target_cluster > MPIDR_AFFLVL1) { + ERROR("%s: unsupported CPU (0x%lx)\n", __func__, mpidr); + return PSCI_E_NOT_PRESENT; + } + + /* construct the target CPU # */ + target_cpu |= (target_cluster << 2); + + mce_command_handler(MCE_CMD_ONLINE_CORE, target_cpu, 0, 0); + + return PSCI_E_SUCCESS; +} + +int tegra_soc_prepare_cpu_on_finish(unsigned long mpidr) +{ + /* + * Check if we are exiting from SOC_POWERDN. + */ + if (tegra_system_suspended()) { + + /* + * System resume complete. + */ + tegra_pm_system_suspend_exit(); + } + + return PSCI_E_SUCCESS; +} + +int tegra_soc_prepare_cpu_off(unsigned long mpidr) +{ + /* Turn off wake_mask */ + mce_command_handler(MCE_CMD_UPDATE_CSTATE_INFO, 0, 0, 1); + + /* Turn off CPU */ + return mce_command_handler(MCE_CMD_ENTER_CSTATE, ~0, 0, 0); +} diff --git a/plat/nvidia/tegra/soc/t186/plat_secondary.c b/plat/nvidia/tegra/soc/t186/plat_secondary.c index 85cc32c84..df802891a 100644 --- a/plat/nvidia/tegra/soc/t186/plat_secondary.c +++ b/plat/nvidia/tegra/soc/t186/plat_secondary.c @@ -28,10 +28,45 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include +#include +#include +#include + +#define MISCREG_CPU_RESET_VECTOR 0x2000 +#define MISCREG_AA64_RST_LOW 0x2004 +#define MISCREG_AA64_RST_HIGH 0x2008 + +#define SCRATCH_SECURE_RSV1_SCRATCH_0 0x658 +#define SCRATCH_SECURE_RSV1_SCRATCH_1 0x65C + +#define CPU_RESET_MODE_AA64 1 + +extern void tegra_secure_entrypoint(void); + /******************************************************************************* * Setup secondary CPU vectors ******************************************************************************/ void plat_secondary_setup(void) { - ; /* do nothing */ + uint32_t addr_low, addr_high; + uint64_t reset_addr = (uint64_t)tegra_secure_entrypoint; + + INFO("Setting up secondary CPU boot\n"); + + addr_low = (uint32_t)reset_addr | CPU_RESET_MODE_AA64; + addr_high = (uint32_t)((reset_addr >> 32) & 0x7ff); + + /* 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, + addr_low); + mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_SECURE_RSV1_SCRATCH_1, + addr_high); + + /* update reset vector address to the CCPLEX */ + mce_update_reset_vector(addr_low, addr_high); } From c7ec0892b113b7ef90807905025521e11d4b26b3 Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Tue, 14 Mar 2017 14:25:35 -0700 Subject: [PATCH 07/26] Tegra186: implement prepare_system_off handler This patch issues the 'System Off' ARI to power off the entire system from the 'prepare_system_off' handler. Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/soc/t186/plat_psci_handlers.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c index 35b7ee915..42f6d89b9 100644 --- a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c +++ b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c @@ -33,6 +33,7 @@ #include #include #include +#include #include int32_t tegra_soc_validate_power_state(unsigned int power_state) @@ -93,3 +94,8 @@ int tegra_soc_prepare_cpu_off(unsigned long mpidr) /* Turn off CPU */ return mce_command_handler(MCE_CMD_ENTER_CSTATE, ~0, 0, 0); } + +__dead2 void tegra_soc_prepare_system_off(void) +{ + mce_enter_ccplex_state(TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF); +} From b5ef956927cf9c3d67af5750e8b51905e4656bd5 Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Mon, 30 Nov 2015 12:05:04 -0800 Subject: [PATCH 08/26] Tegra186: relocate bl31.bin to the SYSRAM Tegra186 has an on-die, 320KB, "System RAM" memory. Out of the total size, 256KB are allocated for the CPU TrustZone binaries - EL3 monitor and Trusted OS. This patch changes the base address for bl31.bin to the SysRAM base address. The carveout is too small for the Trusted OS, so we relocate only the monitor binary. Change-Id: Ib4b667ff2a7a619589851338f9d0bfb02078c575 Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/soc/t186/platform_t186.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plat/nvidia/tegra/soc/t186/platform_t186.mk b/plat/nvidia/tegra/soc/t186/platform_t186.mk index e29282a39..5e55d9d0c 100644 --- a/plat/nvidia/tegra/soc/t186/platform_t186.mk +++ b/plat/nvidia/tegra/soc/t186/platform_t186.mk @@ -33,7 +33,7 @@ ENABLE_NS_L2_CPUECTRL_RW_ACCESS := 1 $(eval $(call add_define,ENABLE_NS_L2_CPUECTRL_RW_ACCESS)) # platform settings -TZDRAM_BASE := 0xEA800000 +TZDRAM_BASE := 0x30000000 $(eval $(call add_define,TZDRAM_BASE)) PLATFORM_CLUSTER_COUNT := 2 From 5d74d68e52659b5f4eba5bb8a35d96979f19e0c9 Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Mon, 4 Jan 2016 10:57:45 -0800 Subject: [PATCH 09/26] Tegra186: update SYSCNT_FREQ to 31.25MHz The System Counter Frequency has been updated to 31.25MHz after some experiments as the previous value was too high. Change-Id: I79986ee1c0c88700a3a2b1dbff2d3f00c0c412b9 Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/soc/t186/plat_setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plat/nvidia/tegra/soc/t186/plat_setup.c b/plat/nvidia/tegra/soc/t186/plat_setup.c index 99329e3ac..f88478d8b 100644 --- a/plat/nvidia/tegra/soc/t186/plat_setup.c +++ b/plat/nvidia/tegra/soc/t186/plat_setup.c @@ -69,7 +69,7 @@ const mmap_region_t *plat_get_mmio_map(void) ******************************************************************************/ unsigned int plat_get_syscnt_freq2(void) { - return 38400000; + return 31250000; } /******************************************************************************* From 348619f2874cd4e7d4ea09a3aa238cb722bf0e0b Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Tue, 5 Jan 2016 15:17:41 -0800 Subject: [PATCH 10/26] Tegra186: implement CPU_OFF handler This patch implements the CPU_OFF handler for powering down a CPU using the MCE driver. Change-Id: I8d455005d0b547cc61cc7778bfe9eb84b7e5480c Signed-off-by: Varun Wadekar --- .../tegra/soc/t186/plat_psci_handlers.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c index 42f6d89b9..02119d359 100644 --- a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c +++ b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c @@ -30,6 +30,10 @@ #include #include +#include +#include +#include +#include #include #include #include @@ -88,11 +92,22 @@ int tegra_soc_prepare_cpu_on_finish(unsigned long mpidr) int tegra_soc_prepare_cpu_off(unsigned long mpidr) { + cpu_context_t *ctx = cm_get_context(NON_SECURE); + gp_regs_t *gp_regs = get_gpregs_ctx(ctx); + + assert(ctx); + assert(gp_regs); + /* Turn off wake_mask */ - mce_command_handler(MCE_CMD_UPDATE_CSTATE_INFO, 0, 0, 1); + write_ctx_reg(gp_regs, CTX_GPREG_X4, 0); + write_ctx_reg(gp_regs, CTX_GPREG_X5, 0); + write_ctx_reg(gp_regs, CTX_GPREG_X6, 1); + mce_command_handler(MCE_CMD_UPDATE_CSTATE_INFO, TEGRA_ARI_CLUSTER_CC7, + 0, TEGRA_ARI_SYSTEM_SC7); /* Turn off CPU */ - return mce_command_handler(MCE_CMD_ENTER_CSTATE, ~0, 0, 0); + return mce_command_handler(MCE_CMD_ENTER_CSTATE, TEGRA_ARI_CORE_C7, + ~0, 0); } __dead2 void tegra_soc_prepare_system_off(void) From b6ea86b1c3d79d37dac213ed6d6d0469e68c4b7f Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Thu, 7 Jan 2016 14:36:12 -0800 Subject: [PATCH 11/26] Tegra186: implement prepare_system_reset handler This patch implements the 'prepare_system_reset' handler to issue the 'system reset' command to the MCE. Change-Id: I83d8d0b4167aac5963d640fe77d5754dc7ef05b1 Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/soc/t186/plat_psci_handlers.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c index 02119d359..d1e469dea 100644 --- a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c +++ b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c @@ -114,3 +114,10 @@ __dead2 void tegra_soc_prepare_system_off(void) { mce_enter_ccplex_state(TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF); } + +int tegra_soc_prepare_system_reset(void) +{ + mce_enter_ccplex_state(TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_REBOOT); + + return PSCI_E_SUCCESS; +} From b67a7c7c47e1272f1dc0d904feddd10f0110bb36 Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Fri, 8 Jan 2016 17:38:51 -0800 Subject: [PATCH 12/26] Tegra186: support for the latest platform port handlers This patch adds support for the newer platform handler functions. Commit I6db74b020b141048b6b8c03e1bef7ed8f72fd75b merges the upstream code which has already moved all the upstream supported platforms over to these handler functions. Change-Id: I621eff038f3c0dc1b90793edcd4dd7c71b196045 Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/include/t186/tegra_def.h | 4 +-- .../tegra/soc/t186/plat_psci_handlers.c | 32 +++++++------------ plat/nvidia/tegra/soc/t186/plat_setup.c | 17 ++++++++++ 3 files changed, 30 insertions(+), 23 deletions(-) diff --git a/plat/nvidia/tegra/include/t186/tegra_def.h b/plat/nvidia/tegra/include/t186/tegra_def.h index 10fea1158..16615a853 100644 --- a/plat/nvidia/tegra/include/t186/tegra_def.h +++ b/plat/nvidia/tegra/include/t186/tegra_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -37,7 +37,7 @@ * This value is used by the PSCI implementation during the `SYSTEM_SUSPEND` * call as the `state-id` field in the 'power state' parameter. ******************************************************************************/ -#define PLAT_SYS_SUSPEND_STATE_ID 0 +#define PSTATE_ID_SOC_POWERDN 1 /******************************************************************************* * Implementation defined ACTLR_EL3 bit definitions diff --git a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c index d1e469dea..aa4291a65 100644 --- a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c +++ b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -40,22 +40,28 @@ #include #include -int32_t tegra_soc_validate_power_state(unsigned int power_state) +int32_t tegra_soc_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) { + int pwr_lvl = psci_get_pstate_pwrlvl(power_state); + /* Sanity check the requested afflvl */ if (psci_get_pstate_type(power_state) == PSTATE_TYPE_STANDBY) { /* * It's possible to enter standby only on affinity level 0 i.e. * a cpu on Tegra. Ignore any other affinity level. */ - if (psci_get_pstate_afflvl(power_state) != MPIDR_AFFLVL0) + if (pwr_lvl != MPIDR_AFFLVL0) return PSCI_E_INVALID_PARAMS; + + /* power domain in standby state */ + req_state->pwr_domain_state[pwr_lvl] = PLAT_MAX_RET_STATE; } return PSCI_E_SUCCESS; } -int tegra_soc_prepare_cpu_on(unsigned long mpidr) +int tegra_soc_pwr_domain_on(u_register_t mpidr) { int target_cpu = mpidr & MPIDR_CPU_MASK; int target_cluster = (mpidr & MPIDR_CLUSTER_MASK) >> @@ -74,23 +80,7 @@ int tegra_soc_prepare_cpu_on(unsigned long mpidr) return PSCI_E_SUCCESS; } -int tegra_soc_prepare_cpu_on_finish(unsigned long mpidr) -{ - /* - * Check if we are exiting from SOC_POWERDN. - */ - if (tegra_system_suspended()) { - - /* - * System resume complete. - */ - tegra_pm_system_suspend_exit(); - } - - return PSCI_E_SUCCESS; -} - -int tegra_soc_prepare_cpu_off(unsigned long mpidr) +int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state) { cpu_context_t *ctx = cm_get_context(NON_SECURE); gp_regs_t *gp_regs = get_gpregs_ctx(ctx); diff --git a/plat/nvidia/tegra/soc/t186/plat_setup.c b/plat/nvidia/tegra/soc/t186/plat_setup.c index f88478d8b..626035119 100644 --- a/plat/nvidia/tegra/soc/t186/plat_setup.c +++ b/plat/nvidia/tegra/soc/t186/plat_setup.c @@ -32,6 +32,23 @@ #include #include +/******************************************************************************* + * The Tegra power domain tree has a single system level power domain i.e. a + * single root node. The first entry in the power domain descriptor specifies + * the number of power domains at the highest power level. + ******************************************************************************* + */ +const unsigned char tegra_power_domain_tree_desc[] = { + /* No of root nodes */ + 1, + /* No of clusters */ + PLATFORM_CLUSTER_COUNT, + /* No of CPU cores - cluster0 */ + PLATFORM_MAX_CPUS_PER_CLUSTER, + /* No of CPU cores - cluster1 */ + PLATFORM_MAX_CPUS_PER_CLUSTER +}; + /* * Table of regions to map using the MMU. */ From d48c0c45de29e41bd5d464c75033f1077badea5f Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Wed, 30 Dec 2015 15:15:08 -0800 Subject: [PATCH 13/26] Tegra: memctrl_v2: secure the on-chip TZSRAM memory This patch programs the Memory controller's control registers to disable non-secure accesses to the TZRAM. In case these registers are already programmed by the BL2/BL30, then the driver just bails out. Change-Id: Ia1416988050e3d067296373060c717a260499122 Signed-off-by: Varun Wadekar --- .../tegra/common/drivers/memctrl/memctrl_v2.c | 45 ++++++++++++++++++- .../nvidia/tegra/include/drivers/memctrl_v2.h | 13 +++++- plat/nvidia/tegra/include/t186/tegra_def.h | 6 +++ 3 files changed, 62 insertions(+), 2 deletions(-) diff --git a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c index c82ddd422..a674b5994 100644 --- a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c +++ b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -283,6 +283,49 @@ void tegra_memctrl_tzdram_setup(uint64_t phys_base, uint32_t size_in_bytes) mce_update_gsc_tzdram(); } +/* + * Secure the BL31 TZRAM aperture. + * + * phys_base = physical base of TZRAM aperture + * size_in_bytes = size of aperture in bytes + */ +void tegra_memctrl_tzram_setup(uint64_t phys_base, uint32_t size_in_bytes) +{ + uint64_t tzram_end = phys_base + size_in_bytes - 1; + uint32_t val; + + /* + * Check if the TZRAM is locked already. + */ + if (tegra_mc_read_32(MC_TZRAM_REG_CTRL) == DISABLE_TZRAM_ACCESS) + return; + + /* + * Setup the Memory controller to allow only secure accesses to + * the TZRAM carveout + */ + INFO("Configuring TrustZone RAM (SysRAM) Memory Carveout\n"); + + /* Program the base and end values */ + tegra_mc_write_32(MC_TZRAM_BASE, (uint32_t)phys_base); + tegra_mc_write_32(MC_TZRAM_END, (uint32_t)tzram_end); + + /* Extract the high address bits from the base/end values */ + val = (uint32_t)(phys_base >> 32) & TZRAM_ADDR_HI_BITS_MASK; + val |= (((uint32_t)(tzram_end >> 32) << TZRAM_END_HI_BITS_SHIFT) & + TZRAM_ADDR_HI_BITS_MASK); + tegra_mc_write_32(MC_TZRAM_HI_ADDR_BITS, val); + + /* Disable further writes to the TZRAM setup registers */ + tegra_mc_write_32(MC_TZRAM_REG_CTRL, DISABLE_TZRAM_ACCESS); + + /* + * MCE propogates the security configuration values across the + * CCPLEX. + */ + mce_update_gsc_tzram(); +} + /* * Program the Video Memory carveout region * diff --git a/plat/nvidia/tegra/include/drivers/memctrl_v2.h b/plat/nvidia/tegra/include/drivers/memctrl_v2.h index 1d5ba0e99..0736b592d 100644 --- a/plat/nvidia/tegra/include/drivers/memctrl_v2.h +++ b/plat/nvidia/tegra/include/drivers/memctrl_v2.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -264,6 +264,17 @@ typedef struct mc_streamid_security_cfg { #define MC_VIDEO_PROTECT_BASE_LO 0x648 #define MC_VIDEO_PROTECT_SIZE_MB 0x64c +/******************************************************************************* + * TZRAM carveout configuration registers + ******************************************************************************/ +#define MC_TZRAM_BASE 0x1850 +#define MC_TZRAM_END 0x1854 +#define MC_TZRAM_HI_ADDR_BITS 0x1588 + #define TZRAM_ADDR_HI_BITS_MASK 0x3 + #define TZRAM_END_HI_BITS_SHIFT 8 +#define MC_TZRAM_REG_CTRL 0x185c + #define DISABLE_TZRAM_ACCESS 1 + static inline uint32_t tegra_mc_read_32(uint32_t off) { return mmio_read_32(TEGRA_MC_BASE + off); diff --git a/plat/nvidia/tegra/include/t186/tegra_def.h b/plat/nvidia/tegra/include/t186/tegra_def.h index 16615a853..bd2c5db9b 100644 --- a/plat/nvidia/tegra/include/t186/tegra_def.h +++ b/plat/nvidia/tegra/include/t186/tegra_def.h @@ -111,4 +111,10 @@ ******************************************************************************/ #define TEGRA_SMMU_BASE 0x12000000 +/******************************************************************************* + * Tegra TZRAM constants + ******************************************************************************/ +#define TEGRA_TZRAM_BASE 0x30000000 +#define TEGRA_TZRAM_SIZE 0x50000 + #endif /* __TEGRA_DEF_H__ */ From 7afd46375318bc912f6bb41362685371a003bb11 Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Mon, 18 Jan 2016 19:03:19 -0800 Subject: [PATCH 14/26] Tegra186: support for C6/C7 CPU_SUSPEND states This patch adds support for the C6 and C7 CPU_SUSPEND states. C6 is an idle state while C7 is a powerdown state. The MCE block takes care of the entry/exit to/from these core power states and hence we call the corresponding MCE handler to process these requests. The NS driver passes the tentative time that the core is expected to stay in this state as part of the power_state parameter, which we store in a per-cpu array and pass it to the MCE block. Change-Id: I152acb11ab93d91fb866da2129b1795843dfa39b Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/include/t186/tegra_def.h | 18 ++++- .../t186/drivers/mce/aarch64/nvg_helpers.S | 1 - .../tegra/soc/t186/plat_psci_handlers.c | 66 ++++++++++++++++--- 3 files changed, 72 insertions(+), 13 deletions(-) diff --git a/plat/nvidia/tegra/include/t186/tegra_def.h b/plat/nvidia/tegra/include/t186/tegra_def.h index bd2c5db9b..3983a6b03 100644 --- a/plat/nvidia/tegra/include/t186/tegra_def.h +++ b/plat/nvidia/tegra/include/t186/tegra_def.h @@ -34,10 +34,22 @@ #include /******************************************************************************* - * This value is used by the PSCI implementation during the `SYSTEM_SUSPEND` - * call as the `state-id` field in the 'power state' parameter. + * These values are used by the PSCI implementation during the `CPU_SUSPEND` + * and `SYSTEM_SUSPEND` calls as the `state-id` field in the 'power state' + * parameter. ******************************************************************************/ -#define PSTATE_ID_SOC_POWERDN 1 +#define PSTATE_ID_CORE_IDLE 6 +#define PSTATE_ID_CORE_POWERDN 7 +#define PSTATE_ID_SOC_POWERDN 2 + +/******************************************************************************* + * Platform power states (used by PSCI framework) + * + * - PLAT_MAX_RET_STATE should be less than lowest PSTATE_ID + * - PLAT_MAX_OFF_STATE should be greater than the highest PSTATE_ID + ******************************************************************************/ +#define PLAT_MAX_RET_STATE 1 +#define PLAT_MAX_OFF_STATE 8 /******************************************************************************* * Implementation defined ACTLR_EL3 bit definitions diff --git a/plat/nvidia/tegra/soc/t186/drivers/mce/aarch64/nvg_helpers.S b/plat/nvidia/tegra/soc/t186/drivers/mce/aarch64/nvg_helpers.S index e1398ccee..b6e4b31ab 100644 --- a/plat/nvidia/tegra/soc/t186/drivers/mce/aarch64/nvg_helpers.S +++ b/plat/nvidia/tegra/soc/t186/drivers/mce/aarch64/nvg_helpers.S @@ -39,7 +39,6 @@ func nvg_set_request_data msr s3_0_c15_c1_2, x0 msr s3_0_c15_c1_3, x1 - isb ret endfunc nvg_set_request_data diff --git a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c index aa4291a65..413e3f820 100644 --- a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c +++ b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c @@ -40,22 +40,70 @@ #include #include +/* state id mask */ +#define TEGRA186_STATE_ID_MASK 0xF +/* constants to get power state's wake time */ +#define TEGRA186_WAKE_TIME_MASK 0xFFFFFF +#define TEGRA186_WAKE_TIME_SHIFT 4 + +/* per cpu wake time value */ +static unsigned int wake_time[PLATFORM_CORE_COUNT]; + int32_t tegra_soc_validate_power_state(unsigned int power_state, psci_power_state_t *req_state) { - int pwr_lvl = psci_get_pstate_pwrlvl(power_state); + int state_id = psci_get_pstate_id(power_state) & TEGRA186_STATE_ID_MASK; + int cpu = read_mpidr() & MPIDR_CPU_MASK; - /* Sanity check the requested afflvl */ - if (psci_get_pstate_type(power_state) == PSTATE_TYPE_STANDBY) { + /* get the wake time value */ + wake_time[cpu] = (power_state & TEGRA186_WAKE_TIME_MASK) >> + TEGRA186_WAKE_TIME_SHIFT; + + /* Sanity check the requested state id */ + switch (state_id) { + case PSTATE_ID_CORE_IDLE: + case PSTATE_ID_CORE_POWERDN: /* - * It's possible to enter standby only on affinity level 0 i.e. - * a cpu on Tegra. Ignore any other affinity level. + * Core powerdown request only for afflvl 0 */ - if (pwr_lvl != MPIDR_AFFLVL0) - return PSCI_E_INVALID_PARAMS; + req_state->pwr_domain_state[MPIDR_AFFLVL0] = state_id; - /* power domain in standby state */ - req_state->pwr_domain_state[pwr_lvl] = PLAT_MAX_RET_STATE; + break; + + default: + ERROR("%s: unsupported state id (%d)\n", __func__, state_id); + return PSCI_E_INVALID_PARAMS; + } + + return PSCI_E_SUCCESS; +} + +int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + const plat_local_state_t *pwr_domain_state; + unsigned int stateid_afflvl0; + int cpu = read_mpidr() & MPIDR_CPU_MASK; + + /* get the state ID */ + pwr_domain_state = target_state->pwr_domain_state; + stateid_afflvl0 = pwr_domain_state[MPIDR_AFFLVL0] & + TEGRA186_STATE_ID_MASK; + + if (stateid_afflvl0 == PSTATE_ID_CORE_IDLE) { + + /* Prepare for cpu idle */ + (void)mce_command_handler(MCE_CMD_ENTER_CSTATE, + TEGRA_ARI_CORE_C6, wake_time[cpu], 0); + + } else if (stateid_afflvl0 == PSTATE_ID_CORE_POWERDN) { + + /* Prepare for cpu powerdn */ + (void)mce_command_handler(MCE_CMD_ENTER_CSTATE, + TEGRA_ARI_CORE_C7, wake_time[cpu], 0); + + } else { + ERROR("%s: Unknown state id\n", __func__); + return PSCI_E_NOT_SUPPORTED; } return PSCI_E_SUCCESS; From 7dd5af0a09dc546e43f775b52150ded8383078c8 Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Wed, 3 Feb 2016 09:51:25 -0800 Subject: [PATCH 15/26] Tegra186: add Video memory carveout settings This patch supports the TEGRA_SIP_NEW_VIDEOMEM_REGION SiP call to program new video memory carveout settings from the NS world. Change-Id: If9ed818fe71e6cb7461f225090105a4d8883b7a2 Signed-off-by: Wayne Lin Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/soc/t186/plat_sip_calls.c | 27 +++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/plat/nvidia/tegra/soc/t186/plat_sip_calls.c b/plat/nvidia/tegra/soc/t186/plat_sip_calls.c index 8c462f7f1..66a433e94 100644 --- a/plat/nvidia/tegra/soc/t186/plat_sip_calls.c +++ b/plat/nvidia/tegra/soc/t186/plat_sip_calls.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -106,6 +107,32 @@ int plat_sip_handler(uint32_t smc_fid, return 0; + case TEGRA_SIP_NEW_VIDEOMEM_REGION: + /* clean up the high bits */ + x1 = (uint32_t)x1; + x2 = (uint32_t)x2; + + /* + * Check if Video Memory overlaps TZDRAM (contains bl31/bl32) + * or falls outside of the valid DRAM range + */ + mce_ret = bl31_check_ns_address(x1, x2); + if (mce_ret) + return -ENOTSUP; + + /* + * Check if Video Memory is aligned to 1MB. + */ + if ((x1 & 0xFFFFF) || (x2 & 0xFFFFF)) { + ERROR("Unaligned Video Memory base address!\n"); + return -ENOTSUP; + } + + /* new video memory carveout settings */ + tegra_memctrl_videomem_setup(x1, x2); + + return 0; + default: ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); break; From aa1bdc960c2280895d90e3af9b915e596300a340 Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Tue, 9 Feb 2016 14:55:44 -0800 Subject: [PATCH 16/26] Tegra186: fix per-cpu wake times for CPU power states This patch fixes the logic used to calculate the CPU index for storing the per-cpu wake times. We use the MIDR register to calculate the CPU index now. This allows us to store values for Denver/A57 CPUs properly. Change-Id: I9df0377afd4b92bbdaea495c0df06a9780a99d09 Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/soc/t186/plat_psci_handlers.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c index 413e3f820..e91d82fbc 100644 --- a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c +++ b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -46,7 +47,6 @@ #define TEGRA186_WAKE_TIME_MASK 0xFFFFFF #define TEGRA186_WAKE_TIME_SHIFT 4 -/* per cpu wake time value */ static unsigned int wake_time[PLATFORM_CORE_COUNT]; int32_t tegra_soc_validate_power_state(unsigned int power_state, @@ -54,10 +54,13 @@ int32_t tegra_soc_validate_power_state(unsigned int power_state, { int state_id = psci_get_pstate_id(power_state) & TEGRA186_STATE_ID_MASK; int cpu = read_mpidr() & MPIDR_CPU_MASK; + int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; - /* get the wake time value */ - wake_time[cpu] = (power_state & TEGRA186_WAKE_TIME_MASK) >> - TEGRA186_WAKE_TIME_SHIFT; + if (impl == DENVER_IMPL) + cpu |= 0x4; + + wake_time[cpu] = (power_state >> TEGRA186_WAKE_TIME_SHIFT) & + TEGRA186_WAKE_TIME_MASK; /* Sanity check the requested state id */ switch (state_id) { @@ -83,6 +86,10 @@ int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state) const plat_local_state_t *pwr_domain_state; unsigned int stateid_afflvl0; int cpu = read_mpidr() & MPIDR_CPU_MASK; + int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; + + if (impl == DENVER_IMPL) + cpu |= 0x4; /* get the state ID */ pwr_domain_state = target_state->pwr_domain_state; @@ -145,7 +152,7 @@ int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state) /* Turn off CPU */ return mce_command_handler(MCE_CMD_ENTER_CSTATE, TEGRA_ARI_CORE_C7, - ~0, 0); + MCE_CORE_SLEEP_TIME_INFINITE, 0); } __dead2 void tegra_soc_prepare_system_off(void) From 8020793fe0c660aa4601a66553636db39c8c2f4f Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Wed, 17 Feb 2016 10:01:28 -0800 Subject: [PATCH 17/26] Tegra: memctrl_v2: no SID override for SCE block This patch fixes the incorrect override settings for the SCE hardware block. Original change by Pekka Pessi Change-Id: I33db55d6004331988b52ca70157aab1409f4829f Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c index a674b5994..97ae3b261 100644 --- a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c +++ b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c @@ -122,7 +122,7 @@ const static uint32_t streamid_overrides[] = { /* array to hold the security configs for stream IDs */ const static mc_streamid_security_cfg_t sec_cfgs[] = { - mc_make_sec_cfg(SCEW, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(SCEW, NON_SECURE, NO_OVERRIDE, ENABLE), mc_make_sec_cfg(AFIR, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(NVDISPLAYR1, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(XUSB_DEVR, NON_SECURE, OVERRIDE, ENABLE), @@ -137,7 +137,7 @@ const static mc_streamid_security_cfg_t sec_cfgs[] = { mc_make_sec_cfg(UFSHCW, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(AFIW, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(SDMMCR, NON_SECURE, OVERRIDE, ENABLE), - mc_make_sec_cfg(SCEDMAW, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(SCEDMAW, NON_SECURE, NO_OVERRIDE, ENABLE), mc_make_sec_cfg(UFSHCR, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(SDMMCWAA, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(APEDMAW, NON_SECURE, OVERRIDE, ENABLE), @@ -148,7 +148,7 @@ const static mc_streamid_security_cfg_t sec_cfgs[] = { mc_make_sec_cfg(ETRW, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(GPUSRD, SECURE, NO_OVERRIDE, DISABLE), mc_make_sec_cfg(VICSWR, NON_SECURE, NO_OVERRIDE, ENABLE), - mc_make_sec_cfg(SCEDMAR, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(SCEDMAR, NON_SECURE, NO_OVERRIDE, ENABLE), mc_make_sec_cfg(HDAW, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(ISPWA, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(EQOSW, NON_SECURE, OVERRIDE, ENABLE), @@ -173,7 +173,7 @@ const static mc_streamid_security_cfg_t sec_cfgs[] = { mc_make_sec_cfg(TSECSRD, NON_SECURE, NO_OVERRIDE, ENABLE), mc_make_sec_cfg(NVJPGSRD, NON_SECURE, NO_OVERRIDE, ENABLE), mc_make_sec_cfg(SDMMCWA, NON_SECURE, OVERRIDE, ENABLE), - mc_make_sec_cfg(SCER, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(SCER, NON_SECURE, NO_OVERRIDE, ENABLE), mc_make_sec_cfg(XUSB_HOSTR, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(VICSRD, NON_SECURE, NO_OVERRIDE, ENABLE), mc_make_sec_cfg(AONDMAR, NON_SECURE, OVERRIDE, ENABLE), From 67bc721b2bc321e07b1ea50c53dd35915dc2a949 Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Wed, 17 Feb 2016 10:10:50 -0800 Subject: [PATCH 18/26] Tegra: memctrl_v2: check GPU state before VPR programming The GPU is the real consumer of the video protected memory region and it needs to be in reset to pick up the new region. This patch checks if the GPU is in reset before we program the new video protected memory region settings. Change-Id: I44f553bfcf07b1975abad53b245954be966c8aeb Signed-off-by: Varun Wadekar --- .../tegra/common/drivers/memctrl/memctrl_v2.c | 16 ++++++++++++++++ plat/nvidia/tegra/soc/t186/plat_setup.c | 2 ++ plat/nvidia/tegra/soc/t186/platform_t186.mk | 4 ++-- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c index 97ae3b261..27c878971 100644 --- a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c +++ b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c @@ -39,6 +39,9 @@ #include #include +#define TEGRA_GPU_RESET_REG_OFFSET 0x30 +#define GPU_RESET_BIT (1 << 0) + /* Video Memory base and size (live values) */ static uint64_t video_mem_base; static uint64_t video_mem_size; @@ -334,6 +337,19 @@ 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) { + uint32_t regval; + + /* + * The GPU is the user of the Video Memory region. In order to + * transition to the new memory region smoothly, we program the + * new base/size ONLY if the GPU is in reset mode. + */ + regval = mmio_read_32(TEGRA_CAR_RESET_BASE + TEGRA_GPU_RESET_REG_OFFSET); + if ((regval & GPU_RESET_BIT) == 0) { + ERROR("GPU not in reset! Video Memory setup failed\n"); + return; + } + /* * Setup the Memory controller to restrict CPU accesses to the Video * Memory region diff --git a/plat/nvidia/tegra/soc/t186/plat_setup.c b/plat/nvidia/tegra/soc/t186/plat_setup.c index 626035119..0496f5a5e 100644 --- a/plat/nvidia/tegra/soc/t186/plat_setup.c +++ b/plat/nvidia/tegra/soc/t186/plat_setup.c @@ -63,6 +63,8 @@ static const mmap_region_t tegra_mmap[] = { MT_DEVICE | MT_RW | MT_SECURE), MAP_REGION_FLAT(TEGRA_GICD_BASE, 0x20000, /* 128KB */ MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_CAR_RESET_BASE, 0x10000, /* 64KB */ + MT_DEVICE | MT_RW | MT_SECURE), MAP_REGION_FLAT(TEGRA_PMC_BASE, 0x40000, /* 256KB */ MT_DEVICE | MT_RW | MT_SECURE), MAP_REGION_FLAT(TEGRA_MMCRAB_BASE, 0x60000, /* 384KB */ diff --git a/plat/nvidia/tegra/soc/t186/platform_t186.mk b/plat/nvidia/tegra/soc/t186/platform_t186.mk index 5e55d9d0c..777f2db21 100644 --- a/plat/nvidia/tegra/soc/t186/platform_t186.mk +++ b/plat/nvidia/tegra/soc/t186/platform_t186.mk @@ -42,10 +42,10 @@ $(eval $(call add_define,PLATFORM_CLUSTER_COUNT)) PLATFORM_MAX_CPUS_PER_CLUSTER := 4 $(eval $(call add_define,PLATFORM_MAX_CPUS_PER_CLUSTER)) -MAX_XLAT_TABLES := 10 +MAX_XLAT_TABLES := 12 $(eval $(call add_define,MAX_XLAT_TABLES)) -MAX_MMAP_REGIONS := 10 +MAX_MMAP_REGIONS := 12 $(eval $(call add_define,MAX_MMAP_REGIONS)) # platform files From be87d920bfd8c70dc3c96dc726f1686bd3430cc0 Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Wed, 17 Feb 2016 15:07:49 -0800 Subject: [PATCH 19/26] Tegra: memctrl_v2: implement MC txn override WAR This patch sets the Memory Controller's TXN_OVERRIDE registers for most write clients to CGID_ADR. This ensures ordering is maintained. In some cases WAW ordering problems could occur. There are different settings for Tegra version A01 v A02. Original changes by Alex Waterman Change-Id: I82ea02afa43a24250ed56985757b83e78e71178c Signed-off-by: Varun Wadekar --- .../tegra/common/drivers/memctrl/memctrl_v2.c | 72 +++++++++++++ .../nvidia/tegra/include/drivers/memctrl_v2.h | 101 ++++++++++++++++++ plat/nvidia/tegra/include/t186/tegra_def.h | 4 + 3 files changed, 177 insertions(+) diff --git a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c index 27c878971..bc2d7b595 100644 --- a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c +++ b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c @@ -199,6 +199,40 @@ const static mc_streamid_security_cfg_t sec_cfgs[] = { mc_make_sec_cfg(GPUSRD2, SECURE, NO_OVERRIDE, DISABLE), }; +const static mc_txn_override_cfg_t mc_override_cfgs[] = { + mc_make_txn_override_cfg(BPMPW, CGID_TAG_ADR), + mc_make_txn_override_cfg(EQOSW, CGID_TAG_ADR), + mc_make_txn_override_cfg(NVJPGSWR, CGID_TAG_ADR), + mc_make_txn_override_cfg(SDMMCWAA, CGID_TAG_ADR), + mc_make_txn_override_cfg(MPCOREW, CGID_TAG_ADR), + mc_make_txn_override_cfg(SCEDMAW, CGID_TAG_ADR), + mc_make_txn_override_cfg(SDMMCW, CGID_TAG_ADR), + mc_make_txn_override_cfg(AXISW, CGID_TAG_ADR), + mc_make_txn_override_cfg(TSECSWR, CGID_TAG_ADR), + mc_make_txn_override_cfg(GPUSWR, CGID_TAG_ADR), + mc_make_txn_override_cfg(XUSB_HOSTW, CGID_TAG_ADR), + mc_make_txn_override_cfg(TSECSWRB, CGID_TAG_ADR), + mc_make_txn_override_cfg(GPUSWR2, CGID_TAG_ADR), + mc_make_txn_override_cfg(AONDMAW, CGID_TAG_ADR), + mc_make_txn_override_cfg(AONW, CGID_TAG_ADR), + mc_make_txn_override_cfg(SESWR, CGID_TAG_ADR), + mc_make_txn_override_cfg(BPMPDMAW, CGID_TAG_ADR), + mc_make_txn_override_cfg(SDMMCWA, CGID_TAG_ADR), + mc_make_txn_override_cfg(HDAW, CGID_TAG_ADR), + mc_make_txn_override_cfg(NVDECSWR, CGID_TAG_ADR), + mc_make_txn_override_cfg(UFSHCW, CGID_TAG_ADR), + mc_make_txn_override_cfg(SATAW, CGID_TAG_ADR), + mc_make_txn_override_cfg(ETRW, CGID_TAG_ADR), + mc_make_txn_override_cfg(VICSWR, CGID_TAG_ADR), + mc_make_txn_override_cfg(NVENCSWR, CGID_TAG_ADR), + mc_make_txn_override_cfg(SDMMCWAB, CGID_TAG_ADR), + mc_make_txn_override_cfg(ISPWB, CGID_TAG_ADR), + mc_make_txn_override_cfg(APEW, CGID_TAG_ADR), + mc_make_txn_override_cfg(XUSB_DEVW, CGID_TAG_ADR), + mc_make_txn_override_cfg(AFIW, CGID_TAG_ADR), + mc_make_txn_override_cfg(SCEW, CGID_TAG_ADR), +}; + /* * Init SMMU. */ @@ -207,6 +241,8 @@ void tegra_memctrl_setup(void) uint32_t val; uint32_t num_overrides = sizeof(streamid_overrides) / sizeof(uint32_t); uint32_t num_sec_cfgs = sizeof(sec_cfgs) / sizeof(mc_streamid_security_cfg_t); + uint32_t num_txn_overrides = sizeof(mc_override_cfgs) / sizeof(mc_txn_override_cfg_t); + uint32_t tegra_rev; int i; INFO("Tegra Memory Controller (v2)\n"); @@ -245,6 +281,42 @@ void tegra_memctrl_setup(void) tegra_mc_write_32(MC_SMMU_BYPASS_CONFIG, MC_SMMU_BYPASS_CONFIG_SETTINGS); + /* + * Set the MC_TXN_OVERRIDE registers for write clients. + */ + tegra_rev = (mmio_read_32(TEGRA_MISC_BASE + HARDWARE_REVISION_OFFSET) & + HARDWARE_MINOR_REVISION_MASK) >> HARDWARE_MINOR_REVISION_SHIFT; + + if (tegra_rev == HARDWARE_REVISION_A01) { + + /* GPU and NVENC settings for 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 rev. A02 */ + for (i = 0; i < num_txn_overrides; i++) { + val = tegra_mc_read_32(mc_override_cfgs[i].offset); + val &= ~MC_TXN_OVERRIDE_CGID_TAG_MASK; + tegra_mc_write_32(mc_override_cfgs[i].offset, + val | mc_override_cfgs[i].cgid_tag); + } + + } + /* video memory carveout region */ if (video_mem_base) { tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, diff --git a/plat/nvidia/tegra/include/drivers/memctrl_v2.h b/plat/nvidia/tegra/include/drivers/memctrl_v2.h index 0736b592d..c1061fec7 100644 --- a/plat/nvidia/tegra/include/drivers/memctrl_v2.h +++ b/plat/nvidia/tegra/include/drivers/memctrl_v2.h @@ -207,6 +207,107 @@ #define MC_SMMU_BYPASS_CONFIG_SETTINGS (MC_SMMU_BYPASS_CONFIG_WRITE_ACCESS_BIT | \ MC_SMMU_CTRL_TBU_BYPASS_SPL_STREAMID) +/******************************************************************************* + * 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 + +/******************************************************************************* + * 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 + +/******************************************************************************* + * Structure to hold the transaction override settings to use to override + * client inputs + ******************************************************************************/ +typedef struct mc_txn_override_cfg { + uint32_t offset; + uint8_t cgid_tag; +} mc_txn_override_cfg_t; + +#define mc_make_txn_override_cfg(off, val) \ + { \ + .offset = MC_TXN_OVERRIDE_CONFIG_ ## off, \ + .cgid_tag = MC_TXN_OVERRIDE_ ## val \ + } + /******************************************************************************* * Memory Controller SMMU Global Secure Aux. Configuration Register ******************************************************************************/ diff --git a/plat/nvidia/tegra/include/t186/tegra_def.h b/plat/nvidia/tegra/include/t186/tegra_def.h index 3983a6b03..e74ed166f 100644 --- a/plat/nvidia/tegra/include/t186/tegra_def.h +++ b/plat/nvidia/tegra/include/t186/tegra_def.h @@ -69,6 +69,10 @@ * Tegra Miscellanous register constants ******************************************************************************/ #define TEGRA_MISC_BASE 0x00100000 +#define HARDWARE_REVISION_OFFSET 0x4 +#define HARDWARE_MINOR_REVISION_MASK 0xf0000 +#define HARDWARE_MINOR_REVISION_SHIFT 0x10 +#define HARDWARE_REVISION_A01 1 /******************************************************************************* * Tegra Memory Controller constants From ac55f309f0eebd29bd57509a13761fd6bb8cdb41 Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Wed, 17 Feb 2016 15:31:25 -0800 Subject: [PATCH 20/26] Tegra: memctrl_v2: set NO_OVERRIDE for APE clients For all APE clients (APER, APEW, APEDMAR, APEDMAW) set NO_OVERRIDE for MC_SID_CFG as ACAST/ADAST will be setup with the required SIDs ie. 0x7F & 0x1E. Original change by Nitin Kumbhar Change-Id: Idec981b3537cc95dac6ec37cdaa38bc45b16d232 Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c index bc2d7b595..4d8d307cf 100644 --- a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c +++ b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c @@ -143,7 +143,7 @@ const static mc_streamid_security_cfg_t sec_cfgs[] = { mc_make_sec_cfg(SCEDMAW, NON_SECURE, NO_OVERRIDE, ENABLE), mc_make_sec_cfg(UFSHCR, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(SDMMCWAA, NON_SECURE, OVERRIDE, ENABLE), - mc_make_sec_cfg(APEDMAW, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(APEDMAW, NON_SECURE, NO_OVERRIDE, ENABLE), mc_make_sec_cfg(SESWR, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(MPCORER, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(PTCR, NON_SECURE, OVERRIDE, ENABLE), @@ -158,9 +158,9 @@ const static mc_streamid_security_cfg_t sec_cfgs[] = { mc_make_sec_cfg(XUSB_HOSTW, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(TSECSWR, NON_SECURE, NO_OVERRIDE, ENABLE), mc_make_sec_cfg(SDMMCRAA, NON_SECURE, OVERRIDE, ENABLE), - mc_make_sec_cfg(APER, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(APER, NON_SECURE, NO_OVERRIDE, ENABLE), mc_make_sec_cfg(VIW, NON_SECURE, OVERRIDE, ENABLE), - mc_make_sec_cfg(APEW, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(APEW, NON_SECURE, NO_OVERRIDE, ENABLE), mc_make_sec_cfg(AXISR, SECURE, NO_OVERRIDE, DISABLE), mc_make_sec_cfg(SDMMCW, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(BPMPDMAW, NON_SECURE, NO_OVERRIDE, ENABLE), @@ -190,7 +190,7 @@ const static mc_streamid_security_cfg_t sec_cfgs[] = { mc_make_sec_cfg(SDMMCRAB, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(ETRR, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(AONR, NON_SECURE, OVERRIDE, ENABLE), - mc_make_sec_cfg(APEDMAR, NON_SECURE, OVERRIDE, ENABLE), + mc_make_sec_cfg(APEDMAR, NON_SECURE, NO_OVERRIDE, ENABLE), mc_make_sec_cfg(SESRD, NON_SECURE, OVERRIDE, ENABLE), mc_make_sec_cfg(NVENCSRD, NON_SECURE, NO_OVERRIDE, ENABLE), mc_make_sec_cfg(GPUSWR, SECURE, NO_OVERRIDE, DISABLE), From 50cd8646c58e68c0ff96e43724fe6029b459e4a4 Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Mon, 28 Dec 2015 18:12:59 -0800 Subject: [PATCH 21/26] Tegra186: register FIQ interrupt sources This patch registers all the FIQ interrupt sources during platform setup. Currently we support AON and TOP watchdog timer interrupts. Change-Id: Ibccd866f00d6b08b574f765538525f95b49c5549 Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/include/t186/tegra_def.h | 10 +++++- plat/nvidia/tegra/soc/t186/plat_setup.c | 40 +++++++++++++++++++++ plat/nvidia/tegra/soc/t186/plat_sip_calls.c | 1 - 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/plat/nvidia/tegra/include/t186/tegra_def.h b/plat/nvidia/tegra/include/t186/tegra_def.h index e74ed166f..0732993d9 100644 --- a/plat/nvidia/tegra/include/t186/tegra_def.h +++ b/plat/nvidia/tegra/include/t186/tegra_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -65,6 +65,14 @@ ACTLR_EL3_CPUECTLR_BIT | \ ACTLR_EL3_CPUACTLR_BIT) +/******************************************************************************* + * Secure IRQ definitions + ******************************************************************************/ +#define TEGRA186_TOP_WDT_IRQ 49 +#define TEGRA186_AON_WDT_IRQ 50 + +#define TEGRA186_SEC_IRQ_TARGET_MASK 0xF3 /* 4 A57 - 2 Denver */ + /******************************************************************************* * Tegra Miscellanous register constants ******************************************************************************/ diff --git a/plat/nvidia/tegra/soc/t186/plat_setup.c b/plat/nvidia/tegra/soc/t186/plat_setup.c index 0496f5a5e..44faefef0 100644 --- a/plat/nvidia/tegra/soc/t186/plat_setup.c +++ b/plat/nvidia/tegra/soc/t186/plat_setup.c @@ -28,8 +28,18 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include +#include +#include #include +#include +#include +#include +#include +#include +#include #include +#include #include /******************************************************************************* @@ -120,3 +130,33 @@ uint32_t plat_get_console_from_id(int id) return tegra186_uart_addresses[id]; } + +/* Secure IRQs for Tegra186 */ +static const irq_sec_cfg_t tegra186_sec_irqs[] = { + { + TEGRA186_TOP_WDT_IRQ, + TEGRA186_SEC_IRQ_TARGET_MASK, + INTR_TYPE_EL3, + }, + { + TEGRA186_AON_WDT_IRQ, + TEGRA186_SEC_IRQ_TARGET_MASK, + INTR_TYPE_EL3, + }, +}; + +/******************************************************************************* + * Initialize the GIC and SGIs + ******************************************************************************/ +void plat_gic_setup(void) +{ + tegra_gic_setup(tegra186_sec_irqs, + sizeof(tegra186_sec_irqs) / sizeof(tegra186_sec_irqs[0])); + + /* + * Initialize the FIQ handler only if the platform supports any + * FIQ interrupt sources. + */ + if (sizeof(tegra186_sec_irqs) > 0) + tegra_fiq_handler_setup(); +} diff --git a/plat/nvidia/tegra/soc/t186/plat_sip_calls.c b/plat/nvidia/tegra/soc/t186/plat_sip_calls.c index 66a433e94..8b340a190 100644 --- a/plat/nvidia/tegra/soc/t186/plat_sip_calls.c +++ b/plat/nvidia/tegra/soc/t186/plat_sip_calls.c @@ -134,7 +134,6 @@ int plat_sip_handler(uint32_t smc_fid, return 0; default: - ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); break; } From 1f586a71377011c362eded70c39c1efb97950d9a Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Fri, 26 Feb 2016 11:09:21 -0800 Subject: [PATCH 22/26] Tegra186: disable DCO operations for PSCI_CPU_OFF This patch disables the DCO operations when we turn OFF a CPU. DCO operations are still ON when a CPU enters a power down suspend state. Change-Id: I954a800209ffcc9ab43a77f04040608cbbbd9055 Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/soc/t186/plat_psci_handlers.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c index e91d82fbc..1a77c5bf2 100644 --- a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c +++ b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c @@ -139,6 +139,7 @@ int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state) { cpu_context_t *ctx = cm_get_context(NON_SECURE); gp_regs_t *gp_regs = get_gpregs_ctx(ctx); + int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; assert(ctx); assert(gp_regs); @@ -150,6 +151,10 @@ int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state) mce_command_handler(MCE_CMD_UPDATE_CSTATE_INFO, TEGRA_ARI_CLUSTER_CC7, 0, TEGRA_ARI_SYSTEM_SC7); + /* Disable Denver's DCO operations */ + if (impl == DENVER_IMPL) + denver_disable_dco(); + /* Turn off CPU */ return mce_command_handler(MCE_CMD_ENTER_CSTATE, TEGRA_ARI_CORE_C7, MCE_CORE_SLEEP_TIME_INFINITE, 0); From 7eaf040abb52511eb638fbd88209cb2d33653762 Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Mon, 29 Feb 2016 10:24:30 -0800 Subject: [PATCH 23/26] Tegra186: implement quasi power off (SC8) state This patch adds support for the SC8 system power off state. This state keeps the sensor subsystem powered ON while powering down the remaining parts of the SoC. The CPUs and DRAM are powered down as part of this state entry and perform a cold boot when exiting SC8. Change-Id: Iba65c661a7fe077a0d696f114bab3b4595e19a0d Signed-off-by: Varun Wadekar --- .../tegra/soc/t186/plat_psci_handlers.c | 53 ++++++++++++++++++- plat/nvidia/tegra/soc/t186/plat_sip_calls.c | 30 +++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) diff --git a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c index 1a77c5bf2..20c0f4c12 100644 --- a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c +++ b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c @@ -41,6 +41,8 @@ #include #include +extern void prepare_cpu_pwr_dwn(void); + /* state id mask */ #define TEGRA186_STATE_ID_MASK 0xF /* constants to get power state's wake time */ @@ -49,6 +51,9 @@ static unsigned int wake_time[PLATFORM_CORE_COUNT]; +/* System power down state */ +uint32_t tegra186_system_powerdn_state = TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF; + int32_t tegra_soc_validate_power_state(unsigned int power_state, psci_power_state_t *req_state) { @@ -162,7 +167,53 @@ int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state) __dead2 void tegra_soc_prepare_system_off(void) { - mce_enter_ccplex_state(TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF); + cpu_context_t *ctx = cm_get_context(NON_SECURE); + gp_regs_t *gp_regs = get_gpregs_ctx(ctx); + uint32_t val; + + if (tegra186_system_powerdn_state == TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF) { + + /* power off the entire system */ + mce_enter_ccplex_state(tegra186_system_powerdn_state); + + } else if (tegra186_system_powerdn_state == TEGRA_ARI_SYSTEM_SC8) { + + /* loop until other CPUs power down */ + do { + val = mce_command_handler(MCE_CMD_IS_SC7_ALLOWED, + TEGRA_ARI_CORE_C7, + MCE_CORE_SLEEP_TIME_INFINITE, + 0); + } while (val == 0); + + /* Prepare for quasi power down */ + write_ctx_reg(gp_regs, CTX_GPREG_X4, 1); + write_ctx_reg(gp_regs, CTX_GPREG_X5, 0); + write_ctx_reg(gp_regs, CTX_GPREG_X6, 1); + (void)mce_command_handler(MCE_CMD_UPDATE_CSTATE_INFO, + TEGRA_ARI_CLUSTER_CC7, 0, TEGRA_ARI_SYSTEM_SC8); + + /* Enter quasi power down state */ + (void)mce_command_handler(MCE_CMD_ENTER_CSTATE, + TEGRA_ARI_CORE_C7, MCE_CORE_SLEEP_TIME_INFINITE, 0); + + /* disable GICC */ + tegra_gic_cpuif_deactivate(); + + /* power down core */ + prepare_cpu_pwr_dwn(); + + } else { + ERROR("%s: unsupported power down state (%d)\n", __func__, + tegra186_system_powerdn_state); + } + + wfi(); + + /* wait for the system to power down */ + for (;;) { + ; + } } int tegra_soc_prepare_system_reset(void) diff --git a/plat/nvidia/tegra/soc/t186/plat_sip_calls.c b/plat/nvidia/tegra/soc/t186/plat_sip_calls.c index 8b340a190..fabab0185 100644 --- a/plat/nvidia/tegra/soc/t186/plat_sip_calls.c +++ b/plat/nvidia/tegra/soc/t186/plat_sip_calls.c @@ -41,10 +41,13 @@ #include #include +extern uint32_t tegra186_system_powerdn_state; + /******************************************************************************* * Tegra186 SiP SMCs ******************************************************************************/ #define TEGRA_SIP_NEW_VIDEOMEM_REGION 0x82000003 +#define TEGRA_SIP_SYSTEM_SHUTDOWN_STATE 0x82FFFE01 #define TEGRA_SIP_MCE_CMD_ENTER_CSTATE 0x82FFFF00 #define TEGRA_SIP_MCE_CMD_UPDATE_CSTATE_INFO 0x82FFFF01 #define TEGRA_SIP_MCE_CMD_UPDATE_CROSSOVER_TIME 0x82FFFF02 @@ -133,6 +136,33 @@ int plat_sip_handler(uint32_t smc_fid, return 0; + case TEGRA_SIP_SYSTEM_SHUTDOWN_STATE: + + /* clean up the high bits */ + x1 = (uint32_t)x1; + + /* + * SC8 is a special Tegra186 system state where the CPUs and + * DRAM are powered down but the other subsystem is still + * alive. + */ + if ((x1 == TEGRA_ARI_SYSTEM_SC8) || + (x1 == TEGRA_ARI_MISC_CCPLEX_SHUTDOWN_POWER_OFF)) { + + tegra186_system_powerdn_state = x1; + flush_dcache_range( + (uintptr_t)&tegra186_system_powerdn_state, + sizeof(tegra186_system_powerdn_state)); + + } else { + + ERROR("%s: unhandled powerdn state (%d)\n", __func__, + (uint32_t)x1); + return -ENOTSUP; + } + + return 0; + default: break; } From 4122151f6d0809de7b8d0b6b78c547307c16d99f Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Thu, 3 Mar 2016 13:09:08 -0800 Subject: [PATCH 24/26] Tegra186: smmu: driver for the smmu hardware block This patch adds a device driver for the SMMU hardware block on Tegra186 SoCs. We use the generic ARM SMMU-500 IP block on Tegra186. The driver only supports saving the SMMU settings before entering system suspend. The MC driver and the NS world clients take care of programming their own settings. Change-Id: Iab5a90310ee10f6bc8745451ce50952ab3de7188 Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/include/drivers/smmu.h | 632 ++++++++++++++++++ .../nvidia/tegra/soc/t186/drivers/smmu/smmu.c | 466 +++++++++++++ plat/nvidia/tegra/soc/t186/platform_t186.mk | 3 +- 3 files changed, 1100 insertions(+), 1 deletion(-) create mode 100644 plat/nvidia/tegra/include/drivers/smmu.h create mode 100644 plat/nvidia/tegra/soc/t186/drivers/smmu/smmu.c diff --git a/plat/nvidia/tegra/include/drivers/smmu.h b/plat/nvidia/tegra/include/drivers/smmu.h new file mode 100644 index 000000000..bb08a559f --- /dev/null +++ b/plat/nvidia/tegra/include/drivers/smmu.h @@ -0,0 +1,632 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __SMMU_H +#define __SMMU_H + +#include +#include + +/******************************************************************************* + * SMMU Register constants + ******************************************************************************/ +#define SMMU_CBn_SCTLR (0x0) +#define SMMU_CBn_SCTLR_STAGE2 (0x0) +#define SMMU_CBn_ACTLR (0x4) +#define SMMU_CBn_RESUME (0x8) +#define SMMU_CBn_TCR2 (0x10) +#define SMMU_CBn_TTBR0_LO (0x20) +#define SMMU_CBn_TTBR0_HI (0x24) +#define SMMU_CBn_TTBR1_LO (0x28) +#define SMMU_CBn_TTBR1_HI (0x2c) +#define SMMU_CBn_TCR_LPAE (0x30) +#define SMMU_CBn_TCR (0x30) +#define SMMU_CBn_TCR_EAE_1 (0x30) +#define SMMU_CBn_TCR (0x30) +#define SMMU_CBn_CONTEXTIDR (0x34) +#define SMMU_CBn_CONTEXTIDR_EAE_1 (0x34) +#define SMMU_CBn_PRRR_MAIR0 (0x38) +#define SMMU_CBn_NMRR_MAIR1 (0x3c) +#define SMMU_CBn_SMMU_CBn_PAR (0x50) +#define SMMU_CBn_SMMU_CBn_PAR0 (0x50) +#define SMMU_CBn_SMMU_CBn_PAR1 (0x54) +/* SMMU_CBn_SMMU_CBn_PAR0_Fault (0x50) */ +/* SMMU_CBn_SMMU_CBn_PAR0_Fault (0x54) */ +#define SMMU_CBn_FSR (0x58) +#define SMMU_CBn_FSRRESTORE (0x5c) +#define SMMU_CBn_FAR_LO (0x60) +#define SMMU_CBn_FAR_HI (0x64) +#define SMMU_CBn_FSYNR0 (0x68) +#define SMMU_CBn_IPAFAR_LO (0x70) +#define SMMU_CBn_IPAFAR_HI (0x74) +#define SMMU_CBn_TLBIVA_LO (0x600) +#define SMMU_CBn_TLBIVA_HI (0x604) +#define SMMU_CBn_TLBIVA_AARCH_32 (0x600) +#define SMMU_CBn_TLBIVAA_LO (0x608) +#define SMMU_CBn_TLBIVAA_HI (0x60c) +#define SMMU_CBn_TLBIVAA_AARCH_32 (0x608) +#define SMMU_CBn_TLBIASID (0x610) +#define SMMU_CBn_TLBIALL (0x618) +#define SMMU_CBn_TLBIVAL_LO (0x620) +#define SMMU_CBn_TLBIVAL_HI (0x624) +#define SMMU_CBn_TLBIVAL_AARCH_32 (0x618) +#define SMMU_CBn_TLBIVAAL_LO (0x628) +#define SMMU_CBn_TLBIVAAL_HI (0x62c) +#define SMMU_CBn_TLBIVAAL_AARCH_32 (0x628) +#define SMMU_CBn_TLBIIPAS2_LO (0x630) +#define SMMU_CBn_TLBIIPAS2_HI (0x634) +#define SMMU_CBn_TLBIIPAS2L_LO (0x638) +#define SMMU_CBn_TLBIIPAS2L_HI (0x63c) +#define SMMU_CBn_TLBSYNC (0x7f0) +#define SMMU_CBn_TLBSTATUS (0x7f4) +#define SMMU_CBn_ATSR (0x800) +#define SMMU_CBn_PMEVCNTR0 (0xe00) +#define SMMU_CBn_PMEVCNTR1 (0xe04) +#define SMMU_CBn_PMEVCNTR2 (0xe08) +#define SMMU_CBn_PMEVCNTR3 (0xe0c) +#define SMMU_CBn_PMEVTYPER0 (0xe80) +#define SMMU_CBn_PMEVTYPER1 (0xe84) +#define SMMU_CBn_PMEVTYPER2 (0xe88) +#define SMMU_CBn_PMEVTYPER3 (0xe8c) +#define SMMU_CBn_PMCFGR (0xf00) +#define SMMU_CBn_PMCR (0xf04) +#define SMMU_CBn_PMCEID (0xf20) +#define SMMU_CBn_PMCNTENSE (0xf40) +#define SMMU_CBn_PMCNTENCLR (0xf44) +#define SMMU_CBn_PMCNTENSET (0xf48) +#define SMMU_CBn_PMINTENCLR (0xf4c) +#define SMMU_CBn_PMOVSCLR (0xf50) +#define SMMU_CBn_PMOVSSET (0xf58) +#define SMMU_CBn_PMAUTHSTATUS (0xfb8) +#define SMMU_GNSR0_CR0 (0x0) +#define SMMU_GNSR0_CR2 (0x8) +#define SMMU_GNSR0_ACR (0x10) +#define SMMU_GNSR0_IDR0 (0x20) +#define SMMU_GNSR0_IDR1 (0x24) +#define SMMU_GNSR0_IDR2 (0x28) +#define SMMU_GNSR0_IDR7 (0x3c) +#define SMMU_GNSR0_GFAR_LO (0x40) +#define SMMU_GNSR0_GFAR_HI (0x44) +#define SMMU_GNSR0_GFSR (0x48) +#define SMMU_GNSR0_GFSRRESTORE (0x4c) +#define SMMU_GNSR0_GFSYNR0 (0x50) +#define SMMU_GNSR0_GFSYNR1 (0x54) +#define SMMU_GNSR0_GFSYNR1_v2 (0x54) +#define SMMU_GNSR0_TLBIVMID (0x64) +#define SMMU_GNSR0_TLBIALLNSNH (0x68) +#define SMMU_GNSR0_TLBIALLH (0x6c) +#define SMMU_GNSR0_TLBGSYNC (0x70) +#define SMMU_GNSR0_TLBGSTATUS (0x74) +#define SMMU_GNSR0_TLBIVAH_LO (0x78) +#define SMMU_GNSR0_TLBIVALH64_LO (0xb0) +#define SMMU_GNSR0_TLBIVALH64_HI (0xb4) +#define SMMU_GNSR0_TLBIVMIDS1 (0xb8) +#define SMMU_GNSR0_TLBIVAH64_LO (0xc0) +#define SMMU_GNSR0_TLBIVAH64_HI (0xc4) +#define SMMU_GNSR0_SMR0 (0x800) +#define SMMU_GNSR0_SMRn (0x800) +#define SMMU_GNSR0_SMR1 (0x804) +#define SMMU_GNSR0_SMR2 (0x808) +#define SMMU_GNSR0_SMR3 (0x80c) +#define SMMU_GNSR0_SMR4 (0x810) +#define SMMU_GNSR0_SMR5 (0x814) +#define SMMU_GNSR0_SMR6 (0x818) +#define SMMU_GNSR0_SMR7 (0x81c) +#define SMMU_GNSR0_SMR8 (0x820) +#define SMMU_GNSR0_SMR9 (0x824) +#define SMMU_GNSR0_SMR10 (0x828) +#define SMMU_GNSR0_SMR11 (0x82c) +#define SMMU_GNSR0_SMR12 (0x830) +#define SMMU_GNSR0_SMR13 (0x834) +#define SMMU_GNSR0_SMR14 (0x838) +#define SMMU_GNSR0_SMR15 (0x83c) +#define SMMU_GNSR0_SMR16 (0x840) +#define SMMU_GNSR0_SMR17 (0x844) +#define SMMU_GNSR0_SMR18 (0x848) +#define SMMU_GNSR0_SMR19 (0x84c) +#define SMMU_GNSR0_SMR20 (0x850) +#define SMMU_GNSR0_SMR21 (0x854) +#define SMMU_GNSR0_SMR22 (0x858) +#define SMMU_GNSR0_SMR23 (0x85c) +#define SMMU_GNSR0_SMR24 (0x860) +#define SMMU_GNSR0_SMR25 (0x864) +#define SMMU_GNSR0_SMR26 (0x868) +#define SMMU_GNSR0_SMR27 (0x86c) +#define SMMU_GNSR0_SMR28 (0x870) +#define SMMU_GNSR0_SMR29 (0x874) +#define SMMU_GNSR0_SMR30 (0x878) +#define SMMU_GNSR0_SMR31 (0x87c) +#define SMMU_GNSR0_SMR32 (0x880) +#define SMMU_GNSR0_SMR33 (0x884) +#define SMMU_GNSR0_SMR34 (0x888) +#define SMMU_GNSR0_SMR35 (0x88c) +#define SMMU_GNSR0_SMR36 (0x890) +#define SMMU_GNSR0_SMR37 (0x894) +#define SMMU_GNSR0_SMR38 (0x898) +#define SMMU_GNSR0_SMR39 (0x89c) +#define SMMU_GNSR0_SMR40 (0x8a0) +#define SMMU_GNSR0_SMR41 (0x8a4) +#define SMMU_GNSR0_SMR42 (0x8a8) +#define SMMU_GNSR0_SMR43 (0x8ac) +#define SMMU_GNSR0_SMR44 (0x8b0) +#define SMMU_GNSR0_SMR45 (0x8b4) +#define SMMU_GNSR0_SMR46 (0x8b8) +#define SMMU_GNSR0_SMR47 (0x8bc) +#define SMMU_GNSR0_SMR48 (0x8c0) +#define SMMU_GNSR0_SMR49 (0x8c4) +#define SMMU_GNSR0_SMR50 (0x8c8) +#define SMMU_GNSR0_SMR51 (0x8cc) +#define SMMU_GNSR0_SMR52 (0x8d0) +#define SMMU_GNSR0_SMR53 (0x8d4) +#define SMMU_GNSR0_SMR54 (0x8d8) +#define SMMU_GNSR0_SMR55 (0x8dc) +#define SMMU_GNSR0_SMR56 (0x8e0) +#define SMMU_GNSR0_SMR57 (0x8e4) +#define SMMU_GNSR0_SMR58 (0x8e8) +#define SMMU_GNSR0_SMR59 (0x8ec) +#define SMMU_GNSR0_SMR60 (0x8f0) +#define SMMU_GNSR0_SMR61 (0x8f4) +#define SMMU_GNSR0_SMR62 (0x8f8) +#define SMMU_GNSR0_SMR63 (0x8fc) +#define SMMU_GNSR0_SMR64 (0x900) +#define SMMU_GNSR0_SMR65 (0x904) +#define SMMU_GNSR0_SMR66 (0x908) +#define SMMU_GNSR0_SMR67 (0x90c) +#define SMMU_GNSR0_SMR68 (0x910) +#define SMMU_GNSR0_SMR69 (0x914) +#define SMMU_GNSR0_SMR70 (0x918) +#define SMMU_GNSR0_SMR71 (0x91c) +#define SMMU_GNSR0_SMR72 (0x920) +#define SMMU_GNSR0_SMR73 (0x924) +#define SMMU_GNSR0_SMR74 (0x928) +#define SMMU_GNSR0_SMR75 (0x92c) +#define SMMU_GNSR0_SMR76 (0x930) +#define SMMU_GNSR0_SMR77 (0x934) +#define SMMU_GNSR0_SMR78 (0x938) +#define SMMU_GNSR0_SMR79 (0x93c) +#define SMMU_GNSR0_SMR80 (0x940) +#define SMMU_GNSR0_SMR81 (0x944) +#define SMMU_GNSR0_SMR82 (0x948) +#define SMMU_GNSR0_SMR83 (0x94c) +#define SMMU_GNSR0_SMR84 (0x950) +#define SMMU_GNSR0_SMR85 (0x954) +#define SMMU_GNSR0_SMR86 (0x958) +#define SMMU_GNSR0_SMR87 (0x95c) +#define SMMU_GNSR0_SMR88 (0x960) +#define SMMU_GNSR0_SMR89 (0x964) +#define SMMU_GNSR0_SMR90 (0x968) +#define SMMU_GNSR0_SMR91 (0x96c) +#define SMMU_GNSR0_SMR92 (0x970) +#define SMMU_GNSR0_SMR93 (0x974) +#define SMMU_GNSR0_SMR94 (0x978) +#define SMMU_GNSR0_SMR95 (0x97c) +#define SMMU_GNSR0_SMR96 (0x980) +#define SMMU_GNSR0_SMR97 (0x984) +#define SMMU_GNSR0_SMR98 (0x988) +#define SMMU_GNSR0_SMR99 (0x98c) +#define SMMU_GNSR0_SMR100 (0x990) +#define SMMU_GNSR0_SMR101 (0x994) +#define SMMU_GNSR0_SMR102 (0x998) +#define SMMU_GNSR0_SMR103 (0x99c) +#define SMMU_GNSR0_SMR104 (0x9a0) +#define SMMU_GNSR0_SMR105 (0x9a4) +#define SMMU_GNSR0_SMR106 (0x9a8) +#define SMMU_GNSR0_SMR107 (0x9ac) +#define SMMU_GNSR0_SMR108 (0x9b0) +#define SMMU_GNSR0_SMR109 (0x9b4) +#define SMMU_GNSR0_SMR110 (0x9b8) +#define SMMU_GNSR0_SMR111 (0x9bc) +#define SMMU_GNSR0_SMR112 (0x9c0) +#define SMMU_GNSR0_SMR113 (0x9c4) +#define SMMU_GNSR0_SMR114 (0x9c8) +#define SMMU_GNSR0_SMR115 (0x9cc) +#define SMMU_GNSR0_SMR116 (0x9d0) +#define SMMU_GNSR0_SMR117 (0x9d4) +#define SMMU_GNSR0_SMR118 (0x9d8) +#define SMMU_GNSR0_SMR119 (0x9dc) +#define SMMU_GNSR0_SMR120 (0x9e0) +#define SMMU_GNSR0_SMR121 (0x9e4) +#define SMMU_GNSR0_SMR122 (0x9e8) +#define SMMU_GNSR0_SMR123 (0x9ec) +#define SMMU_GNSR0_SMR124 (0x9f0) +#define SMMU_GNSR0_SMR125 (0x9f4) +#define SMMU_GNSR0_SMR126 (0x9f8) +#define SMMU_GNSR0_SMR127 (0x9fc) +#define SMMU_GNSR0_S2CR0 (0xc00) +#define SMMU_GNSR0_S2CRn (0xc00) +#define SMMU_GNSR0_S2CRn (0xc00) +#define SMMU_GNSR0_S2CR1 (0xc04) +#define SMMU_GNSR0_S2CR2 (0xc08) +#define SMMU_GNSR0_S2CR3 (0xc0c) +#define SMMU_GNSR0_S2CR4 (0xc10) +#define SMMU_GNSR0_S2CR5 (0xc14) +#define SMMU_GNSR0_S2CR6 (0xc18) +#define SMMU_GNSR0_S2CR7 (0xc1c) +#define SMMU_GNSR0_S2CR8 (0xc20) +#define SMMU_GNSR0_S2CR9 (0xc24) +#define SMMU_GNSR0_S2CR10 (0xc28) +#define SMMU_GNSR0_S2CR11 (0xc2c) +#define SMMU_GNSR0_S2CR12 (0xc30) +#define SMMU_GNSR0_S2CR13 (0xc34) +#define SMMU_GNSR0_S2CR14 (0xc38) +#define SMMU_GNSR0_S2CR15 (0xc3c) +#define SMMU_GNSR0_S2CR16 (0xc40) +#define SMMU_GNSR0_S2CR17 (0xc44) +#define SMMU_GNSR0_S2CR18 (0xc48) +#define SMMU_GNSR0_S2CR19 (0xc4c) +#define SMMU_GNSR0_S2CR20 (0xc50) +#define SMMU_GNSR0_S2CR21 (0xc54) +#define SMMU_GNSR0_S2CR22 (0xc58) +#define SMMU_GNSR0_S2CR23 (0xc5c) +#define SMMU_GNSR0_S2CR24 (0xc60) +#define SMMU_GNSR0_S2CR25 (0xc64) +#define SMMU_GNSR0_S2CR26 (0xc68) +#define SMMU_GNSR0_S2CR27 (0xc6c) +#define SMMU_GNSR0_S2CR28 (0xc70) +#define SMMU_GNSR0_S2CR29 (0xc74) +#define SMMU_GNSR0_S2CR30 (0xc78) +#define SMMU_GNSR0_S2CR31 (0xc7c) +#define SMMU_GNSR0_S2CR32 (0xc80) +#define SMMU_GNSR0_S2CR33 (0xc84) +#define SMMU_GNSR0_S2CR34 (0xc88) +#define SMMU_GNSR0_S2CR35 (0xc8c) +#define SMMU_GNSR0_S2CR36 (0xc90) +#define SMMU_GNSR0_S2CR37 (0xc94) +#define SMMU_GNSR0_S2CR38 (0xc98) +#define SMMU_GNSR0_S2CR39 (0xc9c) +#define SMMU_GNSR0_S2CR40 (0xca0) +#define SMMU_GNSR0_S2CR41 (0xca4) +#define SMMU_GNSR0_S2CR42 (0xca8) +#define SMMU_GNSR0_S2CR43 (0xcac) +#define SMMU_GNSR0_S2CR44 (0xcb0) +#define SMMU_GNSR0_S2CR45 (0xcb4) +#define SMMU_GNSR0_S2CR46 (0xcb8) +#define SMMU_GNSR0_S2CR47 (0xcbc) +#define SMMU_GNSR0_S2CR48 (0xcc0) +#define SMMU_GNSR0_S2CR49 (0xcc4) +#define SMMU_GNSR0_S2CR50 (0xcc8) +#define SMMU_GNSR0_S2CR51 (0xccc) +#define SMMU_GNSR0_S2CR52 (0xcd0) +#define SMMU_GNSR0_S2CR53 (0xcd4) +#define SMMU_GNSR0_S2CR54 (0xcd8) +#define SMMU_GNSR0_S2CR55 (0xcdc) +#define SMMU_GNSR0_S2CR56 (0xce0) +#define SMMU_GNSR0_S2CR57 (0xce4) +#define SMMU_GNSR0_S2CR58 (0xce8) +#define SMMU_GNSR0_S2CR59 (0xcec) +#define SMMU_GNSR0_S2CR60 (0xcf0) +#define SMMU_GNSR0_S2CR61 (0xcf4) +#define SMMU_GNSR0_S2CR62 (0xcf8) +#define SMMU_GNSR0_S2CR63 (0xcfc) +#define SMMU_GNSR0_S2CR64 (0xd00) +#define SMMU_GNSR0_S2CR65 (0xd04) +#define SMMU_GNSR0_S2CR66 (0xd08) +#define SMMU_GNSR0_S2CR67 (0xd0c) +#define SMMU_GNSR0_S2CR68 (0xd10) +#define SMMU_GNSR0_S2CR69 (0xd14) +#define SMMU_GNSR0_S2CR70 (0xd18) +#define SMMU_GNSR0_S2CR71 (0xd1c) +#define SMMU_GNSR0_S2CR72 (0xd20) +#define SMMU_GNSR0_S2CR73 (0xd24) +#define SMMU_GNSR0_S2CR74 (0xd28) +#define SMMU_GNSR0_S2CR75 (0xd2c) +#define SMMU_GNSR0_S2CR76 (0xd30) +#define SMMU_GNSR0_S2CR77 (0xd34) +#define SMMU_GNSR0_S2CR78 (0xd38) +#define SMMU_GNSR0_S2CR79 (0xd3c) +#define SMMU_GNSR0_S2CR80 (0xd40) +#define SMMU_GNSR0_S2CR81 (0xd44) +#define SMMU_GNSR0_S2CR82 (0xd48) +#define SMMU_GNSR0_S2CR83 (0xd4c) +#define SMMU_GNSR0_S2CR84 (0xd50) +#define SMMU_GNSR0_S2CR85 (0xd54) +#define SMMU_GNSR0_S2CR86 (0xd58) +#define SMMU_GNSR0_S2CR87 (0xd5c) +#define SMMU_GNSR0_S2CR88 (0xd60) +#define SMMU_GNSR0_S2CR89 (0xd64) +#define SMMU_GNSR0_S2CR90 (0xd68) +#define SMMU_GNSR0_S2CR91 (0xd6c) +#define SMMU_GNSR0_S2CR92 (0xd70) +#define SMMU_GNSR0_S2CR93 (0xd74) +#define SMMU_GNSR0_S2CR94 (0xd78) +#define SMMU_GNSR0_S2CR95 (0xd7c) +#define SMMU_GNSR0_S2CR96 (0xd80) +#define SMMU_GNSR0_S2CR97 (0xd84) +#define SMMU_GNSR0_S2CR98 (0xd88) +#define SMMU_GNSR0_S2CR99 (0xd8c) +#define SMMU_GNSR0_S2CR100 (0xd90) +#define SMMU_GNSR0_S2CR101 (0xd94) +#define SMMU_GNSR0_S2CR102 (0xd98) +#define SMMU_GNSR0_S2CR103 (0xd9c) +#define SMMU_GNSR0_S2CR104 (0xda0) +#define SMMU_GNSR0_S2CR105 (0xda4) +#define SMMU_GNSR0_S2CR106 (0xda8) +#define SMMU_GNSR0_S2CR107 (0xdac) +#define SMMU_GNSR0_S2CR108 (0xdb0) +#define SMMU_GNSR0_S2CR109 (0xdb4) +#define SMMU_GNSR0_S2CR110 (0xdb8) +#define SMMU_GNSR0_S2CR111 (0xdbc) +#define SMMU_GNSR0_S2CR112 (0xdc0) +#define SMMU_GNSR0_S2CR113 (0xdc4) +#define SMMU_GNSR0_S2CR114 (0xdc8) +#define SMMU_GNSR0_S2CR115 (0xdcc) +#define SMMU_GNSR0_S2CR116 (0xdd0) +#define SMMU_GNSR0_S2CR117 (0xdd4) +#define SMMU_GNSR0_S2CR118 (0xdd8) +#define SMMU_GNSR0_S2CR119 (0xddc) +#define SMMU_GNSR0_S2CR120 (0xde0) +#define SMMU_GNSR0_S2CR121 (0xde4) +#define SMMU_GNSR0_S2CR122 (0xde8) +#define SMMU_GNSR0_S2CR123 (0xdec) +#define SMMU_GNSR0_S2CR124 (0xdf0) +#define SMMU_GNSR0_S2CR125 (0xdf4) +#define SMMU_GNSR0_S2CR126 (0xdf8) +#define SMMU_GNSR0_S2CR127 (0xdfc) +#define SMMU_GNSR0_PIDR0 (0xfe0) +#define SMMU_GNSR0_PIDR1 (0xfe4) +#define SMMU_GNSR0_PIDR2 (0xfe8) +#define SMMU_GNSR0_PIDR3 (0xfec) +#define SMMU_GNSR0_PIDR4 (0xfd0) +#define SMMU_GNSR0_PIDR5 (0xfd4) +#define SMMU_GNSR0_PIDR6 (0xfd8) +#define SMMU_GNSR0_PIDR7 (0xfdc) +#define SMMU_GNSR0_CIDR0 (0xff0) +#define SMMU_GNSR0_CIDR1 (0xff4) +#define SMMU_GNSR0_CIDR2 (0xff8) +#define SMMU_GNSR0_CIDR3 (0xffc) +#define SMMU_GNSR1_CBAR0 (0x0) +#define SMMU_GNSR1_CBARn (0x0) +#define SMMU_GNSR1_CBFRSYNRA0 (0x400) +#define SMMU_GNSR1_CBA2R0 (0x800) +#define SMMU_GNSR1_CBAR1 (0x4) +#define SMMU_GNSR1_CBFRSYNRA1 (0x404) +#define SMMU_GNSR1_CBA2R1 (0x804) +#define SMMU_GNSR1_CBAR2 (0x8) +#define SMMU_GNSR1_CBFRSYNRA2 (0x408) +#define SMMU_GNSR1_CBA2R2 (0x808) +#define SMMU_GNSR1_CBAR3 (0xc) +#define SMMU_GNSR1_CBFRSYNRA3 (0x40c) +#define SMMU_GNSR1_CBA2R3 (0x80c) +#define SMMU_GNSR1_CBAR4 (0x10) +#define SMMU_GNSR1_CBFRSYNRA4 (0x410) +#define SMMU_GNSR1_CBA2R4 (0x810) +#define SMMU_GNSR1_CBAR5 (0x14) +#define SMMU_GNSR1_CBFRSYNRA5 (0x414) +#define SMMU_GNSR1_CBA2R5 (0x814) +#define SMMU_GNSR1_CBAR6 (0x18) +#define SMMU_GNSR1_CBFRSYNRA6 (0x418) +#define SMMU_GNSR1_CBA2R6 (0x818) +#define SMMU_GNSR1_CBAR7 (0x1c) +#define SMMU_GNSR1_CBFRSYNRA7 (0x41c) +#define SMMU_GNSR1_CBA2R7 (0x81c) +#define SMMU_GNSR1_CBAR8 (0x20) +#define SMMU_GNSR1_CBFRSYNRA8 (0x420) +#define SMMU_GNSR1_CBA2R8 (0x820) +#define SMMU_GNSR1_CBAR9 (0x24) +#define SMMU_GNSR1_CBFRSYNRA9 (0x424) +#define SMMU_GNSR1_CBA2R9 (0x824) +#define SMMU_GNSR1_CBAR10 (0x28) +#define SMMU_GNSR1_CBFRSYNRA10 (0x428) +#define SMMU_GNSR1_CBA2R10 (0x828) +#define SMMU_GNSR1_CBAR11 (0x2c) +#define SMMU_GNSR1_CBFRSYNRA11 (0x42c) +#define SMMU_GNSR1_CBA2R11 (0x82c) +#define SMMU_GNSR1_CBAR12 (0x30) +#define SMMU_GNSR1_CBFRSYNRA12 (0x430) +#define SMMU_GNSR1_CBA2R12 (0x830) +#define SMMU_GNSR1_CBAR13 (0x34) +#define SMMU_GNSR1_CBFRSYNRA13 (0x434) +#define SMMU_GNSR1_CBA2R13 (0x834) +#define SMMU_GNSR1_CBAR14 (0x38) +#define SMMU_GNSR1_CBFRSYNRA14 (0x438) +#define SMMU_GNSR1_CBA2R14 (0x838) +#define SMMU_GNSR1_CBAR15 (0x3c) +#define SMMU_GNSR1_CBFRSYNRA15 (0x43c) +#define SMMU_GNSR1_CBA2R15 (0x83c) +#define SMMU_GNSR1_CBAR16 (0x40) +#define SMMU_GNSR1_CBFRSYNRA16 (0x440) +#define SMMU_GNSR1_CBA2R16 (0x840) +#define SMMU_GNSR1_CBAR17 (0x44) +#define SMMU_GNSR1_CBFRSYNRA17 (0x444) +#define SMMU_GNSR1_CBA2R17 (0x844) +#define SMMU_GNSR1_CBAR18 (0x48) +#define SMMU_GNSR1_CBFRSYNRA18 (0x448) +#define SMMU_GNSR1_CBA2R18 (0x848) +#define SMMU_GNSR1_CBAR19 (0x4c) +#define SMMU_GNSR1_CBFRSYNRA19 (0x44c) +#define SMMU_GNSR1_CBA2R19 (0x84c) +#define SMMU_GNSR1_CBAR20 (0x50) +#define SMMU_GNSR1_CBFRSYNRA20 (0x450) +#define SMMU_GNSR1_CBA2R20 (0x850) +#define SMMU_GNSR1_CBAR21 (0x54) +#define SMMU_GNSR1_CBFRSYNRA21 (0x454) +#define SMMU_GNSR1_CBA2R21 (0x854) +#define SMMU_GNSR1_CBAR22 (0x58) +#define SMMU_GNSR1_CBFRSYNRA22 (0x458) +#define SMMU_GNSR1_CBA2R22 (0x858) +#define SMMU_GNSR1_CBAR23 (0x5c) +#define SMMU_GNSR1_CBFRSYNRA23 (0x45c) +#define SMMU_GNSR1_CBA2R23 (0x85c) +#define SMMU_GNSR1_CBAR24 (0x60) +#define SMMU_GNSR1_CBFRSYNRA24 (0x460) +#define SMMU_GNSR1_CBA2R24 (0x860) +#define SMMU_GNSR1_CBAR25 (0x64) +#define SMMU_GNSR1_CBFRSYNRA25 (0x464) +#define SMMU_GNSR1_CBA2R25 (0x864) +#define SMMU_GNSR1_CBAR26 (0x68) +#define SMMU_GNSR1_CBFRSYNRA26 (0x468) +#define SMMU_GNSR1_CBA2R26 (0x868) +#define SMMU_GNSR1_CBAR27 (0x6c) +#define SMMU_GNSR1_CBFRSYNRA27 (0x46c) +#define SMMU_GNSR1_CBA2R27 (0x86c) +#define SMMU_GNSR1_CBAR28 (0x70) +#define SMMU_GNSR1_CBFRSYNRA28 (0x470) +#define SMMU_GNSR1_CBA2R28 (0x870) +#define SMMU_GNSR1_CBAR29 (0x74) +#define SMMU_GNSR1_CBFRSYNRA29 (0x474) +#define SMMU_GNSR1_CBA2R29 (0x874) +#define SMMU_GNSR1_CBAR30 (0x78) +#define SMMU_GNSR1_CBFRSYNRA30 (0x478) +#define SMMU_GNSR1_CBA2R30 (0x878) +#define SMMU_GNSR1_CBAR31 (0x7c) +#define SMMU_GNSR1_CBFRSYNRA31 (0x47c) +#define SMMU_GNSR1_CBA2R31 (0x87c) +#define SMMU_GNSR1_CBAR32 (0x80) +#define SMMU_GNSR1_CBFRSYNRA32 (0x480) +#define SMMU_GNSR1_CBA2R32 (0x880) +#define SMMU_GNSR1_CBAR33 (0x84) +#define SMMU_GNSR1_CBFRSYNRA33 (0x484) +#define SMMU_GNSR1_CBA2R33 (0x884) +#define SMMU_GNSR1_CBAR34 (0x88) +#define SMMU_GNSR1_CBFRSYNRA34 (0x488) +#define SMMU_GNSR1_CBA2R34 (0x888) +#define SMMU_GNSR1_CBAR35 (0x8c) +#define SMMU_GNSR1_CBFRSYNRA35 (0x48c) +#define SMMU_GNSR1_CBA2R35 (0x88c) +#define SMMU_GNSR1_CBAR36 (0x90) +#define SMMU_GNSR1_CBFRSYNRA36 (0x490) +#define SMMU_GNSR1_CBA2R36 (0x890) +#define SMMU_GNSR1_CBAR37 (0x94) +#define SMMU_GNSR1_CBFRSYNRA37 (0x494) +#define SMMU_GNSR1_CBA2R37 (0x894) +#define SMMU_GNSR1_CBAR38 (0x98) +#define SMMU_GNSR1_CBFRSYNRA38 (0x498) +#define SMMU_GNSR1_CBA2R38 (0x898) +#define SMMU_GNSR1_CBAR39 (0x9c) +#define SMMU_GNSR1_CBFRSYNRA39 (0x49c) +#define SMMU_GNSR1_CBA2R39 (0x89c) +#define SMMU_GNSR1_CBAR40 (0xa0) +#define SMMU_GNSR1_CBFRSYNRA40 (0x4a0) +#define SMMU_GNSR1_CBA2R40 (0x8a0) +#define SMMU_GNSR1_CBAR41 (0xa4) +#define SMMU_GNSR1_CBFRSYNRA41 (0x4a4) +#define SMMU_GNSR1_CBA2R41 (0x8a4) +#define SMMU_GNSR1_CBAR42 (0xa8) +#define SMMU_GNSR1_CBFRSYNRA42 (0x4a8) +#define SMMU_GNSR1_CBA2R42 (0x8a8) +#define SMMU_GNSR1_CBAR43 (0xac) +#define SMMU_GNSR1_CBFRSYNRA43 (0x4ac) +#define SMMU_GNSR1_CBA2R43 (0x8ac) +#define SMMU_GNSR1_CBAR44 (0xb0) +#define SMMU_GNSR1_CBFRSYNRA44 (0x4b0) +#define SMMU_GNSR1_CBA2R44 (0x8b0) +#define SMMU_GNSR1_CBAR45 (0xb4) +#define SMMU_GNSR1_CBFRSYNRA45 (0x4b4) +#define SMMU_GNSR1_CBA2R45 (0x8b4) +#define SMMU_GNSR1_CBAR46 (0xb8) +#define SMMU_GNSR1_CBFRSYNRA46 (0x4b8) +#define SMMU_GNSR1_CBA2R46 (0x8b8) +#define SMMU_GNSR1_CBAR47 (0xbc) +#define SMMU_GNSR1_CBFRSYNRA47 (0x4bc) +#define SMMU_GNSR1_CBA2R47 (0x8bc) +#define SMMU_GNSR1_CBAR48 (0xc0) +#define SMMU_GNSR1_CBFRSYNRA48 (0x4c0) +#define SMMU_GNSR1_CBA2R48 (0x8c0) +#define SMMU_GNSR1_CBAR49 (0xc4) +#define SMMU_GNSR1_CBFRSYNRA49 (0x4c4) +#define SMMU_GNSR1_CBA2R49 (0x8c4) +#define SMMU_GNSR1_CBAR50 (0xc8) +#define SMMU_GNSR1_CBFRSYNRA50 (0x4c8) +#define SMMU_GNSR1_CBA2R50 (0x8c8) +#define SMMU_GNSR1_CBAR51 (0xcc) +#define SMMU_GNSR1_CBFRSYNRA51 (0x4cc) +#define SMMU_GNSR1_CBA2R51 (0x8cc) +#define SMMU_GNSR1_CBAR52 (0xd0) +#define SMMU_GNSR1_CBFRSYNRA52 (0x4d0) +#define SMMU_GNSR1_CBA2R52 (0x8d0) +#define SMMU_GNSR1_CBAR53 (0xd4) +#define SMMU_GNSR1_CBFRSYNRA53 (0x4d4) +#define SMMU_GNSR1_CBA2R53 (0x8d4) +#define SMMU_GNSR1_CBAR54 (0xd8) +#define SMMU_GNSR1_CBFRSYNRA54 (0x4d8) +#define SMMU_GNSR1_CBA2R54 (0x8d8) +#define SMMU_GNSR1_CBAR55 (0xdc) +#define SMMU_GNSR1_CBFRSYNRA55 (0x4dc) +#define SMMU_GNSR1_CBA2R55 (0x8dc) +#define SMMU_GNSR1_CBAR56 (0xe0) +#define SMMU_GNSR1_CBFRSYNRA56 (0x4e0) +#define SMMU_GNSR1_CBA2R56 (0x8e0) +#define SMMU_GNSR1_CBAR57 (0xe4) +#define SMMU_GNSR1_CBFRSYNRA57 (0x4e4) +#define SMMU_GNSR1_CBA2R57 (0x8e4) +#define SMMU_GNSR1_CBAR58 (0xe8) +#define SMMU_GNSR1_CBFRSYNRA58 (0x4e8) +#define SMMU_GNSR1_CBA2R58 (0x8e8) +#define SMMU_GNSR1_CBAR59 (0xec) +#define SMMU_GNSR1_CBFRSYNRA59 (0x4ec) +#define SMMU_GNSR1_CBA2R59 (0x8ec) +#define SMMU_GNSR1_CBAR60 (0xf0) +#define SMMU_GNSR1_CBFRSYNRA60 (0x4f0) +#define SMMU_GNSR1_CBA2R60 (0x8f0) +#define SMMU_GNSR1_CBAR61 (0xf4) +#define SMMU_GNSR1_CBFRSYNRA61 (0x4f4) +#define SMMU_GNSR1_CBA2R61 (0x8f4) +#define SMMU_GNSR1_CBAR62 (0xf8) +#define SMMU_GNSR1_CBFRSYNRA62 (0x4f8) +#define SMMU_GNSR1_CBA2R62 (0x8f8) +#define SMMU_GNSR1_CBAR63 (0xfc) +#define SMMU_GNSR1_CBFRSYNRA63 (0x4fc) +#define SMMU_GNSR1_CBA2R63 (0x8fc) + +/******************************************************************************* + * SMMU Global Secure Aux. Configuration Register + ******************************************************************************/ +#define SMMU_GSR0_SECURE_ACR 0x10 +#define SMMU_GSR0_PGSIZE_SHIFT 16 +#define SMMU_GSR0_PGSIZE_4K (0 << SMMU_GSR0_PGSIZE_SHIFT) +#define SMMU_GSR0_PGSIZE_64K (1 << SMMU_GSR0_PGSIZE_SHIFT) + +/******************************************************************************* + * SMMU configuration constants + ******************************************************************************/ +#define ID1_PAGESIZE (1 << 31) +#define ID1_NUMPAGENDXB_SHIFT 28 +#define ID1_NUMPAGENDXB_MASK 7 +#define ID1_NUMS2CB_SHIFT 16 +#define ID1_NUMS2CB_MASK 0xff +#define ID1_NUMCB_SHIFT 0 +#define ID1_NUMCB_MASK 0xff +#define PGSHIFT 16 +#define CB_SIZE 0x800000 + +static inline uint32_t tegra_smmu_read_32(uint32_t off) +{ + return mmio_read_32(TEGRA_SMMU_BASE + off); +} + +static inline void tegra_smmu_write_32(uint32_t off, uint32_t val) +{ + mmio_write_32(TEGRA_SMMU_BASE + off, val); +} + +void tegra_smmu_init(void); +void tegra_smmu_save_context(void); + +#endif /*__SMMU_H */ diff --git a/plat/nvidia/tegra/soc/t186/drivers/smmu/smmu.c b/plat/nvidia/tegra/soc/t186/drivers/smmu/smmu.c new file mode 100644 index 000000000..2940f5837 --- /dev/null +++ b/plat/nvidia/tegra/soc/t186/drivers/smmu/smmu.c @@ -0,0 +1,466 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +typedef struct smmu_regs { + uint32_t reg; + uint32_t val; +} smmu_regs_t; + +#define mc_make_sid_override_cfg(name) \ + { \ + .reg = TEGRA_MC_STREAMID_BASE + MC_STREAMID_OVERRIDE_CFG_ ## name, \ + .val = 0x00000000, \ + } + +#define mc_make_sid_security_cfg(name) \ + { \ + .reg = TEGRA_MC_STREAMID_BASE + MC_STREAMID_SECURITY_CFG_ ## name, \ + .val = 0x00000000, \ + } + +#define smmu_make_gnsr0_sec_cfg(name) \ + { \ + .reg = TEGRA_SMMU_BASE + SMMU_GNSR0_ ## name, \ + .val = 0x00000000, \ + } + +/* + * On ARM-SMMU, conditional offset to access secure aliases of non-secure registers + * is 0x400. So, add it to register address + */ +#define smmu_make_gnsr0_nsec_cfg(name) \ + { \ + .reg = TEGRA_SMMU_BASE + 0x400 + SMMU_GNSR0_ ## name, \ + .val = 0x00000000, \ + } + +#define smmu_make_gnsr0_smr_cfg(n) \ + { \ + .reg = TEGRA_SMMU_BASE + SMMU_GNSR0_SMR ## n, \ + .val = 0x00000000, \ + } + +#define smmu_make_gnsr0_s2cr_cfg(n) \ + { \ + .reg = TEGRA_SMMU_BASE + SMMU_GNSR0_S2CR ## n, \ + .val = 0x00000000, \ + } + +#define smmu_make_gnsr1_cbar_cfg(n) \ + { \ + .reg = TEGRA_SMMU_BASE + (1 << PGSHIFT) + SMMU_GNSR1_CBAR ## n, \ + .val = 0x00000000, \ + } + +#define smmu_make_gnsr1_cba2r_cfg(n) \ + { \ + .reg = TEGRA_SMMU_BASE + (1 << PGSHIFT) + SMMU_GNSR1_CBA2R ## n, \ + .val = 0x00000000, \ + } + +#define make_smmu_cb_cfg(name, n) \ + { \ + .reg = TEGRA_SMMU_BASE + (CB_SIZE >> 1) + (n * (1 << PGSHIFT)) \ + + SMMU_CBn_ ## name, \ + .val = 0x00000000, \ + } + +#define smmu_make_smrg_group(n) \ + smmu_make_gnsr0_smr_cfg(n), \ + smmu_make_gnsr0_s2cr_cfg(n), \ + smmu_make_gnsr1_cbar_cfg(n), \ + smmu_make_gnsr1_cba2r_cfg(n) /* don't put "," here. */ + +#define smmu_make_cb_group(n) \ + make_smmu_cb_cfg(SCTLR, n), \ + make_smmu_cb_cfg(TCR2, n), \ + make_smmu_cb_cfg(TTBR0_LO, n), \ + make_smmu_cb_cfg(TTBR0_HI, n), \ + make_smmu_cb_cfg(TCR, n), \ + make_smmu_cb_cfg(PRRR_MAIR0, n),\ + make_smmu_cb_cfg(FSR, n), \ + make_smmu_cb_cfg(FAR_LO, n), \ + make_smmu_cb_cfg(FAR_HI, n), \ + make_smmu_cb_cfg(FSYNR0, n) /* don't put "," here. */ + +#define smmu_bypass_cfg \ + { \ + .reg = TEGRA_MC_BASE + MC_SMMU_BYPASS_CONFIG, \ + .val = 0x00000000, \ + } + +#define _START_OF_TABLE_ \ + { \ + .reg = 0xCAFE05C7, \ + .val = 0x00000000, \ + } + +#define _END_OF_TABLE_ \ + { \ + .reg = 0xFFFFFFFF, \ + .val = 0xFFFFFFFF, \ + } + +static smmu_regs_t smmu_ctx_regs[] = { + _START_OF_TABLE_, + mc_make_sid_security_cfg(SCEW), + mc_make_sid_security_cfg(AFIR), + mc_make_sid_security_cfg(NVDISPLAYR1), + mc_make_sid_security_cfg(XUSB_DEVR), + mc_make_sid_security_cfg(VICSRD1), + mc_make_sid_security_cfg(NVENCSWR), + mc_make_sid_security_cfg(TSECSRDB), + mc_make_sid_security_cfg(AXISW), + mc_make_sid_security_cfg(SDMMCWAB), + mc_make_sid_security_cfg(AONDMAW), + mc_make_sid_security_cfg(GPUSWR2), + mc_make_sid_security_cfg(SATAW), + mc_make_sid_security_cfg(UFSHCW), + mc_make_sid_security_cfg(AFIW), + mc_make_sid_security_cfg(SDMMCR), + mc_make_sid_security_cfg(SCEDMAW), + mc_make_sid_security_cfg(UFSHCR), + mc_make_sid_security_cfg(SDMMCWAA), + mc_make_sid_security_cfg(APEDMAW), + mc_make_sid_security_cfg(SESWR), + mc_make_sid_security_cfg(MPCORER), + mc_make_sid_security_cfg(PTCR), + mc_make_sid_security_cfg(BPMPW), + mc_make_sid_security_cfg(ETRW), + mc_make_sid_security_cfg(GPUSRD), + mc_make_sid_security_cfg(VICSWR), + mc_make_sid_security_cfg(SCEDMAR), + mc_make_sid_security_cfg(HDAW), + mc_make_sid_security_cfg(ISPWA), + mc_make_sid_security_cfg(EQOSW), + mc_make_sid_security_cfg(XUSB_HOSTW), + mc_make_sid_security_cfg(TSECSWR), + mc_make_sid_security_cfg(SDMMCRAA), + mc_make_sid_security_cfg(APER), + mc_make_sid_security_cfg(VIW), + mc_make_sid_security_cfg(APEW), + mc_make_sid_security_cfg(AXISR), + mc_make_sid_security_cfg(SDMMCW), + mc_make_sid_security_cfg(BPMPDMAW), + mc_make_sid_security_cfg(ISPRA), + mc_make_sid_security_cfg(NVDECSWR), + mc_make_sid_security_cfg(XUSB_DEVW), + mc_make_sid_security_cfg(NVDECSRD), + mc_make_sid_security_cfg(MPCOREW), + mc_make_sid_security_cfg(NVDISPLAYR), + mc_make_sid_security_cfg(BPMPDMAR), + mc_make_sid_security_cfg(NVJPGSWR), + mc_make_sid_security_cfg(NVDECSRD1), + mc_make_sid_security_cfg(TSECSRD), + mc_make_sid_security_cfg(NVJPGSRD), + mc_make_sid_security_cfg(SDMMCWA), + mc_make_sid_security_cfg(SCER), + mc_make_sid_security_cfg(XUSB_HOSTR), + mc_make_sid_security_cfg(VICSRD), + mc_make_sid_security_cfg(AONDMAR), + mc_make_sid_security_cfg(AONW), + mc_make_sid_security_cfg(SDMMCRA), + mc_make_sid_security_cfg(HOST1XDMAR), + mc_make_sid_security_cfg(EQOSR), + mc_make_sid_security_cfg(SATAR), + mc_make_sid_security_cfg(BPMPR), + mc_make_sid_security_cfg(HDAR), + mc_make_sid_security_cfg(SDMMCRAB), + mc_make_sid_security_cfg(ETRR), + mc_make_sid_security_cfg(AONR), + mc_make_sid_security_cfg(APEDMAR), + mc_make_sid_security_cfg(SESRD), + mc_make_sid_security_cfg(NVENCSRD), + mc_make_sid_security_cfg(GPUSWR), + mc_make_sid_security_cfg(TSECSWRB), + mc_make_sid_security_cfg(ISPWB), + mc_make_sid_security_cfg(GPUSRD2), + mc_make_sid_override_cfg(APER), + mc_make_sid_override_cfg(VICSRD), + mc_make_sid_override_cfg(NVENCSRD), + mc_make_sid_override_cfg(NVJPGSWR), + mc_make_sid_override_cfg(AONW), + mc_make_sid_override_cfg(BPMPR), + mc_make_sid_override_cfg(BPMPW), + mc_make_sid_override_cfg(HDAW), + mc_make_sid_override_cfg(NVDISPLAYR1), + mc_make_sid_override_cfg(APEDMAR), + mc_make_sid_override_cfg(AFIR), + mc_make_sid_override_cfg(AXISR), + mc_make_sid_override_cfg(VICSRD1), + mc_make_sid_override_cfg(TSECSRD), + mc_make_sid_override_cfg(BPMPDMAW), + mc_make_sid_override_cfg(MPCOREW), + mc_make_sid_override_cfg(XUSB_HOSTR), + mc_make_sid_override_cfg(GPUSWR), + mc_make_sid_override_cfg(XUSB_DEVR), + mc_make_sid_override_cfg(UFSHCW), + mc_make_sid_override_cfg(XUSB_HOSTW), + mc_make_sid_override_cfg(SDMMCWAB), + mc_make_sid_override_cfg(SATAW), + mc_make_sid_override_cfg(SCEDMAR), + mc_make_sid_override_cfg(HOST1XDMAR), + mc_make_sid_override_cfg(SDMMCWA), + mc_make_sid_override_cfg(APEDMAW), + mc_make_sid_override_cfg(SESWR), + mc_make_sid_override_cfg(AXISW), + mc_make_sid_override_cfg(AONDMAW), + mc_make_sid_override_cfg(TSECSWRB), + mc_make_sid_override_cfg(MPCORER), + mc_make_sid_override_cfg(ISPWB), + mc_make_sid_override_cfg(AONR), + mc_make_sid_override_cfg(BPMPDMAR), + mc_make_sid_override_cfg(HDAR), + mc_make_sid_override_cfg(SDMMCRA), + mc_make_sid_override_cfg(ETRW), + mc_make_sid_override_cfg(GPUSWR2), + mc_make_sid_override_cfg(EQOSR), + mc_make_sid_override_cfg(TSECSWR), + mc_make_sid_override_cfg(ETRR), + mc_make_sid_override_cfg(NVDECSRD), + mc_make_sid_override_cfg(TSECSRDB), + mc_make_sid_override_cfg(SDMMCRAA), + mc_make_sid_override_cfg(NVDECSRD1), + mc_make_sid_override_cfg(SDMMCR), + mc_make_sid_override_cfg(NVJPGSRD), + mc_make_sid_override_cfg(SCEDMAW), + mc_make_sid_override_cfg(SDMMCWAA), + mc_make_sid_override_cfg(APEW), + mc_make_sid_override_cfg(AONDMAR), + mc_make_sid_override_cfg(PTCR), + mc_make_sid_override_cfg(SCER), + mc_make_sid_override_cfg(ISPRA), + mc_make_sid_override_cfg(ISPWA), + mc_make_sid_override_cfg(VICSWR), + mc_make_sid_override_cfg(SESRD), + mc_make_sid_override_cfg(SDMMCW), + mc_make_sid_override_cfg(SDMMCRAB), + mc_make_sid_override_cfg(EQOSW), + mc_make_sid_override_cfg(GPUSRD2), + mc_make_sid_override_cfg(SCEW), + mc_make_sid_override_cfg(GPUSRD), + mc_make_sid_override_cfg(NVDECSWR), + mc_make_sid_override_cfg(XUSB_DEVW), + mc_make_sid_override_cfg(SATAR), + mc_make_sid_override_cfg(NVDISPLAYR), + mc_make_sid_override_cfg(VIW), + mc_make_sid_override_cfg(UFSHCR), + mc_make_sid_override_cfg(NVENCSWR), + mc_make_sid_override_cfg(AFIW), + smmu_make_gnsr0_nsec_cfg(CR0), + smmu_make_gnsr0_sec_cfg(IDR0), + smmu_make_gnsr0_sec_cfg(IDR1), + smmu_make_gnsr0_sec_cfg(IDR2), + smmu_make_gnsr0_nsec_cfg(GFSR), + smmu_make_gnsr0_nsec_cfg(GFSYNR0), + smmu_make_gnsr0_nsec_cfg(GFSYNR1), + smmu_make_gnsr0_nsec_cfg(TLBGSTATUS), + smmu_make_gnsr0_nsec_cfg(PIDR2), + smmu_make_smrg_group(0), + smmu_make_smrg_group(1), + smmu_make_smrg_group(2), + smmu_make_smrg_group(3), + smmu_make_smrg_group(4), + smmu_make_smrg_group(5), + smmu_make_smrg_group(6), + smmu_make_smrg_group(7), + smmu_make_smrg_group(8), + smmu_make_smrg_group(9), + smmu_make_smrg_group(10), + smmu_make_smrg_group(11), + smmu_make_smrg_group(12), + smmu_make_smrg_group(13), + smmu_make_smrg_group(14), + smmu_make_smrg_group(15), + smmu_make_smrg_group(16), + smmu_make_smrg_group(17), + smmu_make_smrg_group(18), + smmu_make_smrg_group(19), + smmu_make_smrg_group(20), + smmu_make_smrg_group(21), + smmu_make_smrg_group(22), + smmu_make_smrg_group(23), + smmu_make_smrg_group(24), + smmu_make_smrg_group(25), + smmu_make_smrg_group(26), + smmu_make_smrg_group(27), + smmu_make_smrg_group(28), + smmu_make_smrg_group(29), + smmu_make_smrg_group(30), + smmu_make_smrg_group(31), + smmu_make_smrg_group(32), + smmu_make_smrg_group(33), + smmu_make_smrg_group(34), + smmu_make_smrg_group(35), + smmu_make_smrg_group(36), + smmu_make_smrg_group(37), + smmu_make_smrg_group(38), + smmu_make_smrg_group(39), + smmu_make_smrg_group(40), + smmu_make_smrg_group(41), + smmu_make_smrg_group(42), + smmu_make_smrg_group(43), + smmu_make_smrg_group(44), + smmu_make_smrg_group(45), + smmu_make_smrg_group(46), + smmu_make_smrg_group(47), + smmu_make_smrg_group(48), + smmu_make_smrg_group(49), + smmu_make_smrg_group(50), + smmu_make_smrg_group(51), + smmu_make_smrg_group(52), + smmu_make_smrg_group(53), + smmu_make_smrg_group(54), + smmu_make_smrg_group(55), + smmu_make_smrg_group(56), + smmu_make_smrg_group(57), + smmu_make_smrg_group(58), + smmu_make_smrg_group(59), + smmu_make_smrg_group(60), + smmu_make_smrg_group(61), + smmu_make_smrg_group(62), + smmu_make_smrg_group(63), + smmu_make_cb_group(0), + smmu_make_cb_group(1), + smmu_make_cb_group(2), + smmu_make_cb_group(3), + smmu_make_cb_group(4), + smmu_make_cb_group(5), + smmu_make_cb_group(6), + smmu_make_cb_group(7), + smmu_make_cb_group(8), + smmu_make_cb_group(9), + smmu_make_cb_group(10), + smmu_make_cb_group(11), + smmu_make_cb_group(12), + smmu_make_cb_group(13), + smmu_make_cb_group(14), + smmu_make_cb_group(15), + smmu_make_cb_group(16), + smmu_make_cb_group(17), + smmu_make_cb_group(18), + smmu_make_cb_group(19), + smmu_make_cb_group(20), + smmu_make_cb_group(21), + smmu_make_cb_group(22), + smmu_make_cb_group(23), + smmu_make_cb_group(24), + smmu_make_cb_group(25), + smmu_make_cb_group(26), + smmu_make_cb_group(27), + smmu_make_cb_group(28), + smmu_make_cb_group(29), + smmu_make_cb_group(30), + smmu_make_cb_group(31), + smmu_make_cb_group(32), + smmu_make_cb_group(33), + smmu_make_cb_group(34), + smmu_make_cb_group(35), + smmu_make_cb_group(36), + smmu_make_cb_group(37), + smmu_make_cb_group(38), + smmu_make_cb_group(39), + smmu_make_cb_group(40), + smmu_make_cb_group(41), + smmu_make_cb_group(42), + smmu_make_cb_group(43), + smmu_make_cb_group(44), + smmu_make_cb_group(45), + smmu_make_cb_group(46), + smmu_make_cb_group(47), + smmu_make_cb_group(48), + smmu_make_cb_group(49), + smmu_make_cb_group(50), + smmu_make_cb_group(51), + smmu_make_cb_group(52), + smmu_make_cb_group(53), + smmu_make_cb_group(54), + smmu_make_cb_group(55), + smmu_make_cb_group(56), + smmu_make_cb_group(57), + smmu_make_cb_group(58), + smmu_make_cb_group(59), + smmu_make_cb_group(60), + smmu_make_cb_group(61), + smmu_make_cb_group(62), + smmu_make_cb_group(63), + smmu_bypass_cfg, /* TBU settings */ + _END_OF_TABLE_, +}; + +/* + * Save SMMU settings before "System Suspend" + */ +void tegra_smmu_save_context(void) +{ + uint32_t i; +#if DEBUG + uint32_t reg_id1, pgshift, cb_size; + + /* sanity check SMMU settings c*/ + reg_id1 = mmio_read_32((TEGRA_SMMU_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)); + + assert(!((pgshift != PGSHIFT) || (cb_size != CB_SIZE))); +#endif + + /* index of _END_OF_TABLE_ */ + smmu_ctx_regs[0].val = ARRAY_SIZE(smmu_ctx_regs) - 1; + + /* save SMMU register values */ + for (i = 1; i < ARRAY_SIZE(smmu_ctx_regs) - 1; i++) + smmu_ctx_regs[i].val = mmio_read_32(smmu_ctx_regs[i].reg); + + /* save the SMMU table address */ + mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV11_LO, + (uint32_t)(unsigned long)smmu_ctx_regs); + mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV11_HI, + (uint32_t)(((unsigned long)smmu_ctx_regs) >> 32)); +} + +/* + * Init SMMU during boot or "System Suspend" exit + */ +void tegra_smmu_init(void) +{ + uint32_t val; + + /* Program the SMMU pagesize */ + val = tegra_smmu_read_32(SMMU_GSR0_SECURE_ACR); + val |= SMMU_GSR0_PGSIZE_64K; + tegra_smmu_write_32(SMMU_GSR0_SECURE_ACR, val); +} diff --git a/plat/nvidia/tegra/soc/t186/platform_t186.mk b/plat/nvidia/tegra/soc/t186/platform_t186.mk index 777f2db21..272074c55 100644 --- a/plat/nvidia/tegra/soc/t186/platform_t186.mk +++ b/plat/nvidia/tegra/soc/t186/platform_t186.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: @@ -58,6 +58,7 @@ BL31_SOURCES += lib/cpus/aarch64/denver.S \ ${SOC_DIR}/drivers/mce/ari.c \ ${SOC_DIR}/drivers/mce/nvg.c \ ${SOC_DIR}/drivers/mce/aarch64/nvg_helpers.S \ + ${SOC_DIR}/drivers/smmu/smmu.c \ ${SOC_DIR}/plat_psci_handlers.c \ ${SOC_DIR}/plat_setup.c \ ${SOC_DIR}/plat_secondary.c \ From ea96ac175e1778d1abedf3bed4e5606c8734e572 Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Thu, 3 Mar 2016 13:22:39 -0800 Subject: [PATCH 25/26] Tegra186: memctrl_v2: restore video memory settings The memory controller loses its settings when the device enters system suspend state. This patch adds a handler to restore the Video Memory settings in the memory controller, which would be called after exiting the system suspend state. Change-Id: I1ac12426d7290ac1452983d3c9e05fabbf3327fa Signed-off-by: Varun Wadekar --- .../tegra/common/drivers/memctrl/memctrl_v2.c | 13 +++++++++---- plat/nvidia/tegra/include/drivers/memctrl_v2.h | 18 ------------------ 2 files changed, 9 insertions(+), 22 deletions(-) diff --git a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c index 4d8d307cf..e11b8adac 100644 --- a/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c +++ b/plat/nvidia/tegra/common/drivers/memctrl/memctrl_v2.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -234,7 +235,7 @@ const static mc_txn_override_cfg_t mc_override_cfgs[] = { }; /* - * Init SMMU. + * Init Memory controller during boot. */ void tegra_memctrl_setup(void) { @@ -248,9 +249,7 @@ void tegra_memctrl_setup(void) INFO("Tegra Memory Controller (v2)\n"); /* Program the SMMU pagesize */ - val = tegra_smmu_read_32(ARM_SMMU_GSR0_SECURE_ACR); - val |= ARM_SMMU_GSR0_PGSIZE_64K; - tegra_smmu_write_32(ARM_SMMU_GSR0_SECURE_ACR, val); + tegra_smmu_init(); /* Program all the Stream ID overrides */ for (i = 0; i < num_overrides; i++) @@ -316,7 +315,13 @@ void tegra_memctrl_setup(void) } } +} +/* + * Restore Memory Controller settings after "System Suspend" + */ +void tegra_memctrl_restore_settings(void) +{ /* video memory carveout region */ if (video_mem_base) { tegra_mc_write_32(MC_VIDEO_PROTECT_BASE_LO, diff --git a/plat/nvidia/tegra/include/drivers/memctrl_v2.h b/plat/nvidia/tegra/include/drivers/memctrl_v2.h index c1061fec7..9623e25f8 100644 --- a/plat/nvidia/tegra/include/drivers/memctrl_v2.h +++ b/plat/nvidia/tegra/include/drivers/memctrl_v2.h @@ -308,14 +308,6 @@ typedef struct mc_txn_override_cfg { .cgid_tag = MC_TXN_OVERRIDE_ ## val \ } -/******************************************************************************* - * Memory Controller SMMU Global Secure Aux. Configuration Register - ******************************************************************************/ -#define ARM_SMMU_GSR0_SECURE_ACR 0x10 -#define ARM_SMMU_GSR0_PGSIZE_SHIFT 16 -#define ARM_SMMU_GSR0_PGSIZE_4K (0 << ARM_SMMU_GSR0_PGSIZE_SHIFT) -#define ARM_SMMU_GSR0_PGSIZE_64K (1 << ARM_SMMU_GSR0_PGSIZE_SHIFT) - /******************************************************************************* * Structure to hold the Stream ID to use to override client inputs ******************************************************************************/ @@ -396,14 +388,4 @@ static inline void tegra_mc_streamid_write_32(uint32_t off, uint32_t val) mmio_write_32(TEGRA_MC_STREAMID_BASE + off, val); } -static inline uint32_t tegra_smmu_read_32(uint32_t off) -{ - return mmio_read_32(TEGRA_SMMU_BASE + off); -} - -static inline void tegra_smmu_write_32(uint32_t off, uint32_t val) -{ - mmio_write_32(TEGRA_SMMU_BASE + off, val); -} - #endif /* __MEMCTRLV2_H__ */ From 50402b17b84fff4d006b2b1150f0217d943cd5e3 Mon Sep 17 00:00:00 2001 From: Varun Wadekar Date: Thu, 3 Mar 2016 13:52:52 -0800 Subject: [PATCH 26/26] Tegra186: implement support for System Suspend This patch adds the chip level support for System Suspend entry and exit. As part of the entry sequence we first query the MCE firmware to check if it is safe to enter system suspend. Once we get a green light, we save hardware block settings and enter the power state. As expected, all the hardware settings are restored once we exit the power state. Change-Id: I6d192d7568d6a555eb10efdfd45f6d79c20f74ea Signed-off-by: Varun Wadekar --- plat/nvidia/tegra/include/t186/tegra_def.h | 14 ++++ plat/nvidia/tegra/soc/t186/drivers/mce/mce.c | 1 - .../tegra/soc/t186/plat_psci_handlers.c | 73 ++++++++++++++++++- plat/nvidia/tegra/soc/t186/plat_setup.c | 12 ++- plat/nvidia/tegra/soc/t186/platform_t186.mk | 4 +- 5 files changed, 98 insertions(+), 6 deletions(-) diff --git a/plat/nvidia/tegra/include/t186/tegra_def.h b/plat/nvidia/tegra/include/t186/tegra_def.h index 0732993d9..f3fbb891e 100644 --- a/plat/nvidia/tegra/include/t186/tegra_def.h +++ b/plat/nvidia/tegra/include/t186/tegra_def.h @@ -81,6 +81,7 @@ #define HARDWARE_MINOR_REVISION_MASK 0xf0000 #define HARDWARE_MINOR_REVISION_SHIFT 0x10 #define HARDWARE_REVISION_A01 1 +#define MISCREG_PFCFG 0x200C /******************************************************************************* * Tegra Memory Controller constants @@ -105,6 +106,16 @@ #define TEGRA_GICD_BASE 0x03881000 #define TEGRA_GICC_BASE 0x03882000 +/******************************************************************************* + * Security Engine related constants + ******************************************************************************/ +#define TEGRA_SE0_BASE 0x03AC0000 +#define SE_MUTEX_WATCHDOG_NS_LIMIT 0x6C +#define TEGRA_PKA1_BASE 0x03AD0000 +#define PKA_MUTEX_WATCHDOG_NS_LIMIT 0x8144 +#define TEGRA_RNG1_BASE 0x03AE0000 +#define RNG_MUTEX_WATCHDOG_NS_LIMIT 0xFE0 + /******************************************************************************* * Tegra Clock and Reset Controller constants ******************************************************************************/ @@ -124,6 +135,9 @@ * Tegra scratch registers constants ******************************************************************************/ #define TEGRA_SCRATCH_BASE 0x0C390000 +#define SECURE_SCRATCH_RSV6 0x680 +#define SECURE_SCRATCH_RSV11_LO 0x6A8 +#define SECURE_SCRATCH_RSV11_HI 0x6AC /******************************************************************************* * Tegra Memory Mapped Control Register Access Bus constants diff --git a/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c b/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c index 981510708..745b6f4e5 100644 --- a/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c +++ b/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c @@ -262,7 +262,6 @@ int mce_command_handler(mce_cmd_t cmd, uint64_t arg0, uint64_t arg1, /* update context to return SC7 status value */ write_ctx_reg(gp_regs, CTX_GPREG_X1, ret); write_ctx_reg(gp_regs, CTX_GPREG_X3, ret); - ret = 0; break; diff --git a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c index 20c0f4c12..7e35cc6b2 100644 --- a/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c +++ b/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -48,7 +49,10 @@ extern void prepare_cpu_pwr_dwn(void); /* constants to get power state's wake time */ #define TEGRA186_WAKE_TIME_MASK 0xFFFFFF #define TEGRA186_WAKE_TIME_SHIFT 4 +/* context size to save during system suspend */ +#define TEGRA186_SE_CONTEXT_SIZE 3 +static uint32_t se_regs[TEGRA186_SE_CONTEXT_SIZE]; static unsigned int wake_time[PLATFORM_CORE_COUNT]; /* System power down state */ @@ -89,9 +93,15 @@ int32_t tegra_soc_validate_power_state(unsigned int power_state, int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state) { const plat_local_state_t *pwr_domain_state; - unsigned int stateid_afflvl0; + unsigned int stateid_afflvl0, stateid_afflvl2; int cpu = read_mpidr() & MPIDR_CPU_MASK; int impl = (read_midr() >> MIDR_IMPL_SHIFT) & MIDR_IMPL_MASK; + cpu_context_t *ctx = cm_get_context(NON_SECURE); + gp_regs_t *gp_regs = get_gpregs_ctx(ctx); + uint32_t val; + + assert(ctx); + assert(gp_regs); if (impl == DENVER_IMPL) cpu |= 0x4; @@ -100,6 +110,8 @@ int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state) pwr_domain_state = target_state->pwr_domain_state; stateid_afflvl0 = pwr_domain_state[MPIDR_AFFLVL0] & TEGRA186_STATE_ID_MASK; + stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] & + TEGRA186_STATE_ID_MASK; if (stateid_afflvl0 == PSTATE_ID_CORE_IDLE) { @@ -113,6 +125,42 @@ int tegra_soc_pwr_domain_suspend(const psci_power_state_t *target_state) (void)mce_command_handler(MCE_CMD_ENTER_CSTATE, TEGRA_ARI_CORE_C7, wake_time[cpu], 0); + } else if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) { + + /* loop until SC7 is allowed */ + do { + val = mce_command_handler(MCE_CMD_IS_SC7_ALLOWED, + TEGRA_ARI_CORE_C7, + MCE_CORE_SLEEP_TIME_INFINITE, + 0); + } while (val == 0); + + /* save SE registers */ + se_regs[0] = mmio_read_32(TEGRA_SE0_BASE + + SE_MUTEX_WATCHDOG_NS_LIMIT); + se_regs[1] = mmio_read_32(TEGRA_RNG1_BASE + + RNG_MUTEX_WATCHDOG_NS_LIMIT); + se_regs[2] = mmio_read_32(TEGRA_PKA1_BASE + + PKA_MUTEX_WATCHDOG_NS_LIMIT); + + /* save 'Secure Boot' Processor Feature Config Register */ + val = mmio_read_32(TEGRA_MISC_BASE + MISCREG_PFCFG); + mmio_write_32(TEGRA_SCRATCH_BASE + SECURE_SCRATCH_RSV6, val); + + /* save SMMU context */ + tegra_smmu_save_context(); + + /* Prepare for system suspend */ + write_ctx_reg(gp_regs, CTX_GPREG_X4, 1); + write_ctx_reg(gp_regs, CTX_GPREG_X5, 0); + write_ctx_reg(gp_regs, CTX_GPREG_X6, 1); + (void)mce_command_handler(MCE_CMD_UPDATE_CSTATE_INFO, + TEGRA_ARI_CLUSTER_CC7, 0, TEGRA_ARI_SYSTEM_SC7); + + /* Enter system suspend state */ + (void)mce_command_handler(MCE_CMD_ENTER_CSTATE, + TEGRA_ARI_CORE_C7, MCE_CORE_SLEEP_TIME_INFINITE, 0); + } else { ERROR("%s: Unknown state id\n", __func__); return PSCI_E_NOT_SUPPORTED; @@ -140,6 +188,29 @@ int tegra_soc_pwr_domain_on(u_register_t mpidr) return PSCI_E_SUCCESS; } +int tegra_soc_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + int state_id = target_state->pwr_domain_state[PLAT_MAX_PWR_LVL]; + + /* + * Check if we are exiting from deep sleep and restore SE + * context if we are. + */ + if (state_id == PSTATE_ID_SOC_POWERDN) { + mmio_write_32(TEGRA_SE0_BASE + SE_MUTEX_WATCHDOG_NS_LIMIT, + se_regs[0]); + mmio_write_32(TEGRA_RNG1_BASE + RNG_MUTEX_WATCHDOG_NS_LIMIT, + se_regs[1]); + mmio_write_32(TEGRA_PKA1_BASE + PKA_MUTEX_WATCHDOG_NS_LIMIT, + se_regs[2]); + + /* Init SMMU */ + tegra_smmu_init(); + } + + return PSCI_E_SUCCESS; +} + int tegra_soc_pwr_domain_off(const psci_power_state_t *target_state) { cpu_context_t *ctx = cm_get_context(NON_SECURE); diff --git a/plat/nvidia/tegra/soc/t186/plat_setup.c b/plat/nvidia/tegra/soc/t186/plat_setup.c index 44faefef0..d6b8bc3f8 100644 --- a/plat/nvidia/tegra/soc/t186/plat_setup.c +++ b/plat/nvidia/tegra/soc/t186/plat_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -73,13 +73,21 @@ static const mmap_region_t tegra_mmap[] = { MT_DEVICE | MT_RW | MT_SECURE), MAP_REGION_FLAT(TEGRA_GICD_BASE, 0x20000, /* 128KB */ MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_SE0_BASE, 0x10000, /* 64KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_PKA1_BASE, 0x10000, /* 64KB */ + MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_RNG1_BASE, 0x10000, /* 64KB */ + MT_DEVICE | MT_RW | MT_SECURE), MAP_REGION_FLAT(TEGRA_CAR_RESET_BASE, 0x10000, /* 64KB */ MT_DEVICE | MT_RW | MT_SECURE), MAP_REGION_FLAT(TEGRA_PMC_BASE, 0x40000, /* 256KB */ MT_DEVICE | MT_RW | MT_SECURE), + MAP_REGION_FLAT(TEGRA_SCRATCH_BASE, 0x10000, /* 64KB */ + MT_DEVICE | MT_RW | MT_SECURE), MAP_REGION_FLAT(TEGRA_MMCRAB_BASE, 0x60000, /* 384KB */ MT_DEVICE | MT_RW | MT_SECURE), - MAP_REGION_FLAT(TEGRA_SMMU_BASE, 0x10000, /* 64KB */ + MAP_REGION_FLAT(TEGRA_SMMU_BASE, 0x1000000, /* 64KB */ MT_DEVICE | MT_RW | MT_SECURE), {0} }; diff --git a/plat/nvidia/tegra/soc/t186/platform_t186.mk b/plat/nvidia/tegra/soc/t186/platform_t186.mk index 272074c55..adc4a9ee9 100644 --- a/plat/nvidia/tegra/soc/t186/platform_t186.mk +++ b/plat/nvidia/tegra/soc/t186/platform_t186.mk @@ -42,10 +42,10 @@ $(eval $(call add_define,PLATFORM_CLUSTER_COUNT)) PLATFORM_MAX_CPUS_PER_CLUSTER := 4 $(eval $(call add_define,PLATFORM_MAX_CPUS_PER_CLUSTER)) -MAX_XLAT_TABLES := 12 +MAX_XLAT_TABLES := 15 $(eval $(call add_define,MAX_XLAT_TABLES)) -MAX_MMAP_REGIONS := 12 +MAX_MMAP_REGIONS := 15 $(eval $(call add_define,MAX_MMAP_REGIONS)) # platform files