blob: 350ed5c49cf4c53ac9549ea885c30462c5b464b2 [file] [log] [blame]
Stephan Gerhold4bc53a12022-08-28 15:18:55 +02001/*
2 * Copyright (c) 2021-2023, Stephan Gerhold <stephan@gerhold.net>
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8
9#include <arch.h>
10#include <lib/mmio.h>
11
12#include "msm8916_config.h"
13#include "msm8916_gicv2.h"
14#include <msm8916_mmap.h>
15#include <platform_def.h>
16
17static void msm8916_configure_timer(void)
18{
19 /* Set timer frequency */
20 mmio_write_32(APCS_QTMR + CNTCTLBASE_CNTFRQ, PLAT_SYSCNT_FREQ);
21
22 /* Make all timer frames available to non-secure world */
23 mmio_write_32(APCS_QTMR + CNTNSAR, GENMASK_32(7, 0));
24}
25
26/*
27 * The APCS register regions always start with a SECURE register that should
28 * be cleared to 0 to only allow secure access. Since BL31 handles most of
29 * the CPU power management, most of them can be cleared to secure access only.
30 */
31#define APCS_GLB_SECURE_STS_NS BIT_32(0)
32#define APCS_GLB_SECURE_PWR_NS BIT_32(1)
33#define APCS_BOOT_START_ADDR_SEC (APCS_CFG + 0x04)
34#define REMAP_EN BIT_32(0)
35#define APCS_AA64NAA32_REG (APCS_CFG + 0x0c)
36
37static void msm8916_configure_cpu_pm(void)
38{
39 unsigned int cpu;
40
41 /* Disallow non-secure access to boot remapper / TCM registers */
42 mmio_write_32(APCS_CFG, 0);
43
44 /*
45 * Disallow non-secure access to power management registers.
46 * However, allow STS and PWR since those also seem to control access
47 * to CPU frequency related registers (e.g. APCS_CMD_RCGR). If these
48 * bits are not set, CPU frequency control fails in the non-secure world.
49 */
50 mmio_write_32(APCS_GLB, APCS_GLB_SECURE_STS_NS | APCS_GLB_SECURE_PWR_NS);
51
52 /* Disallow non-secure access to L2 SAW2 */
53 mmio_write_32(APCS_L2_SAW2, 0);
54
55 /* Disallow non-secure access to CPU ACS and SAW2 */
56 for (cpu = 0; cpu < PLATFORM_CORE_COUNT; cpu++) {
57 mmio_write_32(APCS_ALIAS_ACS(cpu), 0);
58 mmio_write_32(APCS_ALIAS_SAW2(cpu), 0);
59 }
60
Stephan Gerholdb68e4e92022-08-28 15:18:55 +020061#ifdef __aarch64__
Stephan Gerhold4bc53a12022-08-28 15:18:55 +020062 /* Make sure all further warm boots end up in BL31 and aarch64 state */
63 CASSERT((BL31_BASE & 0xffff) == 0, assert_bl31_base_64k_aligned);
64 mmio_write_32(APCS_BOOT_START_ADDR_SEC, BL31_BASE | REMAP_EN);
65 mmio_write_32(APCS_AA64NAA32_REG, 1);
Stephan Gerholdb68e4e92022-08-28 15:18:55 +020066#else
67 /* Make sure all further warm boots end up in BL32 */
68 CASSERT((BL32_BASE & 0xffff) == 0, assert_bl32_base_64k_aligned);
69 mmio_write_32(APCS_BOOT_START_ADDR_SEC, BL32_BASE | REMAP_EN);
70#endif
Stephan Gerhold4bc53a12022-08-28 15:18:55 +020071}
72
73/*
74 * MSM8916 has a special "interrupt aggregation logic" in the APPS SMMU,
75 * which allows routing context bank interrupts to one of 3 interrupt numbers
76 * ("TZ/HYP/NS"). Route all interrupts to the non-secure interrupt number
77 * by default to avoid special setup on the non-secure side.
78 */
79#define CLK_OFF BIT_32(31)
80#define GCC_SMMU_CFG_CBCR (GCC_BASE + 0x12038)
81#define GCC_APCS_SMMU_CLOCK_BRANCH_ENA_VOTE (GCC_BASE + 0x4500c)
82#define SMMU_CFG_CLK_ENA BIT_32(12)
83#define APPS_SMMU_INTR_SEL_NS (APPS_SMMU_QCOM + 0x2000)
84#define APPS_SMMU_INTR_SEL_NS_EN_ALL U(0xffffffff)
85
86static void msm8916_configure_smmu(void)
87{
88 /* Enable SMMU configuration clock to enable register access */
89 mmio_setbits_32(GCC_APCS_SMMU_CLOCK_BRANCH_ENA_VOTE, SMMU_CFG_CLK_ENA);
90 while (mmio_read_32(GCC_SMMU_CFG_CBCR) & CLK_OFF)
91 ;
92
93 /* Route all context bank interrupts to non-secure interrupt */
94 mmio_write_32(APPS_SMMU_INTR_SEL_NS, APPS_SMMU_INTR_SEL_NS_EN_ALL);
95
96 /* Disable configuration clock again */
97 mmio_clrbits_32(GCC_APCS_SMMU_CLOCK_BRANCH_ENA_VOTE, SMMU_CFG_CLK_ENA);
98}
99
100void msm8916_configure(void)
101{
102 msm8916_gicv2_configure();
103 msm8916_configure_timer();
104 msm8916_configure_cpu_pm();
105 msm8916_configure_smmu();
106}