From 7fa2a382b669c18dd59e79961f35ce4b655fedc6 Mon Sep 17 00:00:00 2001 From: Toshiyuki Ogasahara Date: Fri, 15 Oct 2021 15:26:42 +0900 Subject: [PATCH 1/4] rcar_gen4: plat: BL31: First commit for R-Car S4 - CPU power driver code - SCIF driver code - BL31 setup code - Platform side code to handle PSCI - Function to get canary for stack protector Signed-off-by: Hideyuki Nitta Signed-off-by: Toshiyuki Ogasahara Signed-off-by: Yoshifumi Hosoya --- drivers/renesas/rcar_gen4/pwrc/pwrc.c | 288 ++++++++++++++++++ drivers/renesas/rcar_gen4/pwrc/pwrc.h | 24 ++ drivers/renesas/rcar_gen4/scif/scif.S | 251 +++++++++++++++ plat/renesas/rcar_gen4/aarch64/plat_helpers.S | 242 +++++++++++++++ .../rcar_gen4/aarch64/platform_common.c | 165 ++++++++++ plat/renesas/rcar_gen4/bl31_plat_setup.c | 140 +++++++++ plat/renesas/rcar_gen4/include/plat_helpers.h | 12 + plat/renesas/rcar_gen4/include/plat_macros.S | 37 +++ plat/renesas/rcar_gen4/include/platform_def.h | 96 ++++++ plat/renesas/rcar_gen4/include/rcar_def.h | 109 +++++++ plat/renesas/rcar_gen4/include/rcar_private.h | 97 ++++++ plat/renesas/rcar_gen4/include/rcar_version.h | 17 ++ plat/renesas/rcar_gen4/plat_pm.c | 170 +++++++++++ plat/renesas/rcar_gen4/plat_topology.c | 61 ++++ plat/renesas/rcar_gen4/platform.mk | 106 +++++++ plat/renesas/rcar_gen4/rcar_common.c | 47 +++ plat/renesas/rcar_gen4/rcar_stack_protector.c | 38 +++ 17 files changed, 1900 insertions(+) create mode 100644 drivers/renesas/rcar_gen4/pwrc/pwrc.c create mode 100644 drivers/renesas/rcar_gen4/pwrc/pwrc.h create mode 100644 drivers/renesas/rcar_gen4/scif/scif.S create mode 100644 plat/renesas/rcar_gen4/aarch64/plat_helpers.S create mode 100644 plat/renesas/rcar_gen4/aarch64/platform_common.c create mode 100644 plat/renesas/rcar_gen4/bl31_plat_setup.c create mode 100644 plat/renesas/rcar_gen4/include/plat_helpers.h create mode 100644 plat/renesas/rcar_gen4/include/plat_macros.S create mode 100644 plat/renesas/rcar_gen4/include/platform_def.h create mode 100644 plat/renesas/rcar_gen4/include/rcar_def.h create mode 100644 plat/renesas/rcar_gen4/include/rcar_private.h create mode 100644 plat/renesas/rcar_gen4/include/rcar_version.h create mode 100644 plat/renesas/rcar_gen4/plat_pm.c create mode 100644 plat/renesas/rcar_gen4/plat_topology.c create mode 100644 plat/renesas/rcar_gen4/platform.mk create mode 100644 plat/renesas/rcar_gen4/rcar_common.c create mode 100644 plat/renesas/rcar_gen4/rcar_stack_protector.c diff --git a/drivers/renesas/rcar_gen4/pwrc/pwrc.c b/drivers/renesas/rcar_gen4/pwrc/pwrc.c new file mode 100644 index 0000000000..b17c073b43 --- /dev/null +++ b/drivers/renesas/rcar_gen4/pwrc/pwrc.c @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "pwrc.h" +#include "rcar_def.h" +#include "rcar_private.h" + +/* + * Someday there will be a generic power controller api. At the moment each + * platform has its own pwrc so just exporting functions should be acceptable. + */ +static RCAR_INSTANTIATE_LOCK + + +/* APSREG boot configuration */ +static inline uintptr_t APSREG_AP_CLUSTER_AUX0(uint32_t n) +{ + return (APSREG_BASE + UL(0x10) + (((n) & UL(0x3)) * UL(0x1000))); +} + +/* APMU */ +static inline uintptr_t RCAR_APMU_CLUSTER_BASE(uint32_t n) +{ + return (RCAR_APMU_BASE + UL(0x400) + (((n) & UL(0x3)) * UL(0x40))); +} +static inline uintptr_t RCAR_APMU_CPU_BASE(uint32_t n) +{ + return (RCAR_APMU_BASE + UL(0x800) + (((n) & UL(0x6)) * UL(0x100)) + + (((n) & UL(0x1)) * UL(0x40))); +} +static inline uintptr_t RCAR_APMU_PWRCTRLCL(uint32_t n) +{ + return RCAR_APMU_CLUSTER_BASE(n); +} +static inline uintptr_t RCAR_APMU_PWRCTRLC(uint32_t n) +{ + return RCAR_APMU_CPU_BASE(n); +} +static inline uintptr_t RCAR_APMU_SAFECTRLC(uint32_t n) +{ + return (RCAR_APMU_CPU_BASE(n) + UL(0x20)); +} +static inline uintptr_t RCAR_APMU_RVBARPLC(uint32_t n) +{ + return (RCAR_APMU_CPU_BASE(n) + UL(0x38)); +} +static inline uintptr_t RCAR_APMU_RVBARPHC(uint32_t n) +{ + return (RCAR_APMU_CPU_BASE(n) + UL(0x3C)); +} + +/* Product register */ +static inline uint32_t PRR_CA55_XX_EN_CPU(uint32_t n) +{ + return ((uint32_t)(1) << ((n) & U(1))); +} +static inline uint32_t PRR_CA55_XX_EN_SHIFT(uint32_t c) +{ + return ((uint32_t)(20) + (((c) & U(3)) * U(3))); +} + +static inline void write_cpupwrctlr(u_register_t v) +{ + __asm__ volatile ("msr S3_0_C15_C2_7, %0" : : "r" (v)); +} + +static void rcar_pwrc_cpuoff_sub(uint32_t cpu); +static uint32_t rcar_pwrc_get_cpu_num(uint32_t c); +static uint32_t rcar_pwrc_get_cpu_num_sub(uint32_t c); +static uint32_t rcar_pwrc_core_pos(u_register_t mpidr); + + +void rcar_pwrc_cpuon(u_register_t mpidr) +{ + uint32_t cpu; + uint32_t cluster; + + rcar_lock_get(); + + cpu = rcar_pwrc_core_pos(mpidr); + + cluster = rcar_pwrc_get_mpidr_cluster(mpidr); + + /* clear Cluster OFF bit */ + mmio_clrbits_32(RCAR_APMU_PWRCTRLCL(cluster), + RCAR_APMU_PWRCTRLCL_PCHPDNEN); + + /* clear Core OFF bit */ + mmio_clrbits_32(RCAR_APMU_PWRCTRLC(cpu), RCAR_APMU_PWRCTRLC_PCHPDNEN); + while ((mmio_read_32(RCAR_APMU_PWRCTRLC(cpu)) & + RCAR_APMU_PWRCTRLC_PCHPDNEN) != 0U) + ; + + mmio_setbits_32(RCAR_APMU_PWRCTRLC(cpu), RCAR_APMU_PWRCTRLC_WUP_REQ); + + /* Wait until CA55 wake up sequence finishes */ + while ((mmio_read_32(RCAR_APMU_PWRCTRLC(cpu)) & + RCAR_APMU_PWRCTRLC_WUP_REQ) + == RCAR_APMU_PWRCTRLC_WUP_REQ) + ; + + rcar_lock_release(); +} + +void rcar_pwrc_cpuoff(u_register_t mpidr) +{ + uint32_t cpu; + + rcar_lock_get(); + + cpu = rcar_pwrc_core_pos(mpidr); + + rcar_pwrc_cpuoff_sub(cpu); + + rcar_lock_release(); +} + +void rcar_pwrc_enable_interrupt_wakeup(u_register_t mpidr) +{ + uint32_t cpu; + + rcar_lock_get(); + + cpu = rcar_pwrc_core_pos(mpidr); + + mmio_setbits_32(RCAR_APMU_PWRCTRLC(cpu), RCAR_APMU_PWRCTRLC_IWUP_EN); + + rcar_lock_release(); +} + +void rcar_pwrc_disable_interrupt_wakeup(u_register_t mpidr) +{ + uint32_t cpu; + + rcar_lock_get(); + + cpu = rcar_pwrc_core_pos(mpidr); + + mmio_clrbits_32(RCAR_APMU_PWRCTRLC(cpu), RCAR_APMU_PWRCTRLC_IWUP_EN); + + rcar_lock_release(); +} + +void rcar_pwrc_clusteroff(u_register_t mpidr) +{ + uint32_t cluster; + uint32_t cpu; + + rcar_lock_get(); + + cpu = rcar_pwrc_core_pos(mpidr); + + cluster = rcar_pwrc_get_mpidr_cluster(mpidr); + + /* for Cluster OFF */ + mmio_setbits_32(RCAR_APMU_PWRCTRLCL(cluster), + RCAR_APMU_PWRCTRLCL_PCHPDNEN); + + rcar_pwrc_cpuoff_sub(cpu); + + rcar_lock_release(); +} + +void rcar_pwrc_setup(void) +{ + uintptr_t rst_barh; + uintptr_t rst_barl; + uint32_t i, j; + uint32_t reg; + uint32_t cnum; + uint64_t reset = (uint64_t) (&plat_secondary_reset) & 0xFFFFFFFFU; + + reset &= RCAR_APMU_RVBARPLC_MASK; + reset |= RCAR_APMU_RVBARPL_VLD; + + reg = mmio_read_32(RCAR_PRR) >> 17; + for (i = 0; i < PLATFORM_CLUSTER_COUNT; i++) { + reg >>= 3; + if ((reg & PRR_CA55_XX_EN_CLUSTER_MASK) != RCAR_CPU_HAVE_CA55) { + continue; + } + + mmio_setbits_32(APSREG_AP_CLUSTER_AUX0(i), + APSREG_AP_CLUSTER_AUX0_INIT); + cnum = rcar_pwrc_get_cpu_num(i + 1U); + for (j = 0; j < cnum; j++) { + uint32_t cpu = (i * PLATFORM_MAX_CPUS_PER_CLUSTER) + j; + + if ((reg & PRR_CA55_XX_EN_CPU(cpu)) != RCAR_CPU_HAVE_CA55) { + continue; + } + + rst_barh = RCAR_APMU_RVBARPHC(cpu); + rst_barl = RCAR_APMU_RVBARPLC(cpu); + mmio_write_32(rst_barh, 0); + mmio_write_32(rst_barl, (uint32_t)reset); + } + } + mmio_setbits_32(APSREG_CCI500_AUX, APSREG_CCI500_AUX_INIT); + mmio_setbits_32(APSREG_P_CCI500_AUX, APSREG_P_CCI500_AUX_INIT); + + rcar_lock_init(); +} + +uint32_t rcar_pwrc_get_mpidr_cluster(u_register_t mpidr) +{ + int32_t cluster = rcar_cluster_pos_by_mpidr(mpidr); + + if (cluster < 0) { + ERROR("BL3-1 : The value of passed MPIDR is invalid."); + panic(); + } + + return (uint32_t)cluster; +} + +static uint32_t rcar_pwrc_get_cpu_num(uint32_t c) +{ + uint32_t i; + uint32_t count = 0; + + if (c == 0U) { + for (i = 0; i < PLATFORM_CLUSTER_COUNT; i++) { + count += rcar_pwrc_get_cpu_num_sub(i); + } + } else { + count = rcar_pwrc_get_cpu_num_sub(c - 1U); + } + + return count; +} + +static uint32_t rcar_pwrc_get_cpu_num_sub(uint32_t c) +{ + uint32_t i; + uint32_t count = 0; + uint32_t reg = mmio_read_32(RCAR_PRR); + + reg >>= PRR_CA55_XX_EN_SHIFT(c); + if ((reg & PRR_CA55_XX_EN_CLUSTER_MASK) != RCAR_CPU_HAVE_CA55) { + return 0; + } + + for (i = 0; i < PLATFORM_MAX_CPUS_PER_CLUSTER; i++) { + if ((reg & PRR_CA55_XX_EN_CPU(i)) == RCAR_CPU_HAVE_CA55) { + count++; + } + } + + return count; +} + +static void rcar_pwrc_cpuoff_sub(uint32_t cpu) +{ + /* Clear DBGGEN_PPDN bit for core down to 'OFF' mode */ + mmio_clrbits_32(RCAR_APMU_SAFECTRLC(cpu), RCAR_APMU_SAFECTRLC_DBGGEN); + /* for Core OFF */ + mmio_setbits_32(RCAR_APMU_PWRCTRLC(cpu), RCAR_APMU_PWRCTRLC_PCHPDNEN); + + write_cpupwrctlr(CPUPWRCTLR_PWDN); +} + +static uint32_t rcar_pwrc_core_pos(u_register_t mpidr) +{ + int cpu; + + cpu = plat_core_pos_by_mpidr(mpidr); + if (cpu < 0) { + ERROR("BL3-1 : The value of passed MPIDR is invalid."); + panic(); + } + + return (uint32_t)cpu; +} diff --git a/drivers/renesas/rcar_gen4/pwrc/pwrc.h b/drivers/renesas/rcar_gen4/pwrc/pwrc.h new file mode 100644 index 0000000000..d912aa1c6f --- /dev/null +++ b/drivers/renesas/rcar_gen4/pwrc/pwrc.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PWRC_H +#define PWRC_H + + +#ifndef __ASSEMBLER__ +void rcar_pwrc_disable_interrupt_wakeup(u_register_t mpidr); +void rcar_pwrc_enable_interrupt_wakeup(u_register_t mpidr); +void rcar_pwrc_clusteroff(u_register_t mpidr); +void rcar_pwrc_cpuoff(u_register_t mpidr); +void rcar_pwrc_cpuon(u_register_t mpidr); +void rcar_pwrc_setup(void); +uint32_t rcar_pwrc_get_mpidr_cluster(u_register_t mpidr); + +void plat_secondary_reset(void); +#endif + + +#endif /* PWRC_H */ diff --git a/drivers/renesas/rcar_gen4/scif/scif.S b/drivers/renesas/rcar_gen4/scif/scif.S new file mode 100644 index 0000000000..3acc59f560 --- /dev/null +++ b/drivers/renesas/rcar_gen4/scif/scif.S @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#define SCIF_INTERNAL_CLK 0 +#define SCIF_EXTARNAL_CLK 1 +#define SCIF_CLK SCIF_INTERNAL_CLK + +/* scif */ +#define SCIF3_BASE (0xE6C50000) +#define SCIF_BASE SCIF3_BASE +#define SCIF_SCSMR (0x00) +#define SCIF_SCBRR (0x04) +#define SCIF_SCSCR (0x08) +#define SCIF_SCFTDR (0x0C) +#define SCIF_SCFSR (0x10) +#define SCIF_SCFCR (0x18) +#define SCIF_SCFDR (0x1C) +#define SCIF_SCLSR (0x24) +#define SCIF_DL (0x30) +#define SCIF_CKS (0x34) + +#define CPG_BASE (0xE6150000) +#define CPG_CPGWPROFST (0x0000) +#define CPG_MSTPSR (0x2E1C) +#define CPG_SMSTPCR (0x2D1C) +#define MSTP704 (1 << 4) +#define MSTP MSTP704 + +#define SCSMR_CA_ASYNC (0x0000) +#define SCSMR_CHR_8 (0x0000) +#define SCSMR_PE_DIS (0x0000) +#define SCSMR_STOP_1 (0x0000) +#define SCSMR_CKS_DIV1 (0x0000) +#define SCSMR_INIT_DATA (SCSMR_CA_ASYNC + \ + SCSMR_CHR_8 + \ + SCSMR_PE_DIS + \ + SCSMR_STOP_1 + \ + SCSMR_CKS_DIV1) + +#define SCBRR_115200BPS (17) + +#define SCSCR_TE_DIS (0x0000) +#define SCSCR_TE_EN (0x0020) +#define SCSCR_RE_DIS (0x0000) +#define SCSCR_RE_EN (0x0010) +#define SCSCR_CKE_MASK (3 << 0) +#define SCSCR_CKE_INT (0x0000) +#define SCSCR_CKE_BRG (0x0002) +#if SCIF_CLK == SCIF_EXTARNAL_CLK +#define SCSCR_CKE_INT_CLK (SCSCR_CKE_BRG) +#else +#define SCFSR_TEND_MASK (1 << 6) +#define SCFSR_TEND_TRANS_END (0x0040) +#define SCSCR_CKE_INT_CLK (SCSCR_CKE_INT) +#endif +#define SCFSR_INIT_DATA (0x0000) +#define SCFCR_TTRG_8 (0x0000) +#define SCFCR_TFRST_EN (0x0004) +#define SCFCR_RFRS_EN (0x0002) +#define SCFCR_INIT_DATA (SCFCR_TTRG_8) +#define DL_INIT_DATA (8) +#define CKS_CKS_DIV_CLK (0x0000) +#define CKS_XIN_SCIF_CLK (0x0000) +#define CKS_INIT_DATA (CKS_CKS_DIV_CLK + CKS_XIN_SCIF_CLK) + + .globl console_rcar_register + .globl console_rcar_init + .globl console_rcar_putc + .globl console_rcar_flush + + /* + * ----------------------------------------------- + * int console_rcar_register( + * uintptr_t base, uint32_t clk, uint32_t baud, + * console_t *console) + * Function to initialize and register a new rcar + * console. Storage passed in for the console struct + * *must* be persistent (i.e. not from the stack). + * In: x0 - UART register base address + * w1 - UART clock in Hz + * w2 - Baud rate + * x3 - pointer to empty console_t struct + * Out: return 1 on success, 0 on error + * Clobber list : x0, x1, x2, x6, x7, x14 + * ----------------------------------------------- + */ +func console_rcar_register + mov x7, x30 + mov x6, x3 + cbz x6, register_fail + str x0, [x6, #CONSOLE_T_BASE] + + bl console_rcar_init + + mov x0, x6 + mov x30, x7 + finish_console_register rcar, putc=1, getc=0, flush=1 + +register_fail: + ret x7 +endfunc console_rcar_register + + /* + * int console_rcar_init(unsigned long 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_rcar_register + * and crash reporting. + * In: x0 - console base address + * w1 - Uart clock in Hz + * w2 - Baud rate + * Out: return 1 on success + * Clobber list : x1, x2 + */ +func console_rcar_init + ldr x0, =CPG_BASE + ldr w1, [x0, #CPG_SMSTPCR] + and w1, w1, #~MSTP + mvn w2, w1 + str w2, [x0, #CPG_CPGWPROFST] + str w1, [x0, #CPG_SMSTPCR] +2: + ldr w1, [x0, #CPG_MSTPSR] + and w1, w1, #MSTP + cbnz w1, 2b + + ldr x0, =SCIF_BASE + /* Clear bits TE and RE in SCSCR to 0 */ + mov w1, #(SCSCR_TE_DIS + SCSCR_RE_DIS) + strh w1, [x0, #SCIF_SCSCR] + /* Set bits TFRST and RFRST in SCFCR to 1 */ + ldrh w1, [x0, #SCIF_SCFCR] + orr w1, w1, #(SCFCR_TFRST_EN + SCFCR_RFRS_EN) + strh w1, [x0, #SCIF_SCFCR] + /* + * Read flags of ER, DR, BRK, and RDF in SCFSR and those of TO and ORER + * in SCLSR, then clear them to 0 + */ + mov w1, #SCFSR_INIT_DATA + strh w1, [x0, #SCIF_SCFSR] + mov w1, #0 + strh w1, [x0, #SCIF_SCLSR] + /* Set bits CKE[1:0] in SCSCR */ + ldrh w1, [x0, #SCIF_SCSCR] + and w1, w1, #~SCSCR_CKE_MASK + mov w2, #SCSCR_CKE_INT_CLK + orr w1, w1, w2 + strh w1, [x0, #SCIF_SCSCR] + /* Set data transfer format in SCSMR */ + mov w1, #SCSMR_INIT_DATA + strh w1, [x0, #SCIF_SCSMR] + + /* Set value in SCBRR */ +#if SCIF_CLK == SCIF_INTERNAL_CLK + mov w1, #SCBRR_115200BPS + strb w1, [x0, SCIF_SCBRR] +#else + mov w1, #DL_INIT_DATA + strh w1, [x0, #SCIF_DL] + mov w1, #CKS_INIT_DATA + strh w1, [x0, #SCIF_CKS] +#endif + /* 1-bit interval elapsed */ + mov w1, #100 +1: + subs w1, w1, #1 + cbnz w1, 1b + /* + * Set bits RTRG[1:0], TTRG[1:0], and MCE in SCFCR + * Clear bits FRST and RFRST to 0 + */ + mov w1, #SCFCR_INIT_DATA + strh w1, [x0, #SCIF_SCFCR] + /* Set bits TE and RE in SCSCR to 1 */ + ldrh w1, [x0, #SCIF_SCSCR] + orr w1, w1, #(SCSCR_TE_EN + SCSCR_RE_EN) + strh w1, [x0, #SCIF_SCSCR] + mov x0, #1 + + ret +endfunc console_rcar_init + + /* + * int console_rcar_putc(int c, unsigned int 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 - pointer to console_t structure + * Out : return -1 on error else return character. + * Clobber list : x2 + */ +func console_rcar_putc + ldr x1, =SCIF_BASE + cmp w0, #0xA + /* Prepend '\r' to '\n' */ + bne 2f +1: + /* Check if the transmit FIFO is full */ + ldrh w2, [x1, #SCIF_SCFDR] + ubfx w2, w2, #8, #5 + cmp w2, #16 + bcs 1b + mov w2, #0x0D + strb w2, [x1, #SCIF_SCFTDR] +2: + /* Check if the transmit FIFO is full */ + ldrh w2, [x1, #SCIF_SCFDR] + ubfx w2, w2, #8, #5 + cmp w2, #16 + bcs 2b + strb w0, [x1, #SCIF_SCFTDR] + + /* Clear TEND flag */ + ldrh w2, [x1, #SCIF_SCFSR] + and w2, w2, #~SCFSR_TEND_MASK + strh w2, [x1, #SCIF_SCFSR] + + ret +endfunc console_rcar_putc + + /* + * void console_rcar_flush(void) + * Function to force a write of all buffered + * data that hasn't been output. It returns void + * Clobber list : x0, x1 + */ +func console_rcar_flush + ldr x0, =SCIF_BASE +1: + /* Check TEND flag */ + ldrh w1, [x0, #SCIF_SCFSR] + and w1, w1, #SCFSR_TEND_MASK + cmp w1, #SCFSR_TEND_TRANS_END + bne 1b + + ldr x0, =SCIF_BASE + ldrh w1, [x0, #SCIF_SCSCR] + and w1, w1, #~(SCSCR_TE_EN + SCSCR_RE_EN) + strh w1, [x0, #SCIF_SCSCR] + + ret +endfunc console_rcar_flush diff --git a/plat/renesas/rcar_gen4/aarch64/plat_helpers.S b/plat/renesas/rcar_gen4/aarch64/plat_helpers.S new file mode 100644 index 0000000000..d99d62bceb --- /dev/null +++ b/plat/renesas/rcar_gen4/aarch64/plat_helpers.S @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include "rcar_def.h" + + .globl plat_get_my_entrypoint + .extern plat_set_my_stack + .globl platform_mem_init + + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl plat_invalidate_icache + .globl plat_report_exception + .globl plat_secondary_reset + .globl plat_my_core_pos + .globl plat_renesas_calc_core_pos + + .extern console_rcar_init + .extern console_rcar_putc + .extern console_rcar_flush + + /* ----------------------------------------------------- + * void platform_get_core_pos (mpidr) + * ----------------------------------------------------- + */ +func plat_renesas_calc_core_pos + lsr x0, x0, #8 + and x1, x0, #MPIDR_CPU_MASK + and x0, x0, #MPIDR_CLUSTER_MASK + add x0, x1, x0, LSR #7 + ret +endfunc plat_renesas_calc_core_pos + + /* ----------------------------------------------------- + * void platform_my_core_pos + * ----------------------------------------------------- + */ +func plat_my_core_pos + mrs x0, mpidr_el1 + b plat_renesas_calc_core_pos +endfunc plat_my_core_pos + + /* ----------------------------------------------------- + * void platform_get_my_entrypoint (unsigned int mpid); + * + * Main job of this routine is to distinguish between + * a cold and warm boot. + * On a cold boot the secondaries first wait for the + * platform to be initialized after which they are + * hotplugged in. The primary proceeds to perform the + * platform initialization. + * On a warm boot, each cpu jumps to the address in its + * mailbox. + * + * TODO: Not a good idea to save lr in a temp reg + * ----------------------------------------------------- + */ +func plat_get_my_entrypoint + mrs x0, mpidr_el1 + mov x9, x30 /* lr */ + + ldr x1, =BOOT_KIND_BASE + ldr x21, [x1] + + /* Check the reset info */ + and x1, x21, #0x000c + cmp x1, #0x0008 + beq el3_panic + cmp x1, #0x000c + beq el3_panic + + /* Check the boot kind */ + and x1, x21, #0x0003 + cmp x1, #0x0002 + beq el3_panic + cmp x1, #0x0003 + beq el3_panic + + /* warm boot or cold boot */ + and x1, x21, #1 + cmp x1, #0 + bne warm_reset + + /* Cold boot */ + mov x0, #0 + b exit + +warm_reset: + /* -------------------------------------------------------------------- + * A per-cpu mailbox is maintained in the trusted SDRAM. Its flushed out + * of the caches after every update using normal memory so its safe to + * read it here with SO attributes + * --------------------------------------------------------------------- + */ + ldr x10, =MBOX_BASE + bl plat_renesas_calc_core_pos + lsl x0, x0, #CACHE_WRITEBACK_SHIFT + ldr x0, [x10, x0] + cbz x0, _panic +exit: + ret x9 +_panic: + b do_panic + +endfunc plat_get_my_entrypoint + + /* --------------------------------------------- + * plat_secondary_reset + * + * --------------------------------------------- + */ +func plat_secondary_reset + mrs x0, sctlr_el3 + bic x0, x0, #SCTLR_EE_BIT + msr sctlr_el3, x0 + isb + + mrs x0, cptr_el3 + bic w0, w0, #TCPAC_BIT + bic w0, w0, #TTA_BIT + bic w0, w0, #TFP_BIT + msr cptr_el3, x0 + + mov_imm x0, PARAMS_BASE + mov_imm x2, BL31_BASE + ldr x3, =BOOT_KIND_BASE + mov x1, #0x1 + str x1, [x3] + br x2 /* jump to BL31 */ + nop + nop + nop +endfunc plat_secondary_reset + + /* ----------------------------------------------------- + * void platform_mem_init (void); + * + * Zero out the mailbox registers in the shared memory + * and set the rcar_boot_kind_flag. + * The mmu is turned off right now and only the primary can + * ever execute this code. Secondaries will read the + * mailboxes using SO accesses. + * ----------------------------------------------------- + */ +func platform_mem_init + ldr x0, =MBOX_BASE + mov w1, #PLATFORM_CORE_COUNT +loop: + str xzr, [x0], #CACHE_WRITEBACK_GRANULE + subs w1, w1, #1 + b.gt loop + ret +endfunc platform_mem_init + + /* --------------------------------------------- + * void plat_report_exception(unsigned int type) + * Function to report an unhandled exception + * with platform-specific means. + * --------------------------------------------- + */ +func plat_report_exception + /* Switch to SP_EL0 */ + msr spsel, #0 + ret +endfunc plat_report_exception + + /* --------------------------------------------- + * int plat_crash_console_init(void) + * Function to initialize log area + * --------------------------------------------- + */ +func plat_crash_console_init + mov x1, sp + mov_imm x2, RCAR_CRASH_STACK + mov sp, x2 + str x1, [sp, #-16]! + str x30, [sp, #-16]! + bl console_rcar_init + ldr x30, [sp], #16 + ldr x1, [sp], #16 + mov sp, x1 + ret +endfunc plat_crash_console_init + + /* --------------------------------------------- + * int plat_crash_console_putc(int c) + * Function to store a character to log area + * --------------------------------------------- + */ +func plat_crash_console_putc + mov x1, sp + mov_imm x2, RCAR_CRASH_STACK + mov sp, x2 + str x1, [sp, #-16]! + str x30, [sp, #-16]! + str x3, [sp, #-16]! + str x4, [sp, #-16]! + str x5, [sp, #-16]! + str x6, [sp, #-16]! + str x7, [sp, #-16]! + bl console_rcar_putc + ldr x7, [sp], #16 + ldr x6, [sp], #16 + ldr x5, [sp], #16 + ldr x4, [sp], #16 + ldr x3, [sp], #16 + ldr x30, [sp], #16 + ldr x1, [sp], #16 + mov sp, x1 + ret +endfunc plat_crash_console_putc + + /* --------------------------------------------- + * void plat_crash_console_flush() + * --------------------------------------------- + */ +func plat_crash_console_flush + b console_rcar_flush +endfunc plat_crash_console_flush + + + /* --------------------------------------------- + * void plat_invalidate_icache(void) + * Instruction Cache Invalidate All to PoU + * --------------------------------------------- + */ +func plat_invalidate_icache + ic iallu + ret +endfunc plat_invalidate_icache diff --git a/plat/renesas/rcar_gen4/aarch64/platform_common.c b/plat/renesas/rcar_gen4/aarch64/platform_common.c new file mode 100644 index 0000000000..7264c69440 --- /dev/null +++ b/plat/renesas/rcar_gen4/aarch64/platform_common.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include "../drivers/arm/gic/v3/gicv3_private.h" +#include +#include +#include +#include +#include +#include +#include + +#include "rcar_def.h" +#include "rcar_private.h" +#include "rcar_version.h" + +const uint8_t version_of_renesas[VERSION_OF_RENESAS_MAXLEN] + __attribute__ ((__section__("ro"))) = VERSION_OF_RENESAS; + +#define RCAR_DCACHE MT_MEMORY + +#define MAP_SHARED_RAM MAP_REGION_FLAT(RCAR_SHARED_MEM_BASE, \ + RCAR_SHARED_MEM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define MAP_DEVICE_RCAR MAP_REGION_FLAT(DEVICE_RCAR_BASE, \ + DEVICE_RCAR_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + + +#define MAP_ATFW_CRASH MAP_REGION_FLAT(RCAR_BL31_CRASH_BASE, \ + RCAR_BL31_CRASH_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + + + +static const mmap_region_t rcar_mmap[] = { + MAP_SHARED_RAM, + MAP_ATFW_CRASH, + MAP_DEVICE_RCAR, + {0} +}; + +CASSERT((ARRAY_SIZE(rcar_mmap) + RCAR_BL_REGIONS) + <= MAX_MMAP_REGIONS, assert_max_mmap_regions); + +/* + * Macro generating the code for the function setting up the pagetables as per + * the platform memory map & initialize the mmu, for the given exception level + */ +#if USE_COHERENT_MEM +void rcar_configure_mmu_el3(uintptr_t total_base, + size_t total_size, + uintptr_t ro_start, + uintptr_t ro_limit, + uintptr_t coh_start, + uintptr_t coh_limit) +{ + mmap_add_region(total_base, total_base, total_size, + RCAR_DCACHE | MT_RW | MT_SECURE); + mmap_add_region(ro_start, ro_start, ro_limit - ro_start, + RCAR_DCACHE | MT_RO | MT_SECURE); + mmap_add_region(coh_start, coh_start, coh_limit - coh_start, + MT_DEVICE | MT_RW | MT_SECURE); + mmap_add(rcar_mmap); + + init_xlat_tables(); + enable_mmu_el3(0); +} +#else +void rcar_configure_mmu_el3(uintptr_t total_base, + size_t total_size, + uintptr_t ro_start, + uintptr_t ro_limit) +{ + mmap_add_region(total_base, total_base, total_size, + RCAR_DCACHE | MT_RW | MT_SECURE); + mmap_add_region(ro_start, ro_start, ro_limit - ro_start, + RCAR_DCACHE | MT_RO | MT_SECURE); + mmap_add(rcar_mmap); + + init_xlat_tables(); + enable_mmu_el3(0); +} +#endif + +unsigned int plat_get_syscnt_freq2(void) +{ + unsigned int freq; + + freq = mmio_read_32(ARM_SYS_CNTCTL_BASE + CNTFID_OFF); + if (freq == 0U) { + panic(); + } + + return freq; +} + +void plat_rcar_gic_init(void) +{ + gicv3_distif_init(); + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + + +/* + * Define a list of Group 1 Secure and Group 0 interrupt properties as per GICv3 + * terminology. On a GICv2 system or mode, the lists will be merged and treated + * as Group 0 interrupts. + */ +#define PLATFORM_G1S_PROPS(grp) \ + INTR_PROP_DESC(ARM_IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE), \ + INTR_PROP_DESC(ARM_IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY, (grp), \ + GIC_INTR_CFG_EDGE) + +static const interrupt_prop_t interrupt_props[] = { + PLATFORM_G1S_PROPS(INTR_GROUP1S) +}; + +static unsigned int rcar_mpidr_to_core_pos(u_register_t mpidr) +{ + return plat_renesas_calc_core_pos(mpidr); +} + +void plat_rcar_gic_driver_init(void) +{ + static uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; + static gicv3_driver_data_t rcar_gicv3_data = { + .gicd_base = RCAR_GICD_BASE, + .gicr_base = RCAR_GICR_BASE, + .rdistif_num = PLATFORM_CORE_COUNT, + .rdistif_base_addrs = rdistif_base_addrs, + .mpidr_to_core_pos = rcar_mpidr_to_core_pos, + .interrupt_props = interrupt_props, + .interrupt_props_num = (uint32_t) ARRAY_SIZE(interrupt_props), + }; + + gicv3_driver_init(&rcar_gicv3_data); +} diff --git a/plat/renesas/rcar_gen4/bl31_plat_setup.c b/plat/renesas/rcar_gen4/bl31_plat_setup.c new file mode 100644 index 0000000000..3eb62cf2d2 --- /dev/null +++ b/plat/renesas/rcar_gen4/bl31_plat_setup.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pwrc.h" +#include "rcar_def.h" +#include "rcar_private.h" +#include "rcar_version.h" + + +static u_register_t rcar_boot_mpidr; + +static void plat_cci_init(void) +{ + static const int cci_map[] = { + CCI500_CLUSTER0_SL_IFACE_IX, + CCI500_CLUSTER1_SL_IFACE_IX, + CCI500_CLUSTER2_SL_IFACE_IX, + CCI500_CLUSTER3_SL_IFACE_IX + }; + + cci_init(RCAR_CCI_BASE, cci_map, ARRAY_SIZE(cci_map)); +} + +void plat_cci_enable(void) +{ + u_register_t mpidr = read_mpidr(); + uint32_t cluster = rcar_pwrc_get_mpidr_cluster(mpidr); + + cci_enable_snoop_dvm_reqs(cluster); +} + +void plat_cci_disable(void) +{ + u_register_t mpidr = read_mpidr(); + uint32_t cluster = rcar_pwrc_get_mpidr_cluster(mpidr); + + cci_disable_snoop_dvm_reqs(cluster); +} + +struct entry_point_info *bl31_plat_get_next_image_ep_info(uint32_t type) +{ + bl2_to_bl31_params_mem_t *from_bl2 = (bl2_to_bl31_params_mem_t *) + PARAMS_BASE; + entry_point_info_t *next_image_info; + + next_image_info = (type == NON_SECURE) ? + &from_bl2->bl33_ep_info : &from_bl2->bl32_ep_info; + + return (next_image_info->pc != 0U) ? next_image_info : NULL; +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + rcar_console_boot_init(); + + NOTICE("BL3-1 : Rev.%s\n", version_of_renesas); + + plat_cci_init(); + plat_cci_enable(); +} + +void bl31_plat_arch_setup(void) +{ + static const uintptr_t BL31_RO_BASE = BL_CODE_BASE; + static const uintptr_t BL31_RO_LIMIT = BL_CODE_END; + +#if USE_COHERENT_MEM + static const uintptr_t BL31_COHERENT_RAM_BASE = BL_COHERENT_RAM_BASE; + static const uintptr_t BL31_COHERENT_RAM_LIMIT = BL_COHERENT_RAM_END; +#endif /* USE_COHERENT_MEM */ + + rcar_configure_mmu_el3(BL31_BASE, + BL31_LIMIT - BL31_BASE, + BL31_RO_BASE, BL31_RO_LIMIT +#if USE_COHERENT_MEM + , BL31_COHERENT_RAM_BASE, BL31_COHERENT_RAM_LIMIT +#endif /* USE_COHERENT_MEM */ + ); +} + +void bl31_platform_setup(void) +{ + plat_rcar_gic_driver_init(); + plat_rcar_gic_init(); + + /* initialize generic timer */ + uint32_t reg_cntfid = RCAR_CNTC_EXTAL; + /* Update memory mapped and register based frequency */ + write_cntfrq_el0((u_register_t)reg_cntfid); + mmio_write_32(ARM_SYS_CNTCTL_BASE + (uintptr_t)CNTFID_OFF, reg_cntfid); + + /* enable the system level generic timer */ + mmio_write_32(RCAR_CNTC_BASE + CNTCR_OFF, + CNTCR_FCREQ((uint32_t)(0)) | CNTCR_EN); + + rcar_pwrc_setup(); + + /* + * mask should match the kernel's MPIDR_HWID_BITMASK so the core can be + * identified during cpuhotplug (check the kernel's psci migrate set of + * functions + */ + rcar_boot_mpidr = read_mpidr_el1() & RCAR_MPIDR_AFFMASK; +} + +uint32_t bl31_plat_boot_mpidr_chk(void) +{ + uint32_t rc = RCAR_MPIDRCHK_NOT_BOOTCPU; + uint64_t tmp_mpidr; + + tmp_mpidr = read_mpidr_el1() & RCAR_MPIDR_AFFMASK; + + if (tmp_mpidr == rcar_boot_mpidr) { + rc = RCAR_MPIDRCHK_BOOTCPU; + } + return rc; +} + +void bl31_plat_runtime_setup(void) +{ + rcar_console_runtime_init(); + console_switch_state(CONSOLE_FLAG_RUNTIME); +} diff --git a/plat/renesas/rcar_gen4/include/plat_helpers.h b/plat/renesas/rcar_gen4/include/plat_helpers.h new file mode 100644 index 0000000000..f8c706b82c --- /dev/null +++ b/plat/renesas/rcar_gen4/include/plat_helpers.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_HELPERS_H +#define PLAT_HELPERS_H + +u_register_t plat_renesas_calc_core_pos(u_register_t mpidr); + +#endif /* PLAT_HELPERS_H */ diff --git a/plat/renesas/rcar_gen4/include/plat_macros.S b/plat/renesas/rcar_gen4/include/plat_macros.S new file mode 100644 index 0000000000..da8c29d3a6 --- /dev/null +++ b/plat/renesas/rcar_gen4/include/plat_macros.S @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include "rcar_def.h" + +.section .rodata.cci_reg_name, "aS" +cci_iface_regs: + .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , "" + + /* ------------------------------------------------ + * The below macro prints out relevant interconnect + * registers whenever an unhandled exception is + * taken in BL3-1. + * Clobbers: x0 - x9, sp + * ------------------------------------------------ + */ + .macro plat_print_interconnect_regs + adr x6, cci_iface_regs + /* Store in x7 the base address of the first interface */ + mov_imm x7, (CCI500_BASE + SLAVE_IFACE3_OFFSET) + ldr w8, [x7, #SNOOP_CTRL_REG] + /* Store in x7 the base address of the second interface */ + mov_imm x7, (CCI500_BASE + SLAVE_IFACE4_OFFSET) + ldr w9, [x7, #SNOOP_CTRL_REG] + /* Store to the crash buf and print to console */ + bl str_in_crash_buf_print + .endm + + .macro plat_crash_print_regs + plat_print_interconnect_regs + .endm diff --git a/plat/renesas/rcar_gen4/include/platform_def.h b/plat/renesas/rcar_gen4/include/platform_def.h new file mode 100644 index 0000000000..ea1bb8762d --- /dev/null +++ b/plat/renesas/rcar_gen4/include/platform_def.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#ifndef __ASSEMBLER__ +#include +#endif + +#include + +#include "rcar_def.h" + +/******************************************************************************* + * Platform binary types for linking + ******************************************************************************/ +#define PLATFORM_LINKER_FORMAT "elf64-littleaarch64" +#define PLATFORM_LINKER_ARCH aarch64 + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ + +/* Size of cacheable stacks */ +#define PLATFORM_STACK_SIZE U(0x400) + +/* + * R-Car S4 Cortex-A55 + * L1:I/32KB per core, D/32KB per core, L2:0B L3:256KB per cluster + */ +#define PLATFORM_CLUSTER_COUNT U(4) +#define PLATFORM_CLUSTER0_CORE_COUNT U(2) +#define PLATFORM_CLUSTER1_CORE_COUNT U(2) +#define PLATFORM_CLUSTER2_CORE_COUNT U(2) +#define PLATFORM_CLUSTER3_CORE_COUNT U(2) +#define PLATFORM_CORE_COUNT (PLATFORM_CLUSTER3_CORE_COUNT + \ + PLATFORM_CLUSTER2_CORE_COUNT + \ + PLATFORM_CLUSTER1_CORE_COUNT + \ + PLATFORM_CLUSTER0_CORE_COUNT) +#define PLATFORM_MAX_CPUS_PER_CLUSTER U(2) + +#define PLAT_MAX_PWR_LVL MPIDR_AFFLVL2 +#define PLAT_NUM_PWR_DOMAINS (PLATFORM_CORE_COUNT + \ + PLATFORM_CLUSTER_COUNT + 1) + +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) + + +/* + ****************************************************************************** + * BL31 specific defines. + ****************************************************************************** + * Put BL3-1 at the top of the Trusted SRAM. BL31_BASE is calculated using the + * current BL3-1 debug size plus a little space for growth. + */ +#define BL31_BASE (RCAR_TRUSTED_SRAM_BASE) +#define BL31_LIMIT (RCAR_TRUSTED_SRAM_BASE + \ + RCAR_TRUSTED_SRAM_SIZE) + + +/******************************************************************************* + * Platform specific page table and MMU setup constants + ******************************************************************************/ +#define MAX_XLAT_TABLES U(8) + +#define PLAT_PHY_ADDR_SPACE_SIZE (ULL(1) << 32) +#define PLAT_VIRT_ADDR_SPACE_SIZE (ULL(1) << 32) + +#define MAX_MMAP_REGIONS (RCAR_MMAP_ENTRIES + RCAR_BL_REGIONS) + +/******************************************************************************* + * Declarations and constants to access the mailboxes safely. Each mailbox is + * aligned 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. Such alignment ensures that two mailboxes do not sit on the same cache + * line at any cache level. They could belong to different cpus/clusters & + * get written while being protected by different locks causing corruption of + * a valid mailbox address. + ******************************************************************************/ +#define CACHE_WRITEBACK_SHIFT (6) +#define CACHE_WRITEBACK_GRANULE (1 << CACHE_WRITEBACK_SHIFT) + +/******************************************************************************* + * Size of the per-cpu data in bytes that should be reserved in the generic + * per-cpu data structure for the RCAR port. + ******************************************************************************/ +#if !USE_COHERENT_MEM +#define PLAT_PCPU_DATA_SIZE (4) +#endif + +#endif /* PLATFORM_DEF_H */ diff --git a/plat/renesas/rcar_gen4/include/rcar_def.h b/plat/renesas/rcar_gen4/include/rcar_def.h new file mode 100644 index 0000000000..07b1617dd8 --- /dev/null +++ b/plat/renesas/rcar_gen4/include/rcar_def.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RCAR_DEF_H +#define RCAR_DEF_H + +#include +#include + +#define RCAR_DOMAIN UL(0x0) + +#define RCAR_TRUSTED_SRAM_BASE UL(0x46400000) +#define RCAR_TRUSTED_SRAM_SIZE UL(0x00022000) +#define RCAR_SHARED_MEM_BASE (RCAR_TRUSTED_SRAM_BASE + \ + RCAR_TRUSTED_SRAM_SIZE) +#define RCAR_SHARED_MEM_SIZE UL(0x00001000) +#define DEVICE_RCAR_BASE UL(0xE6000000) +#define DEVICE_RCAR_SIZE UL(0x1A000000) +#define RCAR_BL31_CRASH_BASE (RCAR_TRUSTED_SRAM_BASE + UL(0x3F000)) +#define RCAR_BL31_CRASH_SIZE UL(0x00001000) +/* Entrypoint mailboxes */ +#define MBOX_BASE RCAR_SHARED_MEM_BASE +#define MBOX_SIZE UL(0x200) +/* Base address where parameters to BL31 are stored */ +#define PARAMS_BASE (MBOX_BASE + MBOX_SIZE) +#define BOOT_KIND_BASE (RCAR_SHARED_MEM_BASE + \ + RCAR_SHARED_MEM_SIZE - UL(0x100)) +/* + * The number of regions like RO(code), coherent and data required by + * different BL stages which need to be mapped in the MMU + */ +#if USE_COHERENT_MEM +#define RCAR_BL_REGIONS (3) +#else +#define RCAR_BL_REGIONS (2) +#endif +/* + * The RCAR_MAX_MMAP_REGIONS depends on the number of entries in rcar_mmap[] + * defined for each BL stage in platform_common.c. + */ +#define RCAR_MMAP_ENTRIES (4) +/* BL31 */ +#define RCAR_CRASH_STACK RCAR_BL31_CRASH_BASE + +/* CCI related constants */ +#define CCI500_BASE UL(0xF1200000) +#define CCI500_CLUSTER0_SL_IFACE_IX (0) +#define CCI500_CLUSTER1_SL_IFACE_IX (1) +#define CCI500_CLUSTER2_SL_IFACE_IX (2) +#define CCI500_CLUSTER3_SL_IFACE_IX (3) +#define RCAR_CCI_BASE CCI500_BASE + +/* APSREG boot configuration */ +#define APSREG_BASE UL(0xE6280000) +#define APSREG_CCI500_AUX (APSREG_BASE + UL(0x9010)) +#define APSREG_P_CCI500_AUX (APSREG_BASE + UL(0x29010)) + +#define APSREG_AP_CLUSTER_AUX0_INIT U(0x00000003) +#define APSREG_CCI500_AUX_INIT U(0x00000001) +#define APSREG_P_CCI500_AUX_INIT U(0x00000002) + +/* GIC */ +#define RCAR_GICD_BASE UL(0xF1000000) +#define RCAR_GICR_BASE UL(0xF1060000) +#define ARM_IRQ_SEC_PHY_TIMER U(29) +#define ARM_IRQ_SEC_SGI_0 U(8) +#define ARM_IRQ_SEC_SGI_1 U(9) +#define ARM_IRQ_SEC_SGI_2 U(10) +#define ARM_IRQ_SEC_SGI_3 U(11) +#define ARM_IRQ_SEC_SGI_4 U(12) +#define ARM_IRQ_SEC_SGI_5 U(13) +#define ARM_IRQ_SEC_SGI_6 U(14) +#define ARM_IRQ_SEC_SGI_7 U(15) + +/* Timer control */ +#define RCAR_CNTC_BASE UL(0xE6080000) +#define RCAR_CNTC_EXTAL U(16666600) + +/* APMU */ +#define RCAR_APMU_BASE (UL(0xE6170000) + (RCAR_DOMAIN * UL(0x1000))) +#define RCAR_APMU_PWRCTRLCL_PCHPDNEN ((uint32_t)(1) << U(17)) + +#define RCAR_APMU_PWRCTRLC_WUP_REQ ((uint32_t)(1) << U(0)) +#define RCAR_APMU_PWRCTRLC_IWUP_EN ((uint32_t)(1) << U(4)) +#define RCAR_APMU_PWRCTRLC_PCHPDNEN ((uint32_t)(1) << U(17)) + +#define RCAR_APMU_SAFECTRLC_DBGGEN ((uint32_t)(1) << U(13)) + +#define RCAR_APMU_RVBARPLC_MASK U(0xFFFFFFFC) +#define RCAR_APMU_RVBARPL_VLD U(0x00000001) + +/* Product register */ +#define RCAR_PRR UL(0xFFF00044) +#define RCAR_CPU_HAVE_CA55 U(0x00000000) +#define PRR_CA55_XX_EN_CLUSTER_MASK U(0x00000004) + +/* Memory mapped Generic timer interfaces */ +#define ARM_SYS_CNTCTL_BASE RCAR_CNTC_BASE + +/* MPIDR_EL1 */ +#define RCAR_MPIDR_AFFMASK U(0x00FFFF00) + +/* CPUPWRCTLR */ +#define CPUPWRCTLR_PWDN U(0x00000001) + +#endif /* RCAR_DEF_H */ diff --git a/plat/renesas/rcar_gen4/include/rcar_private.h b/plat/renesas/rcar_gen4/include/rcar_private.h new file mode 100644 index 0000000000..7301b55722 --- /dev/null +++ b/plat/renesas/rcar_gen4/include/rcar_private.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RCAR_PRIVATE_H +#define RCAR_PRIVATE_H + +#include +#include +#include + +#include + +typedef volatile struct mailbox { + uint64_t value __aligned(CACHE_WRITEBACK_GRANULE); +} mailbox_t; + +/* + * This structure represents the superset of information that is passed to + * BL31 e.g. while passing control to it from BL2 which is bl31_params + * and bl31_plat_params and its elements + */ +typedef struct bl2_to_bl31_params_mem { + image_info_t bl32_image_info; + image_info_t bl33_image_info; + entry_point_info_t bl33_ep_info; + entry_point_info_t bl32_ep_info; +} bl2_to_bl31_params_mem_t; + +#if USE_COHERENT_MEM +#define RCAR_INSTANTIATE_LOCK DEFINE_BAKERY_LOCK(rcar_lock); +#define rcar_lock_init() bakery_lock_init(&rcar_lock) +#define rcar_lock_get() bakery_lock_get(&rcar_lock) +#define rcar_lock_release() bakery_lock_release(&rcar_lock) +#else +#define RCAR_INSTANTIATE_LOCK DEFINE_BAKERY_LOCK(rcar_lock); +/* + * Constants to specify how many bakery locks this platform implements. These + * are used if the platform chooses not to use coherent memory for bakery lock + * data structures. + */ +#define RCAR_MAX_BAKERIES 2 + +/* + * Definition of structure which holds platform specific per-cpu data. Currently + * it holds only the bakery lock information for each cpu. Constants to + * specify how many bakeries this platform implements and bakery ids are + * specified in rcar_def.h + */ +typedef struct rcar_cpu_data { + bakery_info_t pcpu_bakery_info[RCAR_MAX_BAKERIES]; +} rcar_cpu_data_t; + +/* + * Helper macros for bakery lock api when using the above rcar_cpu_data_t for + * bakery lock data structures. It assumes that the bakery_info is at the + * beginning of the platform specific per-cpu data. + */ +#define rcar_lock_init() bakery_lock_init(&rcar_lock) +#define rcar_lock_get() bakery_lock_get(&rcar_lock) +#define rcar_lock_release() bakery_lock_release(&rcar_lock) + +/* + * Ensure that the size of the RCAR specific per-cpu data structure and the size + * of the memory allocated in generic per-cpu data for the platform are the same + */ +CASSERT(sizeof(rcar_cpu_data_t) == PLAT_PCPU_DATA_SIZE, + rcar_pcpu_data_size_mismatch); +#endif +/* + * Function and variable prototypes + */ +void rcar_configure_mmu_el3(uintptr_t total_base, + size_t total_size, + uintptr_t ro_start, + uintptr_t ro_limit +#if USE_COHERENT_MEM + , uintptr_t coh_start, uintptr_t coh_limit +#endif + ); + + +void plat_invalidate_icache(void); +void plat_cci_disable(void); +void plat_cci_enable(void); + +void rcar_console_boot_init(void); +void rcar_console_runtime_init(void); + +void plat_rcar_gic_driver_init(void); +void plat_rcar_gic_init(void); + +int32_t rcar_cluster_pos_by_mpidr(u_register_t mpidr); + +#endif /* RCAR_PRIVATE_H */ diff --git a/plat/renesas/rcar_gen4/include/rcar_version.h b/plat/renesas/rcar_gen4/include/rcar_version.h new file mode 100644 index 0000000000..908032d143 --- /dev/null +++ b/plat/renesas/rcar_gen4/include/rcar_version.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RCAR_VERSION_H +#define RCAR_VERSION_H + +#include + +#define VERSION_OF_RENESAS "0.2.0" +#define VERSION_OF_RENESAS_MAXLEN 128 + +extern const uint8_t version_of_renesas[VERSION_OF_RENESAS_MAXLEN]; + +#endif /* RCAR_VERSION_H */ diff --git a/plat/renesas/rcar_gen4/plat_pm.c b/plat/renesas/rcar_gen4/plat_pm.c new file mode 100644 index 0000000000..bc55b677cf --- /dev/null +++ b/plat/renesas/rcar_gen4/plat_pm.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "platform_def.h" +#include "pwrc.h" +#include "rcar_def.h" +#include "rcar_private.h" + + +#define CLUSTER_PWR_STATE(s) ((s)->pwr_domain_state[MPIDR_AFFLVL1]) +#define CORE_PWR_STATE(s) ((s)->pwr_domain_state[MPIDR_AFFLVL0]) + + +static uintptr_t rcar_sec_entrypoint; + +static void rcar_program_mailbox(u_register_t mpidr, uintptr_t address) +{ + uintptr_t range; + mailbox_t *rcar_mboxes = (mailbox_t *) MBOX_BASE; + int linear_id = plat_core_pos_by_mpidr(mpidr); + + if (linear_id < 0) { + ERROR("BL3-1 : The value of passed MPIDR is invalid."); + panic(); + } + rcar_mboxes[linear_id].value = address; + range = (uintptr_t)(&rcar_mboxes[linear_id]); + + flush_dcache_range(range, sizeof(mailbox_t)); +} + +static void rcar_cpu_standby(plat_local_state_t cpu_state) +{ + u_register_t scr_el3 = read_scr_el3(); + + write_scr_el3(scr_el3 | SCR_IRQ_BIT); + dsb(); + wfi(); + write_scr_el3(scr_el3); +} + +static int rcar_pwr_domain_on(u_register_t mpidr) +{ + rcar_program_mailbox(mpidr, rcar_sec_entrypoint); + rcar_pwrc_cpuon(mpidr); + + return PSCI_E_SUCCESS; +} + +static void rcar_pwr_domain_on_finish(const psci_power_state_t *target_state) +{ + u_register_t mpidr = read_mpidr_el1(); + + if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + plat_cci_enable(); + } + + rcar_program_mailbox(mpidr, 0U); + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +static void rcar_pwr_domain_off(const psci_power_state_t *target_state) +{ + u_register_t mpidr = read_mpidr_el1(); + + gicv3_cpuif_disable(plat_my_core_pos()); + + if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + plat_cci_disable(); + rcar_pwrc_clusteroff(mpidr); + } else { + rcar_pwrc_cpuoff(mpidr); + } +} + +static void rcar_pwr_domain_suspend(const psci_power_state_t *target_state) +{ + u_register_t mpidr = read_mpidr_el1(); + + if (CORE_PWR_STATE(target_state) != PLAT_MAX_OFF_STATE) { + return; + } + + rcar_program_mailbox(mpidr, rcar_sec_entrypoint); + rcar_pwrc_enable_interrupt_wakeup(mpidr); + gicv3_cpuif_disable(plat_my_core_pos()); + + if (CLUSTER_PWR_STATE(target_state) == PLAT_MAX_OFF_STATE) { + plat_cci_disable(); + rcar_pwrc_clusteroff(mpidr); + } else { + rcar_pwrc_cpuoff(mpidr); + } +} + +static void rcar_pwr_domain_suspend_finish(const psci_power_state_t + *target_state) +{ + rcar_pwr_domain_on_finish(target_state); +} + +static void __dead2 rcar_pwr_domain_pwr_down_wfi(const psci_power_state_t *target_state) +{ + wfi(); + + ERROR("RCAR Power Down: operation not handled.\n"); + panic(); +} + +static int rcar_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + uint32_t pwr_lvl = psci_get_pstate_pwrlvl(power_state); + uint32_t pstate = psci_get_pstate_type(power_state); + uint32_t i; + + if (pstate == PSTATE_TYPE_STANDBY) { + if (pwr_lvl != MPIDR_AFFLVL0) { + return PSCI_E_INVALID_PARAMS; + } + + req_state->pwr_domain_state[MPIDR_AFFLVL0] = PLAT_MAX_RET_STATE; + } else { + for (i = MPIDR_AFFLVL0; i <= pwr_lvl; i++) { + req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; + } + } + + if (psci_get_pstate_id(power_state) != 0U) { + return PSCI_E_INVALID_PARAMS; + } + + return PSCI_E_SUCCESS; +} + +static const plat_psci_ops_t rcar_plat_psci_ops = { + .cpu_standby = rcar_cpu_standby, + .pwr_domain_on = rcar_pwr_domain_on, + .pwr_domain_off = rcar_pwr_domain_off, + .pwr_domain_suspend = rcar_pwr_domain_suspend, + .pwr_domain_on_finish = rcar_pwr_domain_on_finish, + .pwr_domain_suspend_finish = rcar_pwr_domain_suspend_finish, + .validate_power_state = rcar_validate_power_state, + .pwr_domain_pwr_down_wfi = rcar_pwr_domain_pwr_down_wfi, +}; + +int plat_setup_psci_ops(uintptr_t sec_entrypoint, const plat_psci_ops_t **psci_ops) +{ + *psci_ops = &rcar_plat_psci_ops; + rcar_sec_entrypoint = sec_entrypoint; + + return 0; +} + diff --git a/plat/renesas/rcar_gen4/plat_topology.c b/plat/renesas/rcar_gen4/plat_topology.c new file mode 100644 index 0000000000..6559c84220 --- /dev/null +++ b/plat/renesas/rcar_gen4/plat_topology.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include "rcar_private.h" + + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + static const unsigned char rcar_power_domain_tree_desc[] = { + 1, + PLATFORM_CLUSTER_COUNT, + PLATFORM_CLUSTER0_CORE_COUNT, + PLATFORM_CLUSTER1_CORE_COUNT, + PLATFORM_CLUSTER2_CORE_COUNT, + PLATFORM_CLUSTER3_CORE_COUNT + }; + + return rcar_power_domain_tree_desc; +} + +int plat_core_pos_by_mpidr(u_register_t mpidr) +{ + u_register_t cpu; + + /* ARMv8.2 arch */ + if ((mpidr & (MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT)) != 0U) { + return -1; + } + + cpu = plat_renesas_calc_core_pos(mpidr); + if (cpu >= PLATFORM_CORE_COUNT) { + return -1; + } + + return (int)cpu; +} + +int32_t rcar_cluster_pos_by_mpidr(u_register_t mpidr) +{ + u_register_t cluster; + + /* ARMv8.2 arch */ + if ((mpidr & (MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT)) != 0U) { + return -1; + } + + cluster = MPIDR_AFFLVL2_VAL(mpidr); + if (cluster >= PLATFORM_CLUSTER_COUNT) { + return -1; + } + + return (int32_t)cluster; +} diff --git a/plat/renesas/rcar_gen4/platform.mk b/plat/renesas/rcar_gen4/platform.mk new file mode 100644 index 0000000000..28fe4e7cb9 --- /dev/null +++ b/plat/renesas/rcar_gen4/platform.mk @@ -0,0 +1,106 @@ +# +# Copyright (c) 2018-2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PROGRAMMABLE_RESET_ADDRESS := 0 +COLD_BOOT_SINGLE_CPU := 1 +ARM_CCI_PRODUCT_ID := 500 +TRUSTED_BOARD_BOOT := 1 +RESET_TO_BL31 := 1 +GENERATE_COT := 1 +ENABLE_SVE_FOR_NS := 0 +MULTI_CONSOLE_API := 1 + +CRASH_REPORTING := 1 +HANDLE_EA_EL3_FIRST := 1 +ENABLE_STACK_PROTECTOR := strong + + +ifeq (${SPD},none) + SPD_NONE:=1 + $(eval $(call add_define,SPD_NONE)) +endif + +# LSI setting common define +RCAR_S4:=9 +RCAR_AUTO:=99 +$(eval $(call add_define,RCAR_S4)) +$(eval $(call add_define,RCAR_AUTO)) + + +ifndef LSI + $(error "Error: Unknown LSI. Please use LSI= to specify the LSI") +else + ifeq (${LSI},AUTO) + RCAR_LSI:=${RCAR_AUTO} + else ifeq (${LSI},S4) + RCAR_LSI:=${RCAR_S4} + else + $(error "Error: ${LSI} is not supported.") + endif + $(eval $(call add_define,RCAR_LSI)) +endif + + +# Enable workarounds for selected Cortex-A55 errata. +ERRATA_A55_1530923 := 1 + +USE_COHERENT_MEM := 0 +HW_ASSISTED_COHERENCY := 1 + + +PLAT_INCLUDES := -Iplat/renesas/rcar_gen4/include \ + -Iplat/renesas/rcar_gen4 \ + -Idrivers/renesas/rcar_gen4/pwrc + +ifneq (${ENABLE_STACK_PROTECTOR},0) +BL_COMMON_SOURCES += plat/renesas/rcar_gen4/rcar_stack_protector.c +endif + + +# GIC-600 configuration +#GICV3_IMPL := GIC600 +GICV3_SUPPORT_GIC600 := 1 +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk +RCAR_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c + +BL31_SOURCES += ${RCAR_GIC_SOURCES} \ + lib/cpus/aarch64/cortex_a55.S \ + plat/common/plat_psci_common.c \ + plat/renesas/rcar_gen4/plat_topology.c \ + plat/renesas/rcar_gen4/aarch64/plat_helpers.S \ + plat/renesas/rcar_gen4/aarch64/platform_common.c \ + plat/renesas/rcar_gen4/bl31_plat_setup.c \ + plat/renesas/rcar_gen4/plat_pm.c \ + plat/renesas/rcar_gen4/rcar_common.c \ + drivers/renesas/rcar_gen4/pwrc/pwrc.c \ + drivers/renesas/rcar_gen4/scif/scif.S \ + drivers/arm/cci/cci.c + +include lib/xlat_tables_v2/xlat_tables.mk +ifneq (${MBEDTLS_COMMON_MK}, 1) +include drivers/auth/mbedtls/mbedtls_crypto.mk +endif +PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} + +# build the layout images for the bootrom and the necessary srecords +rcar: rcar_srecord +distclean realclean clean: clean_srecord + +# srecords +SREC_PATH = ${BUILD_PLAT} +BL31_ELF_SRC = ${SREC_PATH}/bl31/bl31.elf + +clean_srecord: + @echo "clean bl31 srecs" + rm -f ${SREC_PATH}/bl31.srec + +.PHONY: rcar_srecord +rcar_srecord: $(BL31_ELF_SRC) + @echo "generating srec: ${SREC_PATH}/bl31.srec" + $(Q)$(OC) -O srec --srec-forceS3 ${BL31_ELF_SRC} ${SREC_PATH}/bl31.srec + diff --git a/plat/renesas/rcar_gen4/rcar_common.c b/plat/renesas/rcar_gen4/rcar_common.c new file mode 100644 index 0000000000..86bae9929d --- /dev/null +++ b/plat/renesas/rcar_gen4/rcar_common.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2019-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include "rcar_private.h" + +/* RAS functions common to AArch64 ARM platforms */ +void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie, + void *handle, uint64_t flags) +{ + return; +} + + +void rcar_console_boot_init(void) +{ + static console_t rcar_boot_console = {0}; + int ret; + + ret = console_rcar_register(0, 0, 0, &rcar_boot_console); + if (ret == 0) { + panic(); + } + + console_set_scope(&rcar_boot_console, CONSOLE_FLAG_BOOT); +} + +void rcar_console_runtime_init(void) +{ + static console_t rcar_runtime_console = {0}; + int ret; + + ret = console_rcar_register(1, 0, 0, &rcar_runtime_console); + if (ret == 0) { + panic(); + } + + console_set_scope(&rcar_runtime_console, + CONSOLE_FLAG_BOOT | + CONSOLE_FLAG_RUNTIME | + CONSOLE_FLAG_CRASH); +} diff --git a/plat/renesas/rcar_gen4/rcar_stack_protector.c b/plat/renesas/rcar_gen4/rcar_stack_protector.c new file mode 100644 index 0000000000..b625b5e926 --- /dev/null +++ b/plat/renesas/rcar_gen4/rcar_stack_protector.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#define RANDOM_CANARY_VALUE ((u_register_t)0xDFF5FC8A720E205EULL) + +u_register_t plat_get_stack_protector_canary(void) +{ + u_register_t cnt; + u_register_t seed; + u_register_t mul; + u_register_t ret; + uintptr_t val1 = (uintptr_t)__builtin_return_address(0U); + uintptr_t val2 = (uintptr_t)__builtin_frame_address(0U); + + cnt = read_cntpct_el0(); + seed = (cnt ^ RANDOM_CANARY_VALUE) & ULONG_MAX; + ret = seed; + + INFO("seed value: 0x%16lx cnt: 0x%16lx\n", seed, cnt); + + if ((ULONG_MAX/val1) > seed) { + mul = (u_register_t)(val1 * seed); + if ((ULONG_MAX - mul) > val2) { + ret = mul + val2; + } + } + + INFO("canary value: 0x%lx cnt: 0x%16lx\n", ret, read_cntpct_el0()); + + return ret; +} From 048319791c1c504f7abeaaad94e99a383672ddac Mon Sep 17 00:00:00 2001 From: Toshiyuki Ogasahara Date: Fri, 15 Oct 2021 15:28:43 +0900 Subject: [PATCH 2/4] rcar_gen4: plat: BL31: Add a check not to stop a boot CPU This commit adds a check so that the boot CPU does not stop. Signed-off-by: Hideyuki Nitta Signed-off-by: Toshiyuki Ogasahara Signed-off-by: Yoshifumi Hosoya --- include/plat/common/platform.h | 11 +++++++++++ lib/psci/psci_main.c | 12 ++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/include/plat/common/platform.h b/include/plat/common/platform.h index 1def86ea7d..762c2eb812 100644 --- a/include/plat/common/platform.h +++ b/include/plat/common/platform.h @@ -349,4 +349,15 @@ int32_t plat_get_soc_revision(void); */ int32_t plat_is_smccc_feature_available(u_register_t fid); +#if PLAT_rcar_gen4 +#define RCAR_MPIDRCHK_NOT_BOOTCPU 1U +#define RCAR_MPIDRCHK_BOOTCPU 0U +/******************************************************************************* + * Check boot_mpidr(CPU0). + * If the CPU is the same as CPU0, return RCAR_MPIDRCHK_BOOTCPU, + * otherwise it returns RCAR_MPIDRCHK_NOT_BOOTCPU. + ******************************************************************************/ +uint32_t bl31_plat_boot_mpidr_chk(void); +#endif + #endif /* PLATFORM_H */ diff --git a/lib/psci/psci_main.c b/lib/psci/psci_main.c index 52a8b8a18b..4054380f15 100644 --- a/lib/psci/psci_main.c +++ b/lib/psci/psci_main.c @@ -199,14 +199,22 @@ int psci_cpu_off(void) { int rc; unsigned int target_pwrlvl = PLAT_MAX_PWR_LVL; +#if defined(PLAT_rcar_gen4) + uint32_t chk = bl31_plat_boot_mpidr_chk(); + if (chk == RCAR_MPIDRCHK_NOT_BOOTCPU) { +#endif /* * Do what is needed to power off this CPU and possible higher power * levels if it able to do so. Upon success, enter the final wfi * which will power down this CPU. */ - rc = psci_do_cpu_off(target_pwrlvl); - + rc = psci_do_cpu_off(target_pwrlvl); +#if defined(PLAT_rcar_gen4) + } else { + rc = PSCI_E_DENIED; + } +#endif /* * The only error cpu_off can return is E_DENIED. So check if that's * indeed the case. From 2c6ce9a3e51b989c8c19f3d4823378e466106983 Mon Sep 17 00:00:00 2001 From: Toshiyuki Ogasahara Date: Fri, 15 Oct 2021 15:29:45 +0900 Subject: [PATCH 3/4] rcar_gen4: plat: BL31: Change the migrate information for OP-TEE This commit fixes the migration information to fit the OP-TEE on R-Car. Signed-off-by: Hideyuki Nitta Signed-off-by: Toshiyuki Ogasahara Signed-off-by: Yoshifumi Hosoya --- services/spd/opteed/opteed_pm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/services/spd/opteed/opteed_pm.c b/services/spd/opteed/opteed_pm.c index 719eeb748d..c2b1054288 100644 --- a/services/spd/opteed/opteed_pm.c +++ b/services/spd/opteed/opteed_pm.c @@ -161,7 +161,12 @@ static void opteed_cpu_suspend_finish_handler(u_register_t max_off_pwrlvl) ******************************************************************************/ static int32_t opteed_cpu_migrate_info(u_register_t *resident_cpu) { +#if defined(PLAT_rcar_gen4) + *resident_cpu = 0U; + return OPTEE_TYPE_UP; +#else return OPTEE_MIGRATE_INFO; +#endif } /******************************************************************************* From 441522672a0d45b9934b9391cb7f9f543822bdb2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 15 Oct 2021 08:42:36 +0000 Subject: [PATCH 4/4] build(deps): bump trim-newlines from 3.0.0 to 3.0.1 Bumps [trim-newlines](https://github.com/sindresorhus/trim-newlines) from 3.0.0 to 3.0.1. - [Release notes](https://github.com/sindresorhus/trim-newlines/releases) - [Commits](https://github.com/sindresorhus/trim-newlines/commits) --- updated-dependencies: - dependency-name: trim-newlines dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4967107988..46d8bf366f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1922,9 +1922,9 @@ } }, "trim-newlines": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.0.tgz", - "integrity": "sha512-C4+gOpvmxaSMKuEf9Qc134F1ZuOHVXKRbtEflf4NTtuuJDEIJ9p5PXsalL8SkeRw+qit1Mo+yuvMPAKwWg/1hA==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", "dev": true }, "trim-off-newlines": {