blob: 5015610c0eefef61e22cf61359aeccd6608769ce [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
61 /* Make sure all further warm boots end up in BL31 and aarch64 state */
62 CASSERT((BL31_BASE & 0xffff) == 0, assert_bl31_base_64k_aligned);
63 mmio_write_32(APCS_BOOT_START_ADDR_SEC, BL31_BASE | REMAP_EN);
64 mmio_write_32(APCS_AA64NAA32_REG, 1);
65}
66
67/*
68 * MSM8916 has a special "interrupt aggregation logic" in the APPS SMMU,
69 * which allows routing context bank interrupts to one of 3 interrupt numbers
70 * ("TZ/HYP/NS"). Route all interrupts to the non-secure interrupt number
71 * by default to avoid special setup on the non-secure side.
72 */
73#define CLK_OFF BIT_32(31)
74#define GCC_SMMU_CFG_CBCR (GCC_BASE + 0x12038)
75#define GCC_APCS_SMMU_CLOCK_BRANCH_ENA_VOTE (GCC_BASE + 0x4500c)
76#define SMMU_CFG_CLK_ENA BIT_32(12)
77#define APPS_SMMU_INTR_SEL_NS (APPS_SMMU_QCOM + 0x2000)
78#define APPS_SMMU_INTR_SEL_NS_EN_ALL U(0xffffffff)
79
80static void msm8916_configure_smmu(void)
81{
82 /* Enable SMMU configuration clock to enable register access */
83 mmio_setbits_32(GCC_APCS_SMMU_CLOCK_BRANCH_ENA_VOTE, SMMU_CFG_CLK_ENA);
84 while (mmio_read_32(GCC_SMMU_CFG_CBCR) & CLK_OFF)
85 ;
86
87 /* Route all context bank interrupts to non-secure interrupt */
88 mmio_write_32(APPS_SMMU_INTR_SEL_NS, APPS_SMMU_INTR_SEL_NS_EN_ALL);
89
90 /* Disable configuration clock again */
91 mmio_clrbits_32(GCC_APCS_SMMU_CLOCK_BRANCH_ENA_VOTE, SMMU_CFG_CLK_ENA);
92}
93
94void msm8916_configure(void)
95{
96 msm8916_gicv2_configure();
97 msm8916_configure_timer();
98 msm8916_configure_cpu_pm();
99 msm8916_configure_smmu();
100}