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
+ }
0 commit comments