diff options
-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 | 150 | ||||
-rw-r--r-- | plat/nvidia/tegra194/platform.mk | 28 | ||||
-rw-r--r-- | plat/nvidia/tegra194/pwr_state.c | 77 | ||||
-rw-r--r-- | plat/nvidia/tegra194/setup.c | 65 | ||||
-rw-r--r-- | plat/nvidia/tegra194/tests.xml | 19 | ||||
-rw-r--r-- | plat/nvidia/tegra194/tests_to_skip.txt | 6 | ||||
-rw-r--r-- | plat/nvidia/tegra194/timers.c | 175 | ||||
-rw-r--r-- | plat/nvidia/tegra194/topology.c | 60 |
10 files changed, 844 insertions, 0 deletions
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..2ad63eb0e --- /dev/null +++ b/plat/nvidia/tegra194/include/platform_def.h @@ -0,0 +1,150 @@ +/* + * 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 + +/******************************************************************************* + * 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_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 + +#endif /* __PLATFORM_DEF_H__ */ diff --git a/plat/nvidia/tegra194/platform.mk b/plat/nvidia/tegra194/platform.mk new file mode 100644 index 000000000..494ed1ec4 --- /dev/null +++ b/plat/nvidia/tegra194/platform.mk @@ -0,0 +1,28 @@ +# +# 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/topology.c \ + plat/nvidia/tegra194/timers.c \ + plat/nvidia/tegra194/setup.c + +PLAT_TESTS_SKIP_LIST := plat/nvidia/tegra194/tests_to_skip.txt + +TFTF_CFLAGS += -Wno-maybe-uninitialized + +ENABLE_ASSERTIONS := 1 + +ifeq ($(USE_NVM),1) +$(error "Tegra194 port of TFTF doesn't currently support USE_NVM=1") +endif 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/setup.c b/plat/nvidia/tegra194/setup.c new file mode 100644 index 000000000..818caa6bc --- /dev/null +++ b/plat/nvidia/tegra194/setup.c @@ -0,0 +1,65 @@ +/* + * 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> + +/* + * The memory map currently provides the following apertures + * + * GIC Distributor : 4KB + * GIC CPU Interface : 4KB + * UARTC for the console : 128KB + * RTC : 4KB + * us Timer : 4KB + * DRAM aperture for NVM : 256MB + */ +static const mmap_region_t tegra194_mmap[] = { + 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(DRAM_BASE + TFTF_NVM_OFFSET, TFTF_NVM_SIZE, + 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(); +} 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..9636021e8 --- /dev/null +++ b/plat/nvidia/tegra194/tests_to_skip.txt @@ -0,0 +1,6 @@ +# +# Copyright (c) 2019-2020, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + diff --git a/plat/nvidia/tegra194/timers.c b/plat/nvidia/tegra194/timers.c new file mode 100644 index 000000000..98bd63bfc --- /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(2) + +/* 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); +} |