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