feat(msm8916): setup hardware for non-secure world
Booting e.g. Linux in the non-secure world does not work with the msm8916 port yet because essential hardware is not made available to the non-secure world. Add more platform initialization to: - Initialize the GICv2 and mark secure interrupts. Only secure SGIs/PPIs so far. Override the GICD_PIDR2_GICV2 register address in platform_def.h to avoid a failing assert() because of a (hardware) mistake in Qualcomm's GICv2 implementation. - Make a timer frame available to the non-secure world. The "Qualcomm Timer" (QTMR) implements the ARM generic timer specification, so the standard defines (CNTACR_BASE etc) can be used. - Make parts of the "APCS" register region available to the non-secure world, e.g. for CPU frequency control implemented in Linux. - Initialize a platform-specific register to route all SMMU context bank interrupts to the non-secure interrupt pin, since all control of the SMMUs is left up to the non-secure world for now. Change-Id: Icf676437b8e329dead06658e177107dfd0ba4f9d Signed-off-by: Stephan Gerhold <stephan@gerhold.net>
This commit is contained in:
parent
a7521bd5d8
commit
af6447315c
|
@ -20,6 +20,9 @@
|
|||
|
||||
#define GCC_BASE (PCNOC_BASE + 0x1800000)
|
||||
|
||||
#define APPS_SMMU_BASE (PCNOC_BASE + 0x1e00000)
|
||||
#define APPS_SMMU_QCOM (APPS_SMMU_BASE + 0xf0000)
|
||||
|
||||
#define BLSP_UART1_BASE (PCNOC_BASE + 0x78af000)
|
||||
#define BLSP_UART2_BASE (PCNOC_BASE + 0x78b0000)
|
||||
|
||||
|
|
|
@ -47,4 +47,11 @@
|
|||
/* Timer frequency */
|
||||
#define PLAT_SYSCNT_FREQ 19200000
|
||||
|
||||
/*
|
||||
* The Qualcomm QGIC2 implementation seems to have PIDR0-4 and PIDR4-7
|
||||
* erroneously swapped for some reason. PIDR2 is actually at 0xFD8.
|
||||
* Override the address in <drivers/arm/gicv2.h> to avoid a failing assert().
|
||||
*/
|
||||
#define GICD_PIDR2_GICV2 U(0xFD8)
|
||||
|
||||
#endif /* PLATFORM_DEF_H */
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <lib/xlat_tables/xlat_tables_v2.h>
|
||||
#include <plat/common/platform.h>
|
||||
|
||||
#include "msm8916_gicv2.h"
|
||||
#include <msm8916_mmap.h>
|
||||
#include <platform_def.h>
|
||||
#include <uartdm_console.h>
|
||||
|
@ -113,9 +114,87 @@ void bl31_plat_arch_setup(void)
|
|||
enable_mmu_el3(0);
|
||||
}
|
||||
|
||||
static void msm8916_configure_timer(void)
|
||||
{
|
||||
/* Set timer frequency */
|
||||
mmio_write_32(APCS_QTMR + CNTCTLBASE_CNTFRQ, plat_get_syscnt_freq2());
|
||||
|
||||
/* Make frame 0 available to non-secure world */
|
||||
mmio_write_32(APCS_QTMR + CNTNSAR, BIT_32(CNTNSAR_NS_SHIFT(0)));
|
||||
mmio_write_32(APCS_QTMR + CNTACR_BASE(0),
|
||||
BIT_32(CNTACR_RPCT_SHIFT) | BIT_32(CNTACR_RVCT_SHIFT) |
|
||||
BIT_32(CNTACR_RFRQ_SHIFT) | BIT_32(CNTACR_RVOFF_SHIFT) |
|
||||
BIT_32(CNTACR_RWVT_SHIFT) | BIT_32(CNTACR_RWPT_SHIFT));
|
||||
}
|
||||
|
||||
/*
|
||||
* The APCS register regions always start with a SECURE register that should
|
||||
* be cleared to 0 to only allow secure access. Since BL31 handles most of
|
||||
* the CPU power management, most of them can be cleared to secure access only.
|
||||
*/
|
||||
#define APCS_GLB_SECURE_STS_NS BIT_32(0)
|
||||
#define APCS_GLB_SECURE_PWR_NS BIT_32(1)
|
||||
|
||||
static void msm8916_configure_cpu_pm(void)
|
||||
{
|
||||
unsigned int cpu;
|
||||
|
||||
/* Disallow non-secure access to boot remapper / TCM registers */
|
||||
mmio_write_32(APCS_CFG, 0);
|
||||
|
||||
/*
|
||||
* Disallow non-secure access to power management registers.
|
||||
* However, allow STS and PWR since those also seem to control access
|
||||
* to CPU frequency related registers (e.g. APCS_CMD_RCGR). If these
|
||||
* bits are not set, CPU frequency control fails in the non-secure world.
|
||||
*/
|
||||
mmio_write_32(APCS_GLB, APCS_GLB_SECURE_STS_NS | APCS_GLB_SECURE_PWR_NS);
|
||||
|
||||
/* Disallow non-secure access to L2 SAW2 */
|
||||
mmio_write_32(APCS_L2_SAW2, 0);
|
||||
|
||||
/* Disallow non-secure access to CPU ACS and SAW2 */
|
||||
for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) {
|
||||
mmio_write_32(APCS_ALIAS_ACS(cpu), 0);
|
||||
mmio_write_32(APCS_ALIAS_SAW2(cpu), 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* MSM8916 has a special "interrupt aggregation logic" in the APPS SMMU,
|
||||
* which allows routing context bank interrupts to one of 3 interrupt numbers
|
||||
* ("TZ/HYP/NS"). Route all interrupts to the non-secure interrupt number
|
||||
* by default to avoid special setup on the non-secure side.
|
||||
*/
|
||||
#define GCC_SMMU_CFG_CBCR (GCC_BASE + 0x12038)
|
||||
#define GCC_APCS_SMMU_CLOCK_BRANCH_ENA_VOTE (GCC_BASE + 0x4500c)
|
||||
#define SMMU_CFG_CLK_ENA BIT_32(12)
|
||||
#define APPS_SMMU_INTR_SEL_NS (APPS_SMMU_QCOM + 0x2000)
|
||||
#define APPS_SMMU_INTR_SEL_NS_EN_ALL U(0xffffffff)
|
||||
|
||||
static void msm8916_configure_smmu(void)
|
||||
{
|
||||
/* Enable SMMU configuration clock to enable register access */
|
||||
mmio_setbits_32(GCC_APCS_SMMU_CLOCK_BRANCH_ENA_VOTE, SMMU_CFG_CLK_ENA);
|
||||
while (mmio_read_32(GCC_SMMU_CFG_CBCR) & CLK_OFF)
|
||||
;
|
||||
|
||||
/* Route all context bank interrupts to non-secure interrupt */
|
||||
mmio_write_32(APPS_SMMU_INTR_SEL_NS, APPS_SMMU_INTR_SEL_NS_EN_ALL);
|
||||
|
||||
/* Disable configuration clock again */
|
||||
mmio_clrbits_32(GCC_APCS_SMMU_CLOCK_BRANCH_ENA_VOTE, SMMU_CFG_CLK_ENA);
|
||||
}
|
||||
|
||||
void bl31_platform_setup(void)
|
||||
{
|
||||
INFO("BL31: Platform setup start\n");
|
||||
generic_delay_timer_init();
|
||||
msm8916_configure_timer();
|
||||
msm8916_gicv2_init();
|
||||
msm8916_configure_cpu_pm();
|
||||
msm8916_configure_smmu();
|
||||
INFO("BL31: Platform setup done\n");
|
||||
}
|
||||
|
||||
entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t type)
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <common/debug.h>
|
||||
#include <drivers/arm/gicv2.h>
|
||||
#include <lib/mmio.h>
|
||||
|
||||
#include "msm8916_gicv2.h"
|
||||
#include <msm8916_mmap.h>
|
||||
|
||||
#define IRQ_SEC_SGI_0 8
|
||||
#define IRQ_SEC_SGI_1 9
|
||||
#define IRQ_SEC_SGI_2 10
|
||||
#define IRQ_SEC_SGI_3 11
|
||||
#define IRQ_SEC_SGI_4 12
|
||||
#define IRQ_SEC_SGI_5 13
|
||||
#define IRQ_SEC_SGI_6 14
|
||||
#define IRQ_SEC_SGI_7 15
|
||||
|
||||
#define IRQ_SEC_PHY_TIMER (16 + 2) /* PPI #2 */
|
||||
|
||||
static const interrupt_prop_t msm8916_interrupt_props[] = {
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_0, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_1, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_2, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_3, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_4, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_5, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_6, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_SGI_7, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
INTR_PROP_DESC(IRQ_SEC_PHY_TIMER, GIC_HIGHEST_SEC_PRIORITY,
|
||||
GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL),
|
||||
};
|
||||
|
||||
static const gicv2_driver_data_t msm8916_gic_data = {
|
||||
.gicd_base = APCS_QGIC2_GICD,
|
||||
.gicc_base = APCS_QGIC2_GICC,
|
||||
.interrupt_props = msm8916_interrupt_props,
|
||||
.interrupt_props_num = ARRAY_SIZE(msm8916_interrupt_props),
|
||||
};
|
||||
|
||||
void msm8916_gicv2_init(void)
|
||||
{
|
||||
gicv2_driver_init(&msm8916_gic_data);
|
||||
gicv2_distif_init();
|
||||
gicv2_pcpu_distif_init();
|
||||
gicv2_cpuif_enable();
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
/*
|
||||
* Copyright (c) 2021, Stephan Gerhold <stephan@gerhold.net>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef MSM8916_GICV2_H
|
||||
#define MSM8916_GICV2_H
|
||||
|
||||
void msm8916_gicv2_init(void);
|
||||
|
||||
#endif /* MSM8916_GICV2_H */
|
|
@ -19,6 +19,7 @@ BL31_SOURCES += ${GICV2_SOURCES} \
|
|||
plat/common/plat_gicv2.c \
|
||||
plat/common/plat_psci_common.c \
|
||||
plat/qti/msm8916/msm8916_bl31_setup.c \
|
||||
plat/qti/msm8916/msm8916_gicv2.c \
|
||||
plat/qti/msm8916/msm8916_pm.c \
|
||||
plat/qti/msm8916/msm8916_topology.c \
|
||||
plat/qti/msm8916/${ARCH}/msm8916_helpers.S \
|
||||
|
|
Loading…
Reference in New Issue