diff options
author | Manish Pandey <manish.pandey2@arm.com> | 2020-06-09 14:39:45 +0000 |
---|---|---|
committer | TrustedFirmware Code Review <review@review.trustedfirmware.org> | 2020-06-09 14:39:45 +0000 |
commit | 87c9a5cc97c16f6c1c991fab334bfed4e4fce296 (patch) | |
tree | bf3c91e4eebda0e129be310642d0ebdaad9302ee | |
parent | 5861730b3d6333f936c2fcecaa034de0391cbd94 (diff) | |
parent | 00ed5a4b3b0ddfeb925708e3afb037cc89ebd816 (diff) | |
download | tf-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.S | 172 | ||||
-rw-r--r-- | include/drivers/ti/uart/uart_16550.h | 72 | ||||
-rw-r--r-- | plat/nvidia/drivers/spe/shared_console.S | 183 | ||||
-rw-r--r-- | plat/nvidia/tegra194/helpers.S | 81 | ||||
-rw-r--r-- | plat/nvidia/tegra194/include/platform_def.h | 176 | ||||
-rw-r--r-- | plat/nvidia/tegra194/platform.mk | 38 | ||||
-rw-r--r-- | plat/nvidia/tegra194/pwr_mgmt.c | 73 | ||||
-rw-r--r-- | plat/nvidia/tegra194/pwr_state.c | 77 | ||||
-rw-r--r-- | plat/nvidia/tegra194/reset.c | 18 | ||||
-rw-r--r-- | plat/nvidia/tegra194/setup.c | 78 | ||||
-rw-r--r-- | plat/nvidia/tegra194/tests.xml | 19 | ||||
-rw-r--r-- | plat/nvidia/tegra194/tests_to_skip.txt | 24 | ||||
-rw-r--r-- | plat/nvidia/tegra194/timers.c | 175 | ||||
-rw-r--r-- | plat/nvidia/tegra194/topology.c | 60 | ||||
-rw-r--r-- | plat/nvidia/tegra194/wake.c | 58 | ||||
-rw-r--r-- | plat/nvidia/tegra194/watchdog.c | 92 | ||||
-rw-r--r-- | tftf/tests/runtime_services/arm_arch_svc/smccc_arch_workaround_1.c | 17 |
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; |