aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManish Pandey <manish.pandey2@arm.com>2020-06-09 14:39:45 +0000
committerTrustedFirmware Code Review <review@review.trustedfirmware.org>2020-06-09 14:39:45 +0000
commit87c9a5cc97c16f6c1c991fab334bfed4e4fce296 (patch)
treebf3c91e4eebda0e129be310642d0ebdaad9302ee
parent5861730b3d6333f936c2fcecaa034de0391cbd94 (diff)
parent00ed5a4b3b0ddfeb925708e3afb037cc89ebd816 (diff)
downloadtf-a-tests-87c9a5cc97c16f6c1c991fab334bfed4e4fce296.tar.gz
Merge changes from topic "tegra194-platform-support"
* changes: tests: arm_arch_svc: introduce support for NVIDIA Denver CPUs Tegra194: introduce per-CPU Hypervisor Timer Interrupt ID Tegra194: skip some timer framework validation tests Tegra194: introduce watchdog timer Tegra194: timers: increase the step value to 5ms Tegra194: create dummy SMMU context for system resume Tegra194: introduce system reset Tegra194: disable some system suspend test cases Tegra194: skip CPU suspend tests requiring SGI as wake source Tegra194: wake: introduce support for RTC as wake source Tegra194: pwr_mgmt: introduce power management support plat: nvidia: introduce platform port for Tegra194 drivers: ti: uart: introduce UART 16550 driver
-rw-r--r--drivers/ti/uart/aarch64/16550_console.S172
-rw-r--r--include/drivers/ti/uart/uart_16550.h72
-rw-r--r--plat/nvidia/drivers/spe/shared_console.S183
-rw-r--r--plat/nvidia/tegra194/helpers.S81
-rw-r--r--plat/nvidia/tegra194/include/platform_def.h176
-rw-r--r--plat/nvidia/tegra194/platform.mk38
-rw-r--r--plat/nvidia/tegra194/pwr_mgmt.c73
-rw-r--r--plat/nvidia/tegra194/pwr_state.c77
-rw-r--r--plat/nvidia/tegra194/reset.c18
-rw-r--r--plat/nvidia/tegra194/setup.c78
-rw-r--r--plat/nvidia/tegra194/tests.xml19
-rw-r--r--plat/nvidia/tegra194/tests_to_skip.txt24
-rw-r--r--plat/nvidia/tegra194/timers.c175
-rw-r--r--plat/nvidia/tegra194/topology.c60
-rw-r--r--plat/nvidia/tegra194/wake.c58
-rw-r--r--plat/nvidia/tegra194/watchdog.c92
-rw-r--r--tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_1.c17
17 files changed, 1413 insertions, 0 deletions
diff --git a/drivers/ti/uart/aarch64/16550_console.S b/drivers/ti/uart/aarch64/16550_console.S
new file mode 100644
index 000000000..616333a3b
--- /dev/null
+++ b/drivers/ti/uart/aarch64/16550_console.S
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <drivers/console.h>
+#include <drivers/ti/uart/uart_16550.h>
+
+ /*
+ * "core" functions are low-level implementations that don't require
+ * writable memory and are thus safe to call in BL1 crash context.
+ */
+ .globl console_init
+ .globl console_putc
+ .globl console_getc
+ .globl console_flush
+
+ /*
+ * The console base is in the data section and not in .bss
+ * even though it is zero-init. In particular, this allows
+ * the console functions to start using this variable before
+ * the runtime memory is initialized for images which do not
+ * need to copy the .data section from ROM to RAM.
+ */
+ .section .data.console_base
+ .align 3
+console_base:
+ .quad 0x0
+
+ /* -----------------------------------------------
+ * int console_init(uintptr_t base_addr,
+ * unsigned int uart_clk, unsigned int baud_rate)
+ * Function to initialize the console without a
+ * C Runtime to print debug information. This
+ * function will be accessed by console_init and
+ * crash reporting.
+ * In: x0 - console base address
+ * w1 - Uart clock in Hz
+ * w2 - Baud rate
+ * Out: return 1 on success, 0 on error
+ * Clobber list : x1, x2, x3
+ * -----------------------------------------------
+ */
+func console_init
+ /* Check the input base address */
+ cbz x0, init_fail
+ /* Check baud rate and uart clock for sanity */
+ cbz w1, init_fail
+ cbz w2, init_fail
+
+ adr x3, console_base
+ str x0, [x3]
+
+ /* Program the baudrate */
+ /* Divisor = Uart clock / (16 * baudrate) */
+ lsl w2, w2, #4
+ udiv w2, w1, w2
+ and w1, w2, #0xff /* w1 = DLL */
+ lsr w2, w2, #8
+ and w2, w2, #0xff /* w2 = DLLM */
+ ldr w3, [x0, #UARTLCR]
+ orr w3, w3, #UARTLCR_DLAB
+ str w3, [x0, #UARTLCR] /* enable DLL, DLLM programming */
+ str w1, [x0, #UARTDLL] /* program DLL */
+ str w2, [x0, #UARTDLLM] /* program DLLM */
+ mov w2, #~UARTLCR_DLAB
+ and w3, w3, w2
+ str w3, [x0, #UARTLCR] /* disable DLL, DLLM programming */
+
+ /* 8n1 */
+ mov w3, #3
+ str w3, [x0, #UARTLCR]
+ /* no interrupt */
+ mov w3, #0
+ str w3, [x0, #UARTIER]
+#ifdef TI_16550_MDR_QUIRK
+ /* UART must be enabled on some platforms via the MDR register */
+ str w3, [x0, #UARTMDR1]
+#endif /* TI_16550_MDR_QUIRK */
+ /* enable fifo, DMA */
+ mov w3, #(UARTFCR_FIFOEN | UARTFCR_DMAEN)
+ str w3, [x0, #UARTFCR]
+ /* DTR + RTS */
+ mov w3, #3
+ str w3, [x0, #UARTMCR]
+ mov w0, #1
+ ret
+init_fail:
+ mov w0, #0
+ ret
+endfunc console_init
+
+ /* --------------------------------------------------------
+ * int console_putc(int c)
+ * Function to output a character over the console. It
+ * returns the character printed on success or -1 on error.
+ * In : w0 - character to be printed
+ * Out : return -1 on error else return character.
+ * Clobber list : x1, x2
+ * --------------------------------------------------------
+ */
+func console_putc
+ adr x1, console_base
+ ldr x1, [x1]
+
+ /* Prepend '\r' to '\n' */
+ cmp w0, #0xA
+ b.ne 2f
+ /* Check if the transmit FIFO is full */
+1: ldr w2, [x1, #UARTLSR]
+ and w2, w2, #(UARTLSR_TEMT | UARTLSR_THRE)
+ cmp w2, #(UARTLSR_TEMT | UARTLSR_THRE)
+ b.ne 1b
+ mov w2, #0xD /* '\r' */
+ str w2, [x1, #UARTTX]
+
+ /* Check if the transmit FIFO is full */
+2: ldr w2, [x1, #UARTLSR]
+ and w2, w2, #(UARTLSR_TEMT | UARTLSR_THRE)
+ cmp w2, #(UARTLSR_TEMT | UARTLSR_THRE)
+ b.ne 2b
+ str w0, [x1, #UARTTX]
+ ret
+endfunc console_putc
+
+ /* ---------------------------------------------
+ * int console_getc(void)
+ * Function to get a character from the console.
+ * It returns the character grabbed on success
+ * or -1 on if no character is available.
+ * Out : w0 - character if available, else -1
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func console_getc
+ adr x0, console_base
+ ldr x0, [x0]
+
+ /* Check if the receive FIFO is empty */
+1: ldr w1, [x0, #UARTLSR]
+ tbz w1, #UARTLSR_RDR_BIT, no_char
+ ldr w0, [x0, #UARTRX]
+ ret
+no_char:
+ mov w0, #ERROR_NO_PENDING_CHAR
+ ret
+endfunc console_getc
+
+ /* ---------------------------------------------
+ * int console_16550_core_flush(uintptr_t base_addr)
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * Out : return -1 on error else return 0.
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func console_flush
+ adr x0, console_base
+ ldr x0, [x0]
+
+ /* Loop until the transmit FIFO is empty */
+1: ldr w1, [x0, #UARTLSR]
+ and w1, w1, #(UARTLSR_TEMT | UARTLSR_THRE)
+ cmp w1, #(UARTLSR_TEMT | UARTLSR_THRE)
+ b.ne 1b
+
+ mov w0, #0
+ ret
+endfunc console_flush
diff --git a/include/drivers/ti/uart/uart_16550.h b/include/drivers/ti/uart/uart_16550.h
new file mode 100644
index 000000000..b8c3fdb84
--- /dev/null
+++ b/include/drivers/ti/uart/uart_16550.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#ifndef UART_16550_H
+#define UART_16550_H
+
+/* UART16550 Registers */
+#define UARTTX 0x0
+#define UARTRX 0x0
+#define UARTDLL 0x0
+#define UARTIER 0x4
+#define UARTDLLM 0x4
+#define UARTIIR 0x8
+#define UARTFCR 0x8
+#define UARTLCR 0xc
+#define UARTMCR 0x10
+#define UARTLSR 0x14
+#define UARTMSR 0x18
+#define UARTSPR 0x1c
+#define UARTCSR 0x20
+/* Some instances have MDR1 defined as well */
+#define UARTMDR1 0x20
+#define UARTRXFIFOCFG 0x24
+#define UARTMIE 0x28
+#define UARTVNDR 0x2c
+#define UARTASR 0x3c
+
+/* FIFO Control Register bits */
+#define UARTFCR_FIFOMD_16450 (0 << 6)
+#define UARTFCR_FIFOMD_16550 (1 << 6)
+#define UARTFCR_RXTRIG_1 (0 << 6)
+#define UARTFCR_RXTRIG_4 (1 << 6)
+#define UARTFCR_RXTRIG_8 (2 << 6)
+#define UARTFCR_RXTRIG_16 (3 << 6)
+#define UARTFCR_TXTRIG_1 (0 << 4)
+#define UARTFCR_TXTRIG_4 (1 << 4)
+#define UARTFCR_TXTRIG_8 (2 << 4)
+#define UARTFCR_TXTRIG_16 (3 << 4)
+#define UARTFCR_DMAEN (1 << 3) /* Enable DMA mode */
+#define UARTFCR_TXCLR (1 << 2) /* Clear contents of Tx FIFO */
+#define UARTFCR_RXCLR (1 << 1) /* Clear contents of Rx FIFO */
+#define UARTFCR_FIFOEN (1 << 0) /* Enable the Tx/Rx FIFO */
+
+/* Line Control Register bits */
+#define UARTLCR_DLAB (1 << 7) /* Divisor Latch Access */
+#define UARTLCR_SETB (1 << 6) /* Set BREAK Condition */
+#define UARTLCR_SETP (1 << 5) /* Set Parity to LCR[4] */
+#define UARTLCR_EVEN (1 << 4) /* Even Parity Format */
+#define UARTLCR_PAR (1 << 3) /* Parity */
+#define UARTLCR_STOP (1 << 2) /* Stop Bit */
+#define UARTLCR_WORDSZ_5 0 /* Word Length of 5 */
+#define UARTLCR_WORDSZ_6 1 /* Word Length of 6 */
+#define UARTLCR_WORDSZ_7 2 /* Word Length of 7 */
+#define UARTLCR_WORDSZ_8 3 /* Word Length of 8 */
+
+/* Line Status Register bits */
+#define UARTLSR_RXFIFOEMT (1 << 9) /* Rx Fifo Empty */
+#define UARTLSR_TXFIFOFULL (1 << 8) /* Tx Fifo Full */
+#define UARTLSR_RXFIFOERR (1 << 7) /* Rx Fifo Error */
+#define UARTLSR_TEMT (1 << 6) /* Tx Shift Register Empty */
+#define UARTLSR_THRE (1 << 5) /* Tx Holding Register Empty */
+#define UARTLSR_BRK (1 << 4) /* Break Condition Detected */
+#define UARTLSR_FERR (1 << 3) /* Framing Error */
+#define UARTLSR_PERR (1 << 3) /* Parity Error */
+#define UARTLSR_OVRF (1 << 2) /* Rx Overrun Error */
+#define UARTLSR_RDR_BIT (0) /* Rx Data Ready Bit */
+#define UARTLSR_RDR (1 << UARTLSR_RDR_BIT) /* Rx Data Ready */
+
+#endif /* UART_16550_H */
diff --git a/plat/nvidia/drivers/spe/shared_console.S b/plat/nvidia/drivers/spe/shared_console.S
new file mode 100644
index 000000000..a8584ef83
--- /dev/null
+++ b/plat/nvidia/drivers/spe/shared_console.S
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <asm_macros.S>
+#include <drivers/console.h>
+
+#define CONSOLE_NUM_BYTES_SHIFT 24
+#define CONSOLE_FLUSH_DATA_TO_PORT (1 << 26)
+#define CONSOLE_RING_DOORBELL (1 << 31)
+#define CONSOLE_IS_BUSY (1 << 31)
+#define CONSOLE_TIMEOUT 0xC000 /* 50 ms */
+
+ /*
+ * This file contains a driver implementation to make use of the
+ * real console implementation provided by the SPE firmware running
+ * SoCs after Tegra186.
+ *
+ * This console is shared by multiple components and the SPE firmware
+ * finally displays everything on the UART port.
+ */
+
+ .globl console_init
+ .globl console_putc
+ .globl console_getc
+ .globl console_try_getc
+ .globl console_flush
+
+.macro check_if_console_is_ready base, tmp1, tmp2, label
+ /* wait until spe is ready or timeout expires */
+1: ldr \tmp1, [\base]
+ and \tmp1, \tmp1, #CONSOLE_IS_BUSY
+ cbnz \tmp1, 1b
+.endm
+
+ /*
+ * The console base is in the data section and not in .bss
+ * even though it is zero-init. In particular, this allows
+ * the console functions to start using this variable before
+ * the runtime memory is initialized for images which do not
+ * need to copy the .data section from ROM to RAM.
+ */
+ .section .data.console_base
+ .align 3
+console_base:
+ .quad 0x0
+
+ /* -----------------------------------------------
+ * int console_init(uintptr_t base_addr,
+ * unsigned int uart_clk,
+ * unsigned int baud_rate)
+ *
+ * Clobber list : x1 - x3
+ * -----------------------------------------------
+ */
+func console_init
+ /* Check the input base address */
+ cbz x0, register_fail
+
+ /* save base address */
+ adr x3, console_base
+ str x0, [x3]
+
+ /* Dont use clock or baud rate, so ok to overwrite them */
+ check_if_console_is_ready x0, x1, x2, register_fail
+
+register_fail:
+ mov w0, wzr
+ ret
+endfunc console_init
+
+ /* --------------------------------------------------------
+ * int console_spe_core_putc(int c, uintptr_t base_addr)
+ * Function to output a character over the console. It
+ * returns the character printed on success or -1 on error.
+ * In : w0 - character to be printed
+ * x1 - console base address
+ * Out : return -1 on error else return character.
+ * Clobber list : x2, x3
+ * --------------------------------------------------------
+ */
+func console_spe_core_putc
+ /* Check the input parameter */
+ cbz x1, putc_error
+
+ /* Prepend '\r' to '\n' */
+ cmp w0, #0xA
+ b.ne not_eol
+
+ check_if_console_is_ready x1, x2, x3, putc_error
+
+ /* spe is ready */
+ mov w2, #0xD /* '\r' */
+ and w2, w2, #0xFF
+ mov w3, #(CONSOLE_RING_DOORBELL | (1 << CONSOLE_NUM_BYTES_SHIFT))
+ orr w2, w2, w3
+ str w2, [x1]
+
+not_eol:
+ check_if_console_is_ready x1, x2, x3, putc_error
+
+ /* spe is ready */
+ mov w2, w0
+ and w2, w2, #0xFF
+ mov w3, #(CONSOLE_RING_DOORBELL | (1 << CONSOLE_NUM_BYTES_SHIFT))
+ orr w2, w2, w3
+ str w2, [x1]
+
+ ret
+putc_error:
+ mov w0, #-1
+ ret
+endfunc console_spe_core_putc
+
+ /* ---------------------------------------------
+ * int console_putc(int c)
+ *
+ * Clobber list : x1, x2
+ * ---------------------------------------------
+ */
+func console_putc
+ adr x1, console_base
+ ldr x1, [x1]
+ b console_spe_core_putc
+endfunc console_putc
+
+ /* ---------------------------------------------
+ * int console_getc(void)
+ *
+ * Clobber list : x0 - x3
+ * ---------------------------------------------
+ */
+func console_getc
+ mov w0, #-1
+ ret
+endfunc console_getc
+
+ /* ---------------------------------------------
+ * int console_try_getc(void)
+ *
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func console_try_getc
+ mov w0, #-1
+ ret
+endfunc console_try_getc
+
+ /* -------------------------------------------------
+ * int console_spe_core_flush(uintptr_t base_addr)
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * In : x0 - console base address
+ * Out : return -1 on error else return 0.
+ * Clobber list : x0, x1
+ * -------------------------------------------------
+ */
+func console_spe_core_flush
+ cbz x0, flush_error
+
+ /* flush console */
+ mov w1, #(CONSOLE_RING_DOORBELL | CONSOLE_FLUSH_DATA_TO_PORT)
+ str w1, [x0]
+ mov w0, #0
+ ret
+flush_error:
+ mov w0, #-1
+ ret
+endfunc console_spe_core_flush
+
+ /* ---------------------------------------------
+ * int console_flush(void)
+ *
+ * Clobber list : x0, x1
+ * ---------------------------------------------
+ */
+func console_flush
+ adr x0, console_base
+ ldr x0, [x0]
+ b console_spe_core_flush
+endfunc console_flush
diff --git a/plat/nvidia/tegra194/helpers.S b/plat/nvidia/tegra194/helpers.S
new file mode 100644
index 000000000..166913121
--- /dev/null
+++ b/plat/nvidia/tegra194/helpers.S
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2020, NVIDIA CORPORATION. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <asm_macros.S>
+#include <platform_def.h>
+
+ .globl platform_get_core_pos
+ .globl plat_crash_console_init
+ .globl plat_crash_console_putc
+ .globl plat_crash_console_flush
+
+ /*
+ * Return 0 to 3 for the Cortex-A53 cores and 4 to 5 for the Cortex-A57
+ * cores.
+ */
+func platform_get_core_pos
+ lsr x1, x0, #MPIDR_AFF0_SHIFT
+ and x1, x1, #MPIDR_AFFLVL_MASK /* core id */
+ lsr x2, x0, #MPIDR_AFF1_SHIFT
+ and x2, x2, #MPIDR_AFFLVL_MASK /* cluster id */
+
+ /* core_id >= PLATFORM_CORES_PER_CLUSTER */
+ mov x0, #-1
+ cmp x1, #(PLATFORM_CORES_PER_CLUSTER - 1)
+ b.gt 1f
+
+ /* cluster_id >= PLATFORM_CLUSTER_COUNT */
+ cmp x2, #(PLATFORM_CLUSTER_COUNT - 1)
+ b.gt 1f
+
+ /* CorePos = CoreId + (ClusterId * cpus per cluster) */
+ mov x3, #PLATFORM_CORES_PER_CLUSTER
+ mul x3, x3, x2
+ add x0, x1, x3
+
+1:
+ ret
+endfunc platform_get_core_pos
+
+ /* ---------------------------------------------
+ * int plat_crash_console_init(void)
+ * Function to initialize the crash console
+ * without a C Runtime to print crash report.
+ * Clobber list : x0 - x4
+ * ---------------------------------------------
+ */
+func plat_crash_console_init
+ mov_imm x0, TEGRA194_UARTC_BASE
+ mov_imm x1, TEGRA194_CONSOLE_CLKRATE
+ mov_imm x2, TEGRA194_CONSOLE_BAUDRATE
+ b console_init
+endfunc plat_crash_console_init
+
+ /* ---------------------------------------------
+ * int plat_crash_console_putc(int c)
+ * Function to print a character on the crash
+ * console without a C Runtime.
+ * Clobber list : x1, x2
+ * ---------------------------------------------
+ */
+func plat_crash_console_putc
+ mov_imm x1, TEGRA194_UARTC_BASE
+ b console_putc
+endfunc plat_crash_console_putc
+
+ /* ---------------------------------------------
+ * int plat_crash_console_flush()
+ * Function to force a write of all buffered
+ * data that hasn't been output.
+ * Out : return -1 on error else return 0.
+ * Clobber list : r0 - r1
+ * ---------------------------------------------
+ */
+func plat_crash_console_flush
+ mov_imm x1, TEGRA194_UARTC_BASE
+ b console_flush
+endfunc plat_crash_console_flush
diff --git a/plat/nvidia/tegra194/include/platform_def.h b/plat/nvidia/tegra194/include/platform_def.h
new file mode 100644
index 000000000..bdfd98f01
--- /dev/null
+++ b/plat/nvidia/tegra194/include/platform_def.h
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <utils_def.h>
+
+/*******************************************************************************
+ * Platform definitions used by common code
+ ******************************************************************************/
+
+#ifndef __PLATFORM_DEF_H__
+#define __PLATFORM_DEF_H__
+
+/*******************************************************************************
+ * Platform binary types for linking
+ ******************************************************************************/
+#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64"
+#define PLATFORM_LINKER_ARCH aarch64
+
+/*******************************************************************************
+ * Tegra DRAM memory base address
+ ******************************************************************************/
+#define DRAM_BASE U(0x80000000)
+#define DRAM_END U(0xB0000000)
+#define DRAM_SIZE (DRAM_END - DRAM_BASE)
+
+/*******************************************************************************
+ * Run-time address of the TFTF image.
+ * It has to match the location where the Trusted Firmware-A loads the BL33
+ * image.
+ ******************************************************************************/
+#define TFTF_BASE 0x80080000
+
+/*******************************************************************************
+ * Generic platform constants
+ ******************************************************************************/
+
+/* Translation table constants */
+#define MAX_XLAT_TABLES 20
+#define MAX_MMAP_REGIONS 20
+
+/* stack memory available to each CPU */
+#define PLATFORM_STACK_SIZE 0x1400
+#define PCPU_DV_MEM_STACK_SIZE 0x100
+
+/* total number of system nodes implemented by the platform */
+#define PLATFORM_SYSTEM_COUNT 1
+
+/* total number of clusters implemented by the platform */
+#define PLATFORM_CLUSTER_COUNT 4
+#define PLATFORM_CORES_PER_CLUSTER 2
+
+/* total number of CPUs implemented by the platform across all clusters */
+#define PLATFORM_CORE_COUNT (PLATFORM_CORES_PER_CLUSTER * \
+ PLATFORM_CLUSTER_COUNT)
+
+/* total number of nodes in the affinity hierarchy at all affinity levels */
+#define PLATFORM_NUM_AFFS (PLATFORM_SYSTEM_COUNT + \
+ PLATFORM_CLUSTER_COUNT + \
+ PLATFORM_CORE_COUNT)
+
+/*
+ * maximum number of affinity levels in the system that the platform
+ * implements
+ */
+#define PLATFORM_MAX_AFFLVL MPIDR_AFFLVL2
+#define PLAT_MAX_PWR_LEVEL PLATFORM_MAX_AFFLVL
+
+/*
+ * Defines the maximum number of power states at a power domain level for the
+ * platform.
+ */
+#define PLAT_MAX_PWR_STATES_PER_LVL 2
+
+/*
+ * Defines the offset of the last Shared Peripheral Interrupt supported by the
+ * TF-A Tests on this platform. SPI numbers are mapped onto GIC interrupt IDs,
+ * starting from interrupt ID 32. This offset ID corresponds to the last SPI
+ * number, to which 32 must be added to get the corresponding last GIC IRQ ID.
+ */
+#define PLAT_MAX_SPI_OFFSET_ID 415
+
+/* Local state bit width for each level in the state-ID field of power state */
+#define PLAT_LOCAL_PSTATE_WIDTH 4
+
+/*
+ * We want to run without support for non-volatile memory and hence using a
+ * portion of DRAM as workaround.
+ * The TFTF binary itself is loaded at 0xA0600000 so we have plenty of free
+ * memory at the beginning of the DRAM. Let's use 256MB from the start.
+ */
+#define TFTF_NVM_OFFSET 0x0FF80000
+#define TFTF_NVM_SIZE 0x10000000
+
+/*
+ * Times (in ms) used by test code for completion of different events.
+ * Suspend entry time for debug build is high due to the time taken
+ * by the VERBOSE/INFO prints. The value considers the worst case scenario
+ * where all CPUs are going and coming out of suspend continuously.
+ */
+#define PLAT_SUSPEND_ENTRY_TIME 500
+#define PLAT_SUSPEND_ENTRY_EXIT_TIME 1000
+
+/*******************************************************************************
+ * Non-Secure Software Generated Interupts IDs
+ ******************************************************************************/
+#define IRQ_NS_SGI_0 0
+#define IRQ_NS_SGI_1 1
+#define IRQ_NS_SGI_2 2
+#define IRQ_NS_SGI_3 3
+#define IRQ_NS_SGI_4 4
+#define IRQ_NS_SGI_5 5
+#define IRQ_NS_SGI_6 6
+#define IRQ_NS_SGI_7 7
+
+/*******************************************************************************
+ * Per-CPU Hypervisor Timer Interrupt ID
+ ******************************************************************************/
+#define IRQ_PCPU_HP_TIMER 26
+
+/*******************************************************************************
+ * Platform specific page table and MMU setup constants
+ ******************************************************************************/
+#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 40)
+#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 40)
+
+/*******************************************************************************
+ * Used to align variables on the biggest cache line size in the platform.
+ * This is known only to the platform as it might have a combination of
+ * integrated and external caches.
+ ******************************************************************************/
+#define CACHE_WRITEBACK_SHIFT 6
+#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT)
+
+/*******************************************************************************
+ * Platform console related constants
+ ******************************************************************************/
+#define TEGRA194_CONSOLE_BAUDRATE U(115200)
+#define TEGRA194_CONSOLE_CLKRATE U(408000000)
+
+/*******************************************************************************
+ * Platform MMIO devices
+ ******************************************************************************/
+#define TEGRA194_MC_BASE U(0x02C10000)
+#define TEGRA194_TMR0_BASE U(0x03020000)
+#define TEGRA194_WDT0_BASE U(0x030c0000)
+#define TEGRA194_GICD_BASE U(0x03881000)
+#define TEGRA194_GICC_BASE U(0x03882000)
+#define TEGRA194_SPE_BASE U(0x0C168000)
+#define TEGRA194_UARTC_BASE U(0x0C280000)
+#define TEGRA194_RTC_BASE U(0x0C2A0000)
+#define TEGRA194_TMRUS_BASE U(0x0C2E0000)
+#define SYS_CNT_BASE1 TEGRA194_TMRUS_BASE
+#define TEGRA194_AOWAKE_BASE U(0x0C370000)
+#define TEGRA194_SCRATCH_BASE U(0x0C390000)
+#define TEGRA194_SMMU0_BASE U(0x12000000)
+
+/*******************************************************************************
+ * DRAM carveout to save the SMMU context
+ ******************************************************************************/
+#define TEGRA194_SMMU_CTX_BASE (DRAM_END - 0x1000)
+
+#ifndef __ASSEMBLY__
+
+/*
+ * Platform functions
+ */
+void tegra194_pwr_mgmt_setup(void);
+void tegra194_set_rtc_as_wakeup_source(void);
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __PLATFORM_DEF_H__ */
diff --git a/plat/nvidia/tegra194/platform.mk b/plat/nvidia/tegra194/platform.mk
new file mode 100644
index 000000000..361e39836
--- /dev/null
+++ b/plat/nvidia/tegra194/platform.mk
@@ -0,0 +1,38 @@
+#
+# Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+PLAT_INCLUDES := -Iplat/nvidia/tegra194/include/
+
+PLAT_SOURCES := drivers/arm/gic/arm_gic_v2.c \
+ drivers/arm/gic/gic_common.c \
+ drivers/arm/gic/gic_v2.c \
+ drivers/arm/timer/private_timer.c \
+ drivers/ti/uart/aarch64/16550_console.S \
+ plat/nvidia/tegra194/helpers.S \
+ plat/nvidia/tegra194/pwr_state.c \
+ plat/nvidia/tegra194/pwr_mgmt.c \
+ plat/nvidia/tegra194/reset.c \
+ plat/nvidia/tegra194/setup.c \
+ plat/nvidia/tegra194/topology.c \
+ plat/nvidia/tegra194/timers.c \
+ plat/nvidia/tegra194/wake.c \
+ plat/nvidia/tegra194/watchdog.c
+
+PLAT_TESTS_SKIP_LIST := plat/nvidia/tegra194/tests_to_skip.txt
+
+TFTF_CFLAGS += -Wno-maybe-uninitialized
+
+ENABLE_ASSERTIONS := 1
+
+PLAT_SUPPORTS_NS_RESET := 1
+
+# Process PLAT_SUPPORTS_NS_RESET flag
+$(eval $(call assert_boolean,PLAT_SUPPORTS_NS_RESET))
+$(eval $(call add_define,TFTF_DEFINES,PLAT_SUPPORTS_NS_RESET))
+
+ifeq ($(USE_NVM),1)
+$(error "Tegra194 port of TFTF doesn't currently support USE_NVM=1")
+endif
diff --git a/plat/nvidia/tegra194/pwr_mgmt.c b/plat/nvidia/tegra194/pwr_mgmt.c
new file mode 100644
index 000000000..2f43f0b9c
--- /dev/null
+++ b/plat/nvidia/tegra194/pwr_mgmt.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <arch_helpers.h>
+#include <debug.h>
+#include <mmio.h>
+#include <platform.h>
+#include <stddef.h>
+
+#include <utils_def.h>
+
+/*******************************************************************************
+ * Secure Scratch 73 to save base address of SMMU register context
+ ******************************************************************************/
+#define SCRATCH_SECURE_RSV73_SCRATCH U(0x2ac)
+
+typedef struct mc_regs {
+ uint32_t reg;
+ uint32_t val;
+} mc_regs_t;
+
+#define mc_smmu_bypass_cfg \
+ { \
+ .reg = TEGRA194_SMMU0_BASE, \
+ .val = 0x00000000U, \
+ }
+
+#define START_OF_TABLE \
+ { \
+ .reg = 0xCAFE05C7U, \
+ .val = 0x00000000U, \
+ }
+
+#define END_OF_TABLE \
+ { \
+ .reg = 0xFFFFFFFFU, \
+ .val = 0xFFFFFFFFU, \
+ }
+
+/*******************************************************************************
+ * Array to hold MC context for Tegra194
+ ******************************************************************************/
+static __attribute__((aligned(16))) mc_regs_t tegra194_mc_context[] = {
+ START_OF_TABLE,
+ mc_smmu_bypass_cfg, /* TBU settings */
+ END_OF_TABLE,
+};
+
+void tegra194_pwr_mgmt_setup(void)
+{
+ uintptr_t smmu_ctx_base = (uintptr_t)TEGRA194_SMMU_CTX_BASE;
+
+ /* index of END_OF_TABLE */
+ tegra194_mc_context[0].val = ARRAY_SIZE(tegra194_mc_context) - 1U;
+
+ /* prepare dummy context */
+ for (int i = 1; i < ARRAY_SIZE(tegra194_mc_context) - 1U; i++) {
+ tegra194_mc_context[i].val = mmio_read_32(tegra194_mc_context[i].reg);
+ }
+
+ /* save context for the SC7-RF */
+ memcpy((void *)smmu_ctx_base, (void *)tegra194_mc_context,
+ sizeof(tegra194_mc_context));
+ flush_dcache_range(smmu_ctx_base, sizeof(tegra194_mc_context));
+
+ /* save SMMU context for SC7-RF to restore */
+ mmio_write_32(TEGRA194_SCRATCH_BASE + SCRATCH_SECURE_RSV73_SCRATCH,
+ smmu_ctx_base >> 12);
+}
diff --git a/plat/nvidia/tegra194/pwr_state.c b/plat/nvidia/tegra194/pwr_state.c
new file mode 100644
index 000000000..269b5d41c
--- /dev/null
+++ b/plat/nvidia/tegra194/pwr_state.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <stddef.h>
+
+#include <platform.h>
+#include <psci.h>
+#include <utils_def.h>
+
+/*
+ * State IDs for local power states
+ */
+#define TEGRA194_RUN_STATE_ID U(0) /* Valid for CPUs and Clusters */
+#define TEGRA194_CORE_RETN_STATE_ID U(6) /* Valid for only CPUs */
+#define TEGRA194_CORE_OFF_STATE_ID U(7) /* Valid for CPUs and Clusters */
+#define TEGRA194_SOC_OFF_STATE_ID U(2) /* Valid for the System */
+
+/*
+ * Suspend depth definitions for each power state
+ */
+typedef enum {
+ TEGRA194_RUN_DEPTH = 0,
+ TEGRA194_CORE_RETENTION_DEPTH,
+ TEGRA194_CORE_OFF_DEPTH,
+ TEGRA194_SYSTEM_OFF_DEPTH,
+} suspend_depth_t;
+
+/* The state property array with details of idle state possible for the core */
+static const plat_state_prop_t core_state_prop[] = {
+ {TEGRA194_CORE_RETENTION_DEPTH, TEGRA194_CORE_RETN_STATE_ID, PSTATE_TYPE_STANDBY},
+ {0},
+};
+
+/*
+ * The state property array with details of idle state possible
+ * for the cluster
+ */
+static const plat_state_prop_t cluster_state_prop[] = {
+ {TEGRA194_CORE_OFF_DEPTH, TEGRA194_CORE_RETN_STATE_ID, PSTATE_TYPE_STANDBY},
+ {0},
+};
+
+/*
+ * The state property array with details of idle state possible
+ * for the system. Currently Tegra194 does not support CPU SUSPEND
+ * at system power level.
+ */
+static const plat_state_prop_t system_state_prop[] = {
+ {TEGRA194_SYSTEM_OFF_DEPTH, TEGRA194_SOC_OFF_STATE_ID, PSTATE_TYPE_POWERDOWN},
+ {0},
+};
+
+/*
+ * This functions returns the plat_state_prop_t array for all the valid low
+ * power states from platform for a specified affinity level and returns NULL
+ * for an invalid affinity level. The array is expected to be NULL-terminated.
+ * This function is expected to be used by tests that need to compose the power
+ * state parameter for use in PSCI_CPU_SUSPEND API or PSCI_STAT/RESIDENCY
+ * API.
+ */
+const plat_state_prop_t *plat_get_state_prop(unsigned int level)
+{
+ switch (level) {
+ case MPIDR_AFFLVL0:
+ return core_state_prop;
+ case MPIDR_AFFLVL1:
+ return cluster_state_prop;
+ case MPIDR_AFFLVL2:
+ return system_state_prop;
+ default:
+ return NULL;
+ }
+}
diff --git a/plat/nvidia/tegra194/reset.c b/plat/nvidia/tegra194/reset.c
new file mode 100644
index 000000000..2112be428
--- /dev/null
+++ b/plat/nvidia/tegra194/reset.c
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <platform.h>
+
+#include <psci.h>
+#include <tftf.h>
+
+void tftf_plat_reset(void)
+{
+ smc_args reset_args = { SMC_PSCI_SYSTEM_RESET };
+
+ (void)tftf_smc(&reset_args);
+ bug_unreachable();
+}
diff --git a/plat/nvidia/tegra194/setup.c b/plat/nvidia/tegra194/setup.c
new file mode 100644
index 000000000..d420acd6b
--- /dev/null
+++ b/plat/nvidia/tegra194/setup.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <drivers/console.h>
+#include <drivers/arm/gic_common.h>
+#include <drivers/arm/gic_v2.h>
+#include <platform.h>
+#include <platform_def.h>
+
+#include <xlat_tables_v2.h>
+
+/*
+ * Memory map
+ */
+static const mmap_region_t tegra194_mmap[] = {
+ MAP_REGION_FLAT(TEGRA194_MC_BASE, 0x2000, /* 8KB */
+ MT_DEVICE | MT_RW | MT_NS),
+ MAP_REGION_FLAT(TEGRA194_TMR0_BASE, 0x1000, /* 4KB */
+ MT_DEVICE | MT_RW | MT_NS),
+ MAP_REGION_FLAT(TEGRA194_WDT0_BASE, 0x1000, /* 4KB */
+ MT_DEVICE | MT_RW | MT_NS),
+ MAP_REGION_FLAT(TEGRA194_GICD_BASE, 0x1000, /* 4KB */
+ MT_DEVICE | MT_RW | MT_NS),
+ MAP_REGION_FLAT(TEGRA194_GICC_BASE, 0x1000, /* 4KB */
+ MT_DEVICE | MT_RW | MT_NS),
+ MAP_REGION_FLAT(TEGRA194_UARTC_BASE, 0x20000U, /* 128KB */
+ MT_DEVICE | MT_RW | MT_NS),
+ MAP_REGION_FLAT(TEGRA194_RTC_BASE, 0x1000, /* 4KB */
+ MT_DEVICE | MT_RW | MT_NS),
+ MAP_REGION_FLAT(TEGRA194_TMRUS_BASE, 0x1000, /* 4KB */
+ MT_DEVICE | MT_RW | MT_NS),
+ MAP_REGION_FLAT(TEGRA194_AOWAKE_BASE, 0x1000, /* 4KB */
+ MT_DEVICE | MT_RW | MT_NS),
+ MAP_REGION_FLAT(TEGRA194_SCRATCH_BASE, 0x1000, /* 4KB */
+ MT_DEVICE | MT_RW | MT_NS),
+ MAP_REGION_FLAT(TEGRA194_SMMU0_BASE, 0x1000, /* 4KB */
+ MT_DEVICE | MT_RW | MT_NS),
+ MAP_REGION_FLAT(DRAM_BASE + TFTF_NVM_OFFSET, TFTF_NVM_SIZE,
+ MT_MEMORY | MT_RW | MT_NS),
+ MAP_REGION_FLAT(TEGRA194_SMMU_CTX_BASE, 0x1000, /* 4KB */
+ MT_MEMORY | MT_RW | MT_NS),
+ {0}
+};
+
+const mmap_region_t *tftf_platform_get_mmap(void)
+{
+ return tegra194_mmap;
+}
+
+void tftf_plat_arch_setup(void)
+{
+ tftf_plat_configure_mmu();
+}
+
+void tftf_early_platform_setup(void)
+{
+ /* Tegra194 platforms use UARTC as the console */
+ console_init(TEGRA194_UARTC_BASE, TEGRA194_CONSOLE_CLKRATE,
+ TEGRA194_CONSOLE_BAUDRATE);
+}
+
+void tftf_platform_setup(void)
+{
+ gicv2_init(TEGRA194_GICC_BASE, TEGRA194_GICD_BASE);
+ gicv2_setup_distif();
+ gicv2_probe_gic_cpu_id();
+ gicv2_setup_cpuif();
+
+ /* Setup power management dependencies */
+ tegra194_pwr_mgmt_setup();
+
+ /* Configure system suspend wake sources */
+ tegra194_set_rtc_as_wakeup_source();
+}
diff --git a/plat/nvidia/tegra194/tests.xml b/plat/nvidia/tegra194/tests.xml
new file mode 100644
index 000000000..03153f38d
--- /dev/null
+++ b/plat/nvidia/tegra194/tests.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<!--
+ Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+
+ SPDX-License-Identifier: BSD-3-Clause
+-->
+
+
+<!-- External references to all individual tests files. -->
+<!DOCTYPE testsuites [
+ <!ENTITY tests-tftf-validation SYSTEM "../../../tftf/tests/tests-tftf-validation.xml">
+]>
+
+<testsuites>
+
+ &tests-tftf-validation;
+
+</testsuites>
diff --git a/plat/nvidia/tegra194/tests_to_skip.txt b/plat/nvidia/tegra194/tests_to_skip.txt
new file mode 100644
index 000000000..a6a307865
--- /dev/null
+++ b/plat/nvidia/tegra194/tests_to_skip.txt
@@ -0,0 +1,24 @@
+#
+# Copyright (c) 2020, NVIDIA Coprporation. All rights reserved.
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+
+################################################################################
+# Disable the following tests from tests-psci.xml as a result
+################################################################################
+
+# Tegra194 platforms cannot be woken up from CPU_SUSPEND by an SGI
+PSCI Affinity Info/Affinity info level0 powerdown
+PSCI CPU Suspend/CPU suspend to standby at level 0
+PSCI CPU Suspend/CPU suspend to standby at level 1
+PSCI CPU Suspend/CPU suspend to standby at level 2
+PSCI System Suspend Validation/Suspend system with cores in suspend
+
+# Tegra194 platforms enter system suspend only from the boot core
+PSCI System Suspend Validation/system suspend from all cores
+
+# CPUs cannot be woken up with a timer interrupt after power off
+Timer framework Validation/Target timer to a power down cpu
+Timer framework Validation/Test scenario where multiple CPUs call same timeout
+Timer framework Validation/Stress test the timer framework
diff --git a/plat/nvidia/tegra194/timers.c b/plat/nvidia/tegra194/timers.c
new file mode 100644
index 000000000..39080dfc9
--- /dev/null
+++ b/plat/nvidia/tegra194/timers.c
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <assert.h>
+#include <stddef.h>
+
+#include <mmio.h>
+#include <platform.h>
+#include <timer.h>
+#include <tftf_lib.h>
+#include <utils_def.h>
+
+/* timer granularity in ms */
+#define TEGRA194_RTC_STEP_VALUE_MS U(5)
+
+/* IRQ value for Tegra194 Timer0 */
+#define TEGRA194_RTC_IRQ U(42)
+
+/* set to 1 = busy every eight 32kHz clocks during copy of sec+msec to AHB */
+#define TEGRA194_RTC_REG_BUSY U(0x004)
+#define TEGRA194_RTC_REG_SECONDS U(0x008)
+/* when msec is read, the seconds are buffered into shadow seconds. */
+#define TEGRA194_RTC_REG_SHADOW_SECONDS U(0x00c)
+#define TEGRA194_RTC_REG_MILLI_SECONDS U(0x010)
+#define TEGRA194_RTC_REG_SECONDS_ALARM0 U(0x014)
+#define TEGRA194_RTC_REG_SECONDS_ALARM1 U(0x018)
+#define TEGRA194_RTC_REG_MILLI_SECONDS_ALARM0 U(0x01c)
+#define TEGRA194_RTC_REG_MSEC_CDN_ALARM0 U(0x024)
+#define TEGRA194_RTC_REG_INTR_MASK U(0x028)
+/* write 1 bits to clear status bits */
+#define TEGRA194_RTC_REG_INTR_STATUS U(0x02c)
+
+/*
+ * bits in the TEGRA194_RTC_REG_BUSY register
+ * bit 0: 1 = busy, 0 = idle
+ */
+#define TEGRA194_RTC_REG_BUSY_BIT BIT_32(0)
+
+/* bits in INTR_MASK and INTR_STATUS */
+#define TEGRA194_RTC_INTR_MSEC_CDN_ALARM BIT_32(4)
+#define TEGRA194_RTC_INTR_SEC_CDN_ALARM BIT_32(3)
+#define TEGRA194_RTC_INTR_MSEC_ALARM BIT_32(2)
+#define TEGRA194_RTC_INTR_SEC_ALARM1 BIT_32(1)
+#define TEGRA194_RTC_INTR_SEC_ALARM0 BIT_32(0)
+
+static bool is_rtc_busy(void)
+{
+ uint32_t reg = mmio_read_32(TEGRA194_RTC_BASE + TEGRA194_RTC_REG_BUSY) &
+ TEGRA194_RTC_REG_BUSY_BIT;
+
+ /* 1 = busy, 0 = idle */
+ return (reg == 1);
+}
+
+/*
+ * Wait for hardware to be ready for writing.
+ * This function tries to maximize the amount of time before the next update.
+ * It does this by waiting for the RTC to become busy with its periodic update,
+ * then returning once the RTC first becomes not busy.
+ * This periodic update (where the seconds and milliseconds are copied to the
+ * AHB side) occurs every eight 32kHz clocks (~250uS).
+ * The behavior of this function allows us to make some assumptions without
+ * introducing a race, because 250uS is plenty of time to write a value.
+ */
+static void wait_until_idle(void)
+{
+ uint32_t retries = 500;
+
+ /* wait until idle */
+ while (is_rtc_busy() || (retries-- > 0)) {
+ waitus(1);
+ }
+}
+
+static void timer_idle_write_32(uint32_t offset, uint32_t val)
+{
+ /* wait until the RTC is idle first */
+ wait_until_idle();
+
+ /* actual write */
+ mmio_write_32(TEGRA194_RTC_BASE + offset, val);
+
+ /* wait until RTC has processed the write */
+ wait_until_idle();
+}
+
+static uint32_t timer_idle_read_32(uint32_t offset)
+{
+ /* wait until the RTC is idle first */
+ wait_until_idle();
+
+ /* actual read */
+ return mmio_read_32(TEGRA194_RTC_BASE + offset);
+}
+
+static int cancel_timer(void)
+{
+ /* read current values to clear them */
+ (void)timer_idle_read_32(TEGRA194_RTC_REG_MILLI_SECONDS);
+ (void)timer_idle_read_32(TEGRA194_RTC_REG_SHADOW_SECONDS);
+
+ /* clear the alarm */
+ timer_idle_write_32(TEGRA194_RTC_REG_MSEC_CDN_ALARM0, 0);
+ /* clear all status values */
+ timer_idle_write_32(TEGRA194_RTC_REG_INTR_STATUS, 0xffffffff);
+ /* disable all interrupts */
+ timer_idle_write_32(TEGRA194_RTC_REG_INTR_MASK, 0);
+
+ return 0;
+}
+
+static int program_timer(unsigned long time_out_ms)
+{
+ uint32_t reg;
+
+ /* set timer value */
+ reg = BIT_32(31) | (0x0fffffff & time_out_ms);
+ timer_idle_write_32(TEGRA194_RTC_REG_MSEC_CDN_ALARM0, reg);
+
+ /* enable timer interrupt */
+ timer_idle_write_32(TEGRA194_RTC_REG_INTR_MASK, TEGRA194_RTC_INTR_MSEC_ALARM);
+
+ /* program timeout value */
+ reg = timer_idle_read_32(TEGRA194_RTC_REG_MILLI_SECONDS);
+ timer_idle_write_32(TEGRA194_RTC_REG_MILLI_SECONDS_ALARM0, reg + time_out_ms);
+
+ return 0;
+}
+
+static int handler_timer(void)
+{
+ uint32_t __unused reg, status, mask;
+
+ /* disable timer interrupt */
+ reg = timer_idle_read_32(TEGRA194_RTC_REG_INTR_MASK);
+ reg &= ~TEGRA194_RTC_INTR_MSEC_CDN_ALARM;
+ timer_idle_write_32(TEGRA194_RTC_REG_INTR_MASK, reg);
+
+ /* read current values to clear them */
+ reg = timer_idle_read_32(TEGRA194_RTC_REG_MILLI_SECONDS);
+ reg = timer_idle_read_32(TEGRA194_RTC_REG_SHADOW_SECONDS);
+
+ /* clear interrupts */
+ status = timer_idle_read_32(TEGRA194_RTC_REG_INTR_STATUS);
+ mask = timer_idle_read_32(TEGRA194_RTC_REG_INTR_MASK);
+ mask &= ~status;
+ if (status) {
+ timer_idle_write_32(TEGRA194_RTC_REG_INTR_MASK, mask);
+ timer_idle_write_32(TEGRA194_RTC_REG_INTR_STATUS, status);
+ }
+
+ return 0;
+}
+
+static const plat_timer_t tegra194_timers = {
+ .program = program_timer,
+ .cancel = cancel_timer,
+ .handler = handler_timer,
+ .timer_step_value = TEGRA194_RTC_STEP_VALUE_MS,
+ .timer_irq = TEGRA194_RTC_IRQ
+};
+
+int plat_initialise_timer_ops(const plat_timer_t **timer_ops)
+{
+ assert(timer_ops != NULL);
+ *timer_ops = &tegra194_timers;
+
+ /* clear the timers */
+ cancel_timer();
+
+ return 0;
+}
diff --git a/plat/nvidia/tegra194/topology.c b/plat/nvidia/tegra194/topology.c
new file mode 100644
index 000000000..51ac26367
--- /dev/null
+++ b/plat/nvidia/tegra194/topology.c
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <assert.h>
+#include <stddef.h>
+
+#include <plat_topology.h>
+#include <platform_def.h>
+#include <tftf_lib.h>
+
+static const struct {
+ unsigned cluster_id;
+ unsigned cpu_id;
+} tegra194_cores[] = {
+ { 0, 0 },
+ { 0, 1 },
+ { 1, 0 },
+ { 1, 1 },
+ { 2, 0 },
+ { 2, 1 },
+ { 3, 0 },
+ { 3, 1 }
+};
+
+/*
+ * The Tegra194 power domain tree descriptor. Tegra194 implements a system
+ * power domain at the level 2. The first entry in the power domain descriptor
+ * specifies the number of power domains at the highest power level.
+ */
+static const unsigned char tegra194_power_domain_tree_desc[] = {
+ /* Number of root nodes */
+ PLATFORM_SYSTEM_COUNT,
+ /* Number of children of root node */
+ PLATFORM_CLUSTER_COUNT,
+ /* Number of children for the first cluster */
+ PLATFORM_CORES_PER_CLUSTER,
+ /* Number of children for the second cluster */
+ PLATFORM_CORES_PER_CLUSTER,
+ /* Number of children for the third cluster */
+ PLATFORM_CORES_PER_CLUSTER,
+ /* Number of children for the fourth cluster */
+ PLATFORM_CORES_PER_CLUSTER
+};
+
+const unsigned char *tftf_plat_get_pwr_domain_tree_desc(void)
+{
+ return tegra194_power_domain_tree_desc;
+}
+
+uint64_t tftf_plat_get_mpidr(unsigned int core_pos)
+{
+ assert(core_pos < PLATFORM_CORE_COUNT);
+
+ return make_mpid(tegra194_cores[core_pos].cluster_id,
+ tegra194_cores[core_pos].cpu_id);
+}
diff --git a/plat/nvidia/tegra194/wake.c b/plat/nvidia/tegra194/wake.c
new file mode 100644
index 000000000..d4bfbd6bd
--- /dev/null
+++ b/plat/nvidia/tegra194/wake.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <arch.h>
+#include <mmio.h>
+#include <platform.h>
+#include <stddef.h>
+
+#include <utils_def.h>
+
+#define WAKE_AOWAKE_RTC_ID U(73)
+#define WAKE_AOWAKE_CNTRL_73 U(0x124)
+#define WAKE_AOWAKE_MASK_W_73 U(0x2A4)
+#define WAKE_AOWAKE_STATUS_W_73 U(0x430)
+#define WAKE_AOWAKE_TIER2_CTRL_0 U(0x4B0)
+#define WAKE_AOWAKE_TIER2_ROUTING_31_0_0 U(0x4CC)
+#define WAKE_AOWAKE_TIER2_ROUTING_63_32_0 U(0x4D0)
+#define WAKE_AOWAKE_TIER2_ROUTING_95_64_0 U(0x4D4)
+
+
+#define WAKE_AOWAKE_TIER2_CTRL_0_INT_EN_TRUE BIT_32(0)
+#define WAKE_AOWAKE_CNTRL_73_COAL_EN_FIELD BIT_32(6)
+#define WAKE_AOWAKE_CNTRL_73_COAL_GRP_SEL_FIELD BIT_32(5)
+#define WAKE_AOWAKE_CNTRL_73_LEVEL_FIELD BIT_32(3)
+#define WAKE_AOWAKE_STATUS_W_73_CLEAR_FALSE U(0)
+#define WAKE_AOWAKE_MASK_W_73_MASK_UNMASK U(1)
+
+static inline void aowake_write_32(uint32_t offset, uint32_t value)
+{
+ mmio_write_32(TEGRA194_AOWAKE_BASE + offset, value);
+}
+
+void tegra194_set_rtc_as_wakeup_source(void)
+{
+ /*
+ * Configure RTC as the wake source to tier2 = CCPLEX,
+ * and disable others
+ */
+ aowake_write_32(WAKE_AOWAKE_TIER2_ROUTING_31_0_0, 0U);
+ aowake_write_32(WAKE_AOWAKE_TIER2_ROUTING_63_32_0, 0U);
+ aowake_write_32(WAKE_AOWAKE_TIER2_ROUTING_95_64_0,
+ BIT_32(WAKE_AOWAKE_RTC_ID - 64));
+
+ /* Enable the tier 2 wake up */
+ aowake_write_32(WAKE_AOWAKE_TIER2_CTRL_0, WAKE_AOWAKE_TIER2_CTRL_0_INT_EN_TRUE);
+
+ /* Configure the RTC wake up source as per the golden register value */
+ aowake_write_32(WAKE_AOWAKE_CNTRL_73, WAKE_AOWAKE_CNTRL_73_COAL_EN_FIELD |
+ WAKE_AOWAKE_CNTRL_73_COAL_GRP_SEL_FIELD |
+ WAKE_AOWAKE_CNTRL_73_LEVEL_FIELD);
+
+ /* Clear current wake status of RTC then enable it as a wake source */
+ aowake_write_32(WAKE_AOWAKE_STATUS_W_73, WAKE_AOWAKE_STATUS_W_73_CLEAR_FALSE);
+ aowake_write_32(WAKE_AOWAKE_MASK_W_73, WAKE_AOWAKE_MASK_W_73_MASK_UNMASK);
+}
diff --git a/plat/nvidia/tegra194/watchdog.c b/plat/nvidia/tegra194/watchdog.c
new file mode 100644
index 000000000..3773a3b6e
--- /dev/null
+++ b/plat/nvidia/tegra194/watchdog.c
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ */
+
+#include <debug.h>
+#include <mmio.h>
+#include <platform.h>
+
+/* Timer registers */
+#define TIMER_PTV U(0)
+ #define TIMER_EN_BIT BIT_32(31)
+ #define TIMER_PERIODIC_BIT BIT_32(30)
+#define TIMER_PCR U(0x4)
+ #define TIMER_PCR_INTR_BIT BIT_32(30)
+
+/* WDT registers */
+#define WDT_CFG U(0)
+ #define WDT_CFG_TMR_SRC U(0) /* for TMR0. */
+ #define WDT_CFG_PERIOD_BIT BIT_32(4)
+ #define WDT_CFG_INT_EN_BIT BIT_32(12)
+ #define WDT_CFG_SYS_RST_EN_BIT BIT_32(14)
+ #define WDT_CFG_PMC2CAR_RST_EN_BIT BIT_32(15)
+#define WDT_CMD U(8)
+ #define WDT_CMD_START_COUNTER_BIT BIT_32(0)
+ #define WDT_CMD_DISABLE_COUNTER_BIT BIT_32(1)
+#define WDT_UNLOCK U(0xC)
+ #define WDT_UNLOCK_PATTERN U(0xC45A)
+
+/* watchdog will fire after this timeout value is reached */
+#define WDT_TIMEOUT_SECONDS U(10)
+#define WDT_TIMEOUT_MULTIPLIER UL(125000)
+
+static inline void tegra194_wdt_write(uint32_t offset, uint32_t val)
+{
+ mmio_write_32(TEGRA194_WDT0_BASE + offset, val);
+}
+
+static inline uint32_t tegra194_wdt_read(uint32_t offset)
+{
+ return mmio_read_32(TEGRA194_WDT0_BASE + offset);
+}
+
+static inline void tegra194_tmr_write(uint32_t offset, uint32_t val)
+{
+ mmio_write_32(TEGRA194_TMR0_BASE + offset, val);
+}
+
+static inline uint32_t tegra194_tmr_read(uint32_t offset)
+{
+ return mmio_read_32(TEGRA194_TMR0_BASE + offset);
+}
+
+/*
+ * Start the watchdog timer
+ */
+void tftf_platform_watchdog_set(void)
+{
+ uint32_t val;
+
+ /* Clear pending interrupts first */
+ tegra194_tmr_write(TIMER_PCR, TIMER_PCR_INTR_BIT);
+
+ /*
+ * Normally, we would set the period to 1 second by writing 125000ul,
+ * but the watchdog system reset actually occurs on the 4th expiration
+ * of this counter, so we set the period to 1/4 of this amount.
+ */
+ val = (WDT_TIMEOUT_SECONDS * WDT_TIMEOUT_MULTIPLIER) / 4;
+ val |= (TIMER_EN_BIT | TIMER_PERIODIC_BIT);
+ tegra194_tmr_write(TIMER_PTV, val);
+
+ /*
+ * Set number of periods and start counter.
+ */
+ val = WDT_CFG_TMR_SRC | WDT_CFG_SYS_RST_EN_BIT |
+ WDT_CFG_PMC2CAR_RST_EN_BIT;
+ tegra194_wdt_write(WDT_CFG, val);
+ tegra194_wdt_write(WDT_CMD, WDT_CMD_START_COUNTER_BIT);
+}
+
+/*
+ * Stop the watchdog timer
+ */
+void tftf_platform_watchdog_reset(void)
+{
+ tegra194_tmr_write(TIMER_PCR, TIMER_PCR_INTR_BIT);
+ tegra194_wdt_write(WDT_UNLOCK, WDT_UNLOCK_PATTERN);
+ tegra194_wdt_write(WDT_CMD, WDT_CMD_DISABLE_COUNTER_BIT);
+ tegra194_tmr_write(TIMER_PTV, 0);
+}
diff --git a/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_1.c b/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_1.c
index e88f183f0..93abf1520 100644
--- a/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_1.c
+++ b/tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_1.c
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2020, NVIDIA Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
@@ -19,9 +20,15 @@
#define CORTEX_A72_MIDR 0x410FD080
#define CORTEX_A73_MIDR 0x410FD090
#define CORTEX_A75_MIDR 0x410FD0A0
+#define DENVER_MIDR_PN0 0x4E0F0000
+#define DENVER_MIDR_PN1 0x4E0F0010
+#define DENVER_MIDR_PN2 0x4E0F0020
+#define DENVER_MIDR_PN3 0x4E0F0030
+#define DENVER_MIDR_PN4 0x4E0F0040
static int cortex_a57_test(void);
static int csv2_test(void);
+static int denver_test(void);
static struct ent {
unsigned int midr;
@@ -31,6 +38,11 @@ static struct ent {
{ .midr = CORTEX_A72_MIDR, .wa_required = csv2_test },
{ .midr = CORTEX_A73_MIDR, .wa_required = csv2_test },
{ .midr = CORTEX_A75_MIDR, .wa_required = csv2_test },
+ { .midr = DENVER_MIDR_PN0, .wa_required = denver_test },
+ { .midr = DENVER_MIDR_PN1, .wa_required = denver_test },
+ { .midr = DENVER_MIDR_PN2, .wa_required = denver_test },
+ { .midr = DENVER_MIDR_PN3, .wa_required = denver_test },
+ { .midr = DENVER_MIDR_PN4, .wa_required = denver_test },
};
static int cortex_a57_test(void)
@@ -48,6 +60,11 @@ static int csv2_test(void)
return 1;
}
+static int denver_test(void)
+{
+ return 1;
+}
+
static test_result_t test_smccc_entrypoint(void)
{
smc_args args;