1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "sgm776_pik.h"
9 #include "sgm776_pik_cpu.h"
10 #include "sgm776_pik_gpu.h"
11 #include "sgm776_pik_system.h"
12 #include "system_clock.h"
13
14 #include <mod_pik_clock.h>
15 #include <mod_sid.h>
16
17 #include <fwk_assert.h>
18 #include <fwk_element.h>
19 #include <fwk_id.h>
20 #include <fwk_macros.h>
21 #include <fwk_module.h>
22 #include <fwk_status.h>
23
24 #include <stdbool.h>
25 #include <stddef.h>
26
27 /*
28 * Rate lookup tables.
29 */
30
31 static const struct mod_pik_clock_rate rate_table_sys_nocmemclk[] = {
32 {
33 .rate = 720 * FWK_MHZ,
34 .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK,
35 .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS,
36 .divider = CLOCK_RATE_SYSPLLCLK / (720 * FWK_MHZ),
37 },
38 };
39
40 static const struct mod_pik_clock_rate rate_table_sys_fcmclk[] = {
41 {
42 .rate = 1800 * FWK_MHZ,
43 .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK,
44 .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS,
45 .divider = CLOCK_RATE_SYSPLLCLK / (1800 * FWK_MHZ),
46 },
47 };
48
49 static const struct mod_pik_clock_rate rate_table_sys_gicclk[] = {
50 {
51 .rate = 600 * FWK_MHZ,
52 .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK,
53 .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS,
54 .divider = CLOCK_RATE_SYSPLLCLK / (600 * FWK_MHZ),
55 },
56 };
57
58 static const struct mod_pik_clock_rate rate_table_sys_pclkscp[] = {
59 {
60 .rate = 225 * FWK_MHZ,
61 .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK,
62 .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS,
63 .divider = CLOCK_RATE_SYSPLLCLK / (225 * FWK_MHZ),
64 },
65 };
66
67 static const struct mod_pik_clock_rate rate_table_sys_sysperclk[] = {
68 {
69 .rate = 225 * FWK_MHZ,
70 .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK,
71 .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS,
72 .divider = CLOCK_RATE_SYSPLLCLK / (225 * FWK_MHZ),
73 },
74 };
75
76 static const struct mod_pik_clock_rate rate_table_cpu_a55[] = {
77 {
78 .rate = 2200 * FWK_MHZ,
79 .source = MOD_PIK_CLOCK_CLUSCLK_SOURCE_PLL0,
80 .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_EXT,
81 .divider = 1, /* Rate adjusted via CPU PLL */
82 },
83 };
84
85 static const struct mod_pik_clock_rate rate_table_cpu_a75[] = {
86 {
87 .rate = 2700 * FWK_MHZ,
88 .source = MOD_PIK_CLOCK_CLUSCLK_SOURCE_PLL1,
89 .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_EXT,
90 .divider = 1, /* Rate adjusted via CPU PLL */
91 },
92 };
93
94 static const struct mod_pik_clock_rate rate_table_gpu[] = {
95 {
96 .rate = 800 * FWK_MHZ,
97 .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_PRIVPLLCLK,
98 .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_EXT,
99 .divider = 1, /* Rate adjusted via GPU PLL */
100 },
101 };
102
103 static const struct fwk_element pik_clock_element_table[] = {
104 /*
105 * System Clocks
106 */
107 {
108 .name = "SYS_NOCMEMCLK",
109 .data = &((struct mod_pik_clock_dev_config) {
110 .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE,
111 .is_group_member = false,
112 .control_reg = &PIK_SYSTEM->NOCMEMCLK_CTRL,
113 .divsys_reg = &PIK_SYSTEM->NOCMEMCLK_DIV1,
114 .rate_table = rate_table_sys_nocmemclk,
115 .rate_count = FWK_ARRAY_SIZE(rate_table_sys_nocmemclk),
116 .initial_rate = 720 * FWK_MHZ,
117 .defer_initialization = true,
118 }),
119 },
120 {
121 .name = "SYS_FCMCLK",
122 .data = &((struct mod_pik_clock_dev_config) {
123 .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE,
124 .is_group_member = false,
125 .control_reg = &PIK_SYSTEM->FCMCLK_CTRL,
126 .divsys_reg = &PIK_SYSTEM->FCMCLK_DIV1,
127 .rate_table = rate_table_sys_fcmclk,
128 .rate_count = FWK_ARRAY_SIZE(rate_table_sys_fcmclk),
129 .initial_rate = 1800 * FWK_MHZ,
130 .defer_initialization = true,
131 }),
132 },
133 {
134 .name = "SYS_GICCLK",
135 .data = &((struct mod_pik_clock_dev_config) {
136 .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE,
137 .is_group_member = false,
138 .control_reg = &PIK_SYSTEM->GICCLK_CTRL,
139 .divsys_reg = &PIK_SYSTEM->GICCLK_DIV1,
140 .rate_table = rate_table_sys_gicclk,
141 .rate_count = FWK_ARRAY_SIZE(rate_table_sys_gicclk),
142 .initial_rate = 600 * FWK_MHZ,
143 .defer_initialization = true,
144 }),
145 },
146 {
147 .name = "SYS_PCLKSCP",
148 .data = &((struct mod_pik_clock_dev_config) {
149 .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE,
150 .is_group_member = false,
151 .control_reg = &PIK_SYSTEM->PCLKSCP_CTRL,
152 .divsys_reg = &PIK_SYSTEM->PCLKSCP_DIV1,
153 .rate_table = rate_table_sys_pclkscp,
154 .rate_count = FWK_ARRAY_SIZE(rate_table_sys_pclkscp),
155 .initial_rate = 225 * FWK_MHZ,
156 .defer_initialization = true,
157 }),
158 },
159 {
160 .name = "SYS_SYSPERCLK",
161 .data = &((struct mod_pik_clock_dev_config) {
162 .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE,
163 .is_group_member = false,
164 .control_reg = &PIK_SYSTEM->SYSPERCLK_CTRL,
165 .divsys_reg = &PIK_SYSTEM->SYSPERCLK_DIV1,
166 .rate_table = rate_table_sys_sysperclk,
167 .rate_count = FWK_ARRAY_SIZE(rate_table_sys_sysperclk),
168 .initial_rate = 225 * FWK_MHZ,
169 .defer_initialization = true,
170 }),
171 },
172 /*
173 * Cluster 0 CPUs
174 */
175 {
176 .name = "CLUS0_CPU0",
177 .data = &((struct mod_pik_clock_dev_config) {
178 .type = MOD_PIK_CLOCK_TYPE_CLUSTER,
179 .is_group_member = true,
180 .control_reg = &PIK_CLUS0->CORECLK[0].CTRL,
181 .divext_reg = &PIK_CLUS0->CORECLK[0].DIV,
182 .modulator_reg = &PIK_CLUS0->CORECLK[0].MOD,
183 .initial_rate = 2200 * FWK_MHZ,
184 .defer_initialization = true,
185 }),
186 },
187 {
188 .name = "CLUS0_CPU1",
189 .data = &((struct mod_pik_clock_dev_config) {
190 .type = MOD_PIK_CLOCK_TYPE_CLUSTER,
191 .is_group_member = true,
192 .control_reg = &PIK_CLUS0->CORECLK[1].CTRL,
193 .divext_reg = &PIK_CLUS0->CORECLK[1].DIV,
194 .modulator_reg = &PIK_CLUS0->CORECLK[1].MOD,
195 .initial_rate = 2200 * FWK_MHZ,
196 .defer_initialization = true,
197 }),
198 },
199 {
200 .name = "CLUS0_CPU2",
201 .data = &((struct mod_pik_clock_dev_config) {
202 .type = MOD_PIK_CLOCK_TYPE_CLUSTER,
203 .is_group_member = true,
204 .control_reg = &PIK_CLUS0->CORECLK[2].CTRL,
205 .divext_reg = &PIK_CLUS0->CORECLK[2].DIV,
206 .modulator_reg = &PIK_CLUS0->CORECLK[2].MOD,
207 .initial_rate = 2200 * FWK_MHZ,
208 .defer_initialization = true,
209 }),
210 },
211 {
212 .name = "CLUS0_CPU3",
213 .data = &((struct mod_pik_clock_dev_config) {
214 .type = MOD_PIK_CLOCK_TYPE_CLUSTER,
215 .is_group_member = true,
216 .control_reg = &PIK_CLUS0->CORECLK[3].CTRL,
217 .divext_reg = &PIK_CLUS0->CORECLK[3].DIV,
218 .modulator_reg = &PIK_CLUS0->CORECLK[3].MOD,
219 .initial_rate = 2200 * FWK_MHZ,
220 .defer_initialization = true,
221 }),
222 },
223 {
224 .name = "CLUS0_CPU4",
225 .data = &((struct mod_pik_clock_dev_config) {
226 .type = MOD_PIK_CLOCK_TYPE_CLUSTER,
227 .is_group_member = true,
228 .control_reg = &PIK_CLUS0->CORECLK[4].CTRL,
229 .divext_reg = &PIK_CLUS0->CORECLK[4].DIV,
230 .modulator_reg = &PIK_CLUS0->CORECLK[4].MOD,
231 .initial_rate = 2700 * FWK_MHZ,
232 .defer_initialization = true,
233 }),
234 },
235 {
236 .name = "CLUS0_CPU5",
237 .data = &((struct mod_pik_clock_dev_config) {
238 .type = MOD_PIK_CLOCK_TYPE_CLUSTER,
239 .is_group_member = true,
240 .control_reg = &PIK_CLUS0->CORECLK[5].CTRL,
241 .divext_reg = &PIK_CLUS0->CORECLK[5].DIV,
242 .modulator_reg = &PIK_CLUS0->CORECLK[5].MOD,
243 .initial_rate = 2700 * FWK_MHZ,
244 .defer_initialization = true,
245 }),
246 },
247 {
248 .name = "CLUS0_CPU6",
249 .data = &((struct mod_pik_clock_dev_config) {
250 .type = MOD_PIK_CLOCK_TYPE_CLUSTER,
251 .is_group_member = true,
252 .control_reg = &PIK_CLUS0->CORECLK[6].CTRL,
253 .divext_reg = &PIK_CLUS0->CORECLK[6].DIV,
254 .modulator_reg = &PIK_CLUS0->CORECLK[6].MOD,
255 .initial_rate = 2700 * FWK_MHZ,
256 .defer_initialization = true,
257 }),
258 },
259 {
260 .name = "CLUS0_CPU7",
261 .data = &((struct mod_pik_clock_dev_config) {
262 .type = MOD_PIK_CLOCK_TYPE_CLUSTER,
263 .is_group_member = true,
264 .control_reg = &PIK_CLUS0->CORECLK[7].CTRL,
265 .divext_reg = &PIK_CLUS0->CORECLK[7].DIV,
266 .modulator_reg = &PIK_CLUS0->CORECLK[7].MOD,
267 .initial_rate = 2700 * FWK_MHZ,
268 .defer_initialization = true,
269 }),
270 },
271 /*
272 * GPU
273 */
274 {
275 .name = "GPU",
276 .data = &((struct mod_pik_clock_dev_config) {
277 .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE,
278 .is_group_member = true,
279 .control_reg = &PIK_GPU->GPUCLK_CTRL,
280 .divsys_reg = &PIK_GPU->GPUCLK_DIV1,
281 .divext_reg = &PIK_GPU->GPUCLK_DIV2,
282 .rate_table = rate_table_gpu,
283 .rate_count = FWK_ARRAY_SIZE(rate_table_gpu),
284 .initial_rate = 800 * FWK_MHZ,
285 .defer_initialization = true,
286 }),
287 },
288 { 0 }, /* Termination description. */
289 };
290
pik_clock_get_element_table(fwk_id_t module_id)291 static const struct fwk_element *pik_clock_get_element_table
292 (fwk_id_t module_id)
293 {
294 int status;
295 int element_idx;
296 struct mod_pik_clock_dev_config *config;
297 const struct mod_sid_info *system_info;
298
299 status = mod_sid_get_system_info(&system_info);
300 fwk_assert(status == FWK_SUCCESS);
301
302 switch (system_info->config_number) {
303 case 1:
304 case 5:
305 case 7:
306 case 8:
307 /* CPUs 0-5: Little */
308 for (element_idx = 5; element_idx < 11; element_idx++) {
309 config = (struct mod_pik_clock_dev_config *)
310 pik_clock_element_table[element_idx].data;
311 config->rate_table = rate_table_cpu_a55;
312 config->rate_count = FWK_ARRAY_SIZE(rate_table_cpu_a55);
313 }
314 /* CPUs 6-7: Big */
315 for (element_idx = 11; element_idx < 13; element_idx++) {
316 config = (struct mod_pik_clock_dev_config *)
317 pik_clock_element_table[element_idx].data;
318 config->rate_table = rate_table_cpu_a75;
319 config->rate_count = FWK_ARRAY_SIZE(rate_table_cpu_a75);
320 }
321 break;
322 case 2:
323 case 3:
324 case 4:
325 case 6:
326 /* CPUs 0-3: Little */
327 for (element_idx = 5; element_idx < 9; element_idx++) {
328 config = (struct mod_pik_clock_dev_config *)
329 pik_clock_element_table[element_idx].data;
330 config->rate_table = rate_table_cpu_a55;
331 config->rate_count = FWK_ARRAY_SIZE(rate_table_cpu_a55);
332 }
333 /* CPUs 4-7: Big */
334 for (element_idx = 9; element_idx < 13; element_idx++) {
335 config = (struct mod_pik_clock_dev_config *)
336 pik_clock_element_table[element_idx].data;
337 config->rate_table = rate_table_cpu_a75;
338 config->rate_count = FWK_ARRAY_SIZE(rate_table_cpu_a75);
339 }
340 break;
341 default:
342 return NULL;
343 }
344
345 return pik_clock_element_table;
346 }
347
348 const struct fwk_module_config config_pik_clock = {
349 .elements = FWK_MODULE_DYNAMIC_ELEMENTS(pik_clock_get_element_table),
350 };
351