Skip to content

Commit 1b4db14

Browse files
committed
lk2nd: smp: add msm8994 cpu boot support
Signed-off-by: Eugene Lepshy <fekz115@gmail.com>
1 parent 02ef037 commit 1b4db14

File tree

4 files changed

+231
-0
lines changed

4 files changed

+231
-0
lines changed

lk2nd/smp/cpu-boot.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,23 @@ static uint32_t read_phandle_reg(const void *dtb, int node, const char *prop)
157157
return read_phandle_reg_indexed(dtb, node, prop, 0);
158158
}
159159

160+
#if CPU_BOOT_CORTEX_A_MSM8994
161+
bool boot_msm8994_cpu(const void *dtb, int acc, int node) {
162+
node = lkfdt_lookup_phandle(dtb, node, "next-level-cache");
163+
if (node < 0) {
164+
dprintf(CRITICAL, "Cannot find CPU next-level-cache: %d\n", node);
165+
return false;
166+
}
167+
uint32_t l2ccc_base = read_phandle_reg(dtb, node, "power-domain");
168+
node = lkfdt_lookup_phandle(dtb, node, "power-domain");
169+
uint32_t vctl_base_0 = read_phandle_reg_indexed(dtb, node, "qcom,vctl-node", 0);
170+
uint32_t vctl_base_1 = read_phandle_reg_indexed(dtb, node, "qcom,vctl-node", 1);
171+
uint32_t vctl_val = read_phandle_value(dtb, node, "qcom,vctl-val");
172+
cpu_boot_cortex_a_msm8994(acc, l2ccc_base, vctl_base_0, vctl_base_1, vctl_val);
173+
return true;
174+
}
175+
#endif
176+
160177
bool cpu_boot(const void *dtb, int node, uint32_t mpidr)
161178
{
162179
uint32_t acc, extra_reg __UNUSED;
@@ -182,6 +199,9 @@ bool cpu_boot(const void *dtb, int node, uint32_t mpidr)
182199
*/
183200
extra_reg = read_phandle_reg(dtb, node, "clocks");
184201
cpu_boot_cortex_a(acc, extra_reg);
202+
#elif CPU_BOOT_CORTEX_A_MSM8994
203+
if(!boot_msm8994_cpu(dtb, acc, node))
204+
return false;
185205
#elif CPU_BOOT_KPSSV1
186206
extra_reg = read_phandle_reg(dtb, node, "qcom,saw");
187207
if (!extra_reg)

lk2nd/smp/cpu-boot.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,35 @@
55
int cpu_boot_set_addr(uintptr_t addr, bool arm64);
66

77
bool cpu_boot(const void *dtb, int node, uint32_t mpidr);
8+
9+
/**
10+
* @brief This function boot cpus for msm8994/2 if firmware doesn't
11+
* support pcsi
12+
*
13+
* @note cpu node must contain `next-level-cache`
14+
* @note cache node must contain `power-domain`
15+
* @note power-domain node must contain `qcom,vctl-node`
16+
* and might contain `qcom,vctl-val`
17+
*
18+
* @return true if core successfully booted
19+
*/
20+
bool boot_msm8994_cpu(const void *dtb, int acc, int node);
821
void cpu_boot_cortex_a(uint32_t base, uint32_t apcs_base);
22+
23+
/**
24+
* @brief This function enables core with the address stored in `base`
25+
*
26+
* As l2 cache for first(boot) cluster enabled by lk1st,
27+
* this function skips it and work only for second cluster
28+
*
29+
* @param base value of current cpu reg
30+
* @param l2ccc_base value of l2 clock controller reg
31+
* @param vctl_base_0 first `qcom,vctl-node` reg address
32+
* @param vctl_base_1 second `qcom,vctl-node` reg address
33+
* @param vctl_val The value to be set on the rail
34+
*/
35+
void cpu_boot_cortex_a_msm8994(uint32_t base, uint32_t l2ccc_base,
36+
uint32_t vctl_base_0, uint32_t vctl_base_1, uint32_t vctl_val);
937
void cpu_boot_kpssv1(uint32_t reg, uint32_t saw_reg);
1038
void cpu_boot_kpssv2(uint32_t reg, uint32_t l2_saw_base);
1139

lk2nd/smp/gpl/cortex-a-msm8994.c

Lines changed: 180 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
// SPDX-License-Identifier: GPL-2.0-only
2+
/* Copyright (c) 2023, Eugene Lepshy <fekz115@gmail.com> */
3+
4+
#include <arch/defines.h>
5+
#include <bits.h>
6+
#include <debug.h>
7+
#include <kernel/thread.h>
8+
#include <platform/timer.h>
9+
#include <reg.h>
10+
11+
#include "../cpu-boot.h"
12+
13+
#define CPU_PWR_CTL 0x4
14+
#define APC_PWR_GATE_CTL 0x14
15+
16+
#define L1_RST_DIS 0x284
17+
18+
#define L2_VREG_CTL 0x1c
19+
#define L2_PWR_CTL 0x14
20+
#define L2_PWR_CTL_OVERRIDE 0xc
21+
#define L2_PWR_STATUS_L2_HS_STS_MSM8994 (BIT(9) | BIT(28))
22+
23+
/**
24+
* @brief delay for voltage to settle on the core
25+
*/
26+
#define REGULATOR_SETUP_VOLTAGE_TIMEOUT 2000
27+
28+
/**
29+
* @brief Power on cpu rail before turning on core
30+
* @param vctl_base_0 first `qcom,vctl-node` reg address
31+
* @param vctl_base_1 second `qcom,vctl-node` reg address
32+
* @param vctl_val The value to be set on the rail
33+
*/
34+
static void msm_spm_turn_on_cpu_rail(uint32_t vctl_base_0, uint32_t vctl_base_1,
35+
unsigned int vctl_val)
36+
{
37+
if (vctl_base_1) {
38+
/*
39+
* Program Q2S to disable SPM legacy mode and ignore Q2S
40+
* channel requests.
41+
* bit[1] = qchannel_ignore = 1
42+
* bit[2] = spm_legacy_mode = 0
43+
*/
44+
writel(0x2, vctl_base_1);
45+
dsb();
46+
}
47+
48+
/* Set the CPU supply regulator voltage */
49+
vctl_val = (vctl_val & 0xFF);
50+
writel(vctl_val, vctl_base_0 + L2_VREG_CTL);
51+
dsb();
52+
udelay(REGULATOR_SETUP_VOLTAGE_TIMEOUT);
53+
54+
/* Enable the CPU supply regulator*/
55+
vctl_val = 0x30080;
56+
writel(vctl_val, vctl_base_0 + L2_VREG_CTL);
57+
dsb();
58+
udelay(REGULATOR_SETUP_VOLTAGE_TIMEOUT);
59+
}
60+
61+
/**
62+
* @brief This function used to enable l2 cache
63+
*
64+
* As l2 cache for first(boot) cluster enabled by lk1st,
65+
* this function skips it and work only for second cluster
66+
*
67+
* @param l2ccc_base value of l2 clock controller reg
68+
* @param vctl_base_0 first `qcom,vctl-node` reg address
69+
* @param vctl_base_1 second `qcom,vctl-node` reg address
70+
* @param vctl_val The value to be set on the rail
71+
* @note Function has a check if cache at `l2ccc_base` already enabled
72+
*/
73+
static void power_on_l2_cache_msm8994(uint32_t l2ccc_base, uint32_t vctl_base_0,
74+
uint32_t vctl_base_1, uint32_t vctl_val) {
75+
/* Skip if cluster L2 is already powered on */
76+
if (readl(l2ccc_base + L2_PWR_CTL) & L2_PWR_STATUS_L2_HS_STS_MSM8994)
77+
return;
78+
79+
msm_spm_turn_on_cpu_rail(vctl_base_0, vctl_base_1, vctl_val);
80+
81+
dprintf(INFO, "Powering on L2 cache @ %#08x\n", l2ccc_base);
82+
83+
enter_critical_section();
84+
85+
/* Enable L1 invalidation by h/w */
86+
writel(0x00000000, l2ccc_base + L1_RST_DIS);
87+
dsb();
88+
89+
/* Assert PRESETDBGn */
90+
writel(0x00400000 , l2ccc_base + L2_PWR_CTL_OVERRIDE);
91+
dsb();
92+
93+
/* Close L2/SCU Logic GDHS and power up the cache */
94+
writel(0x00029716 , l2ccc_base + L2_PWR_CTL);
95+
dsb();
96+
udelay(8);
97+
98+
/* De-assert L2/SCU memory Clamp */
99+
writel(0x00023716 , l2ccc_base + L2_PWR_CTL);
100+
dsb();
101+
102+
/* Wakeup L2/SCU RAMs by deasserting sleep signals */
103+
writel(0x0002371E , l2ccc_base + L2_PWR_CTL);
104+
dsb();
105+
udelay(8);
106+
107+
/* Un-gate clock and wait for sequential waking up
108+
* of L2 rams with a delay of 2*X0 cycles
109+
*/
110+
writel(0x0002371C , l2ccc_base + L2_PWR_CTL);
111+
dsb();
112+
udelay(4);
113+
114+
/* De-assert L2/SCU logic clamp */
115+
writel(0x0002361C , l2ccc_base + L2_PWR_CTL);
116+
dsb();
117+
udelay(2);
118+
119+
/* De-assert L2/SCU logic reset */
120+
writel(0x00022218 , l2ccc_base + L2_PWR_CTL);
121+
dsb();
122+
udelay(4);
123+
124+
/* Turn on the PMIC_APC */
125+
writel(0x10022218 , l2ccc_base + L2_PWR_CTL);
126+
dsb();
127+
128+
/* De-assert PRESETDBGn */
129+
writel(0x00000000 , l2ccc_base + L2_PWR_CTL_OVERRIDE);
130+
dsb();
131+
exit_critical_section();
132+
}
133+
134+
void cpu_boot_cortex_a_msm8994(uint32_t base, uint32_t l2ccc_base,
135+
uint32_t vctl_base_0, uint32_t vctl_base_1, uint32_t vctl_val)
136+
{
137+
if (l2ccc_base)
138+
power_on_l2_cache_msm8994(l2ccc_base, vctl_base_0, vctl_base_1, vctl_val);
139+
140+
enter_critical_section();
141+
142+
/* Assert head switch enable few */
143+
writel(0x00000001, base + APC_PWR_GATE_CTL);
144+
dsb();
145+
udelay(1);
146+
147+
/* Assert head switch enable rest */
148+
writel(0x00000003, base + APC_PWR_GATE_CTL);
149+
dsb();
150+
udelay(1);
151+
152+
/* De-assert coremem clamp. This is asserted by default */
153+
writel(0x00000079, base + CPU_PWR_CTL);
154+
dsb();
155+
udelay(2);
156+
157+
/* Close coremem array gdhs */
158+
writel(0x0000007D, base + CPU_PWR_CTL);
159+
dsb();
160+
udelay(2);
161+
162+
/* De-assert clamp */
163+
writel(0x0000003D, base + CPU_PWR_CTL);
164+
dsb();
165+
166+
/* De-assert clamp */
167+
writel(0x0000003C, base + CPU_PWR_CTL);
168+
dsb();
169+
udelay(1);
170+
171+
/* De-assert core0 reset */
172+
writel(0x0000000C, base + CPU_PWR_CTL);
173+
dsb();
174+
175+
/* Assert PWRDUP */
176+
writel(0x0000008C, base + CPU_PWR_CTL);
177+
dsb();
178+
179+
exit_critical_section();
180+
}

lk2nd/smp/rules.mk

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ OBJS += $(patsubst %.c,%.o, $(wildcard $(LOCAL_DIR)/clock-$(PLATFORM).c))
88
ifneq ($(filter msm8226 msm8610 msm8909 msm8916, $(PLATFORM)),)
99
CPU_BOOT_OBJ := $(LOCAL_DIR)/cortex-a.o
1010
DEFINES += CPU_BOOT_CORTEX_A=1
11+
else ifneq ($(filter msm8994, $(PLATFORM)),)
12+
CPU_BOOT_OBJ := $(if $(BUILD_GPL), $(LOCAL_DIR)/gpl/cortex-a-msm8994.o)
13+
DEFINES += CPU_BOOT_CORTEX_A_MSM8994=1
1114
else ifneq ($(filter apq8084 msm8974, $(PLATFORM)),)
1215
CPU_BOOT_OBJ := $(if $(BUILD_GPL), $(LOCAL_DIR)/gpl/krait.o)
1316
DEFINES += CPU_BOOT_KPSSV2=1

0 commit comments

Comments
 (0)