1 /*
2  * Arm SCP/MCP Software
3  * Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "config_clock.h"
9 #include "scp_sgi575_pik.h"
10 #include "sgi575_pik_cpu.h"
11 #include "sgi575_pik_scp.h"
12 #include "sgi575_pik_system.h"
13 #include "system_clock.h"
14 
15 #include <mod_pik_clock.h>
16 
17 #include <fwk_element.h>
18 #include <fwk_id.h>
19 #include <fwk_macros.h>
20 #include <fwk_module.h>
21 
22 #include <stdbool.h>
23 
24 /*
25  * Rate lookup tables
26  */
27 
28 static struct mod_pik_clock_rate rate_table_cpu_group_0[] = {
29     {
30         .rate = 2600 * FWK_MHZ,
31         .source = MOD_PIK_CLOCK_CLUSCLK_SOURCE_PLL0,
32         .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_EXT,
33         .divider = 1, /* Rate adjusted via CPU PLL */
34     },
35 };
36 
37 static struct mod_pik_clock_rate rate_table_cpu_group_1[] = {
38     {
39         .rate = 2600 * FWK_MHZ,
40         .source = MOD_PIK_CLOCK_CLUSCLK_SOURCE_PLL1,
41         .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_EXT,
42         .divider = 1, /* Rate adjusted via CPU PLL */
43     },
44 };
45 
46 static const struct mod_pik_clock_rate rate_table_sys_intclk[] = {
47     {
48         .rate = 2000 * FWK_MHZ,
49         .source = MOD_PIK_CLOCK_INTCLK_SOURCE_INTPLL,
50         .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_EXT,
51         .divider = 1,
52     },
53 };
54 
55 static const struct mod_pik_clock_rate rate_table_sys_dmcclk[] = {
56     {
57         .rate = 1600 * FWK_MHZ,
58         .source = MOD_PIK_CLOCK_DMCCLK_SOURCE_DDRPLL,
59         .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_EXT,
60         .divider = 1,
61     },
62 };
63 
64 static const struct mod_pik_clock_rate rate_table_scp[] = {
65     {
66         .rate = 250 * FWK_MHZ,
67         .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK,
68         .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS,
69         .divider = CLOCK_RATE_SYSPLLCLK / (250 * FWK_MHZ),
70     },
71 };
72 
73 static const struct mod_pik_clock_rate rate_table_gicclk[] = {
74     {
75         .rate = 1000 * FWK_MHZ,
76         .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK,
77         .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS,
78         .divider = CLOCK_RATE_SYSPLLCLK / (1000 * FWK_MHZ),
79     },
80 };
81 
82 static const struct mod_pik_clock_rate rate_table_pclkscp[] = {
83     {
84         .rate = 400 * FWK_MHZ,
85         .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK,
86         .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS,
87         .divider = CLOCK_RATE_SYSPLLCLK / (400 * FWK_MHZ),
88     },
89 };
90 
91 static const struct mod_pik_clock_rate rate_table_sysperclk[] = {
92     {
93         .rate = 500 * FWK_MHZ,
94         .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK,
95         .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS,
96         .divider = CLOCK_RATE_SYSPLLCLK / (500 * FWK_MHZ),
97     },
98 };
99 
100 static const struct mod_pik_clock_rate rate_table_uartclk[] = {
101     {
102         .rate = 250 * FWK_MHZ,
103         .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK,
104         .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS,
105         .divider = CLOCK_RATE_SYSPLLCLK / (250 * FWK_MHZ),
106     },
107 };
108 
109 static const struct fwk_element pik_clock_element_table[] = {
110     /*
111      * Cluster 0 CPUS
112      */
113     [CLOCK_PIK_IDX_CLUS0_CPU0] = {
114         .name = "CLUS0_CPU0",
115         .data = &((struct mod_pik_clock_dev_config) {
116             .type = MOD_PIK_CLOCK_TYPE_CLUSTER,
117             .is_group_member = true,
118             .control_reg = &PIK_CLUSTER(0)->CORECLK[0].CTRL,
119             .divext_reg = &PIK_CLUSTER(0)->CORECLK[0].DIV,
120             .modulator_reg = &PIK_CLUSTER(0)->CORECLK[0].MOD,
121             .rate_table = rate_table_cpu_group_0,
122             .rate_count = FWK_ARRAY_SIZE(rate_table_cpu_group_0),
123         }),
124     },
125     [CLOCK_PIK_IDX_CLUS0_CPU1] = {
126         .name = "CLUS0_CPU1",
127         .data = &((struct mod_pik_clock_dev_config) {
128             .type = MOD_PIK_CLOCK_TYPE_CLUSTER,
129             .is_group_member = true,
130             .control_reg = &PIK_CLUSTER(0)->CORECLK[1].CTRL,
131             .divext_reg = &PIK_CLUSTER(0)->CORECLK[1].DIV,
132             .modulator_reg = &PIK_CLUSTER(0)->CORECLK[1].MOD,
133             .rate_table = rate_table_cpu_group_0,
134             .rate_count = FWK_ARRAY_SIZE(rate_table_cpu_group_0),
135         }),
136     },
137     [CLOCK_PIK_IDX_CLUS0_CPU2] = {
138         .name = "CLUS0_CPU2",
139         .data = &((struct mod_pik_clock_dev_config) {
140             .type = MOD_PIK_CLOCK_TYPE_CLUSTER,
141             .is_group_member = true,
142             .control_reg = &PIK_CLUSTER(0)->CORECLK[2].CTRL,
143             .divext_reg = &PIK_CLUSTER(0)->CORECLK[2].DIV,
144             .modulator_reg = &PIK_CLUSTER(0)->CORECLK[2].MOD,
145             .rate_table = rate_table_cpu_group_0,
146             .rate_count = FWK_ARRAY_SIZE(rate_table_cpu_group_0),
147         }),
148     },
149     [CLOCK_PIK_IDX_CLUS0_CPU3] = {
150         .name = "CLUS0_CPU3",
151         .data = &((struct mod_pik_clock_dev_config) {
152             .type = MOD_PIK_CLOCK_TYPE_CLUSTER,
153             .is_group_member = true,
154             .control_reg = &PIK_CLUSTER(0)->CORECLK[3].CTRL,
155             .divext_reg = &PIK_CLUSTER(0)->CORECLK[3].DIV,
156             .modulator_reg = &PIK_CLUSTER(0)->CORECLK[3].MOD,
157             .rate_table = rate_table_cpu_group_0,
158             .rate_count = FWK_ARRAY_SIZE(rate_table_cpu_group_0),
159         }),
160     },
161     [CLOCK_PIK_IDX_CLUS1_CPU0] = {
162         .name = "CLUS1_CPU0",
163         .data = &((struct mod_pik_clock_dev_config) {
164             .type = MOD_PIK_CLOCK_TYPE_CLUSTER,
165             .is_group_member = true,
166             .control_reg = &PIK_CLUSTER(1)->CORECLK[0].CTRL,
167             .divext_reg = &PIK_CLUSTER(1)->CORECLK[0].DIV,
168             .modulator_reg = &PIK_CLUSTER(1)->CORECLK[0].MOD,
169             .rate_table = rate_table_cpu_group_1,
170             .rate_count = FWK_ARRAY_SIZE(rate_table_cpu_group_1),
171         }),
172     },
173     [CLOCK_PIK_IDX_CLUS1_CPU1] = {
174         .name = "CLUS1_CPU1",
175         .data = &((struct mod_pik_clock_dev_config) {
176             .type = MOD_PIK_CLOCK_TYPE_CLUSTER,
177             .is_group_member = true,
178             .control_reg = &PIK_CLUSTER(1)->CORECLK[1].CTRL,
179             .divext_reg = &PIK_CLUSTER(1)->CORECLK[1].DIV,
180             .modulator_reg = &PIK_CLUSTER(1)->CORECLK[1].MOD,
181             .rate_table = rate_table_cpu_group_1,
182             .rate_count = FWK_ARRAY_SIZE(rate_table_cpu_group_1),
183         }),
184     },
185     [CLOCK_PIK_IDX_CLUS1_CPU2] = {
186         .name = "CLUS1_CPU2",
187         .data = &((struct mod_pik_clock_dev_config) {
188             .type = MOD_PIK_CLOCK_TYPE_CLUSTER,
189             .is_group_member = true,
190             .control_reg = &PIK_CLUSTER(1)->CORECLK[2].CTRL,
191             .divext_reg = &PIK_CLUSTER(1)->CORECLK[2].DIV,
192             .modulator_reg = &PIK_CLUSTER(1)->CORECLK[2].MOD,
193             .rate_table = rate_table_cpu_group_1,
194             .rate_count = FWK_ARRAY_SIZE(rate_table_cpu_group_1),
195         }),
196     },
197     [CLOCK_PIK_IDX_CLUS1_CPU3] = {
198         .name = "CLUS1_CPU3",
199         .data = &((struct mod_pik_clock_dev_config) {
200             .type = MOD_PIK_CLOCK_TYPE_CLUSTER,
201             .is_group_member = true,
202             .control_reg = &PIK_CLUSTER(1)->CORECLK[3].CTRL,
203             .divext_reg = &PIK_CLUSTER(1)->CORECLK[3].DIV,
204             .modulator_reg = &PIK_CLUSTER(1)->CORECLK[3].MOD,
205             .rate_table = rate_table_cpu_group_1,
206             .rate_count = FWK_ARRAY_SIZE(rate_table_cpu_group_1),
207         }),
208     },
209     [CLOCK_PIK_IDX_DMC] = {
210         .name = "DMC",
211         .data = &((struct mod_pik_clock_dev_config) {
212             .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE,
213             .is_group_member = false,
214             .control_reg = &PIK_SYSTEM->DMCCLK_CTRL,
215             .divext_reg = &PIK_SYSTEM->DMCCLK_DIV1,
216             .rate_table = rate_table_sys_dmcclk,
217             .rate_count = FWK_ARRAY_SIZE(rate_table_sys_dmcclk),
218             .initial_rate = 1600 * FWK_MHZ,
219         }),
220     },
221     [CLOCK_PIK_IDX_INTERCONNECT] = {
222         .name = "INTERCONNECT",
223         .data = &((struct mod_pik_clock_dev_config) {
224             .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE,
225             .is_group_member = false,
226             .control_reg = &PIK_SYSTEM->INTCLK_CTRL,
227             .divext_reg = &PIK_SYSTEM->INTCLK_DIV1,
228             .rate_table = rate_table_sys_intclk,
229             .rate_count = FWK_ARRAY_SIZE(rate_table_sys_intclk),
230             .initial_rate = 2000 * FWK_MHZ,
231         }),
232     },
233     [CLOCK_PIK_IDX_SCP] = {
234         .name = "SCP",
235         .data = &((struct mod_pik_clock_dev_config) {
236             .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE,
237             .is_group_member = false,
238             .control_reg = &PIK_SCP->CORECLK_CTRL,
239             .divsys_reg = &PIK_SCP->CORECLK_DIV1,
240             .rate_table = rate_table_scp,
241             .rate_count = FWK_ARRAY_SIZE(rate_table_scp),
242             .initial_rate = 250 * FWK_MHZ,
243         }),
244     },
245     [CLOCK_PIK_IDX_GIC] = {
246         .name = "GIC",
247         .data = &((struct mod_pik_clock_dev_config) {
248             .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE,
249             .is_group_member = false,
250             .control_reg = &PIK_SYSTEM->GICCLK_CTRL,
251             .divsys_reg = &PIK_SYSTEM->GICCLK_DIV1,
252             .rate_table = rate_table_gicclk,
253             .rate_count = FWK_ARRAY_SIZE(rate_table_gicclk),
254             .initial_rate = 1000 * FWK_MHZ,
255         }),
256     },
257     [CLOCK_PIK_IDX_PCLKSCP] = {
258         .name = "PCLKSCP",
259         .data = &((struct mod_pik_clock_dev_config) {
260             .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE,
261             .is_group_member = false,
262             .control_reg = &PIK_SYSTEM->PCLKSCP_CTRL,
263             .divsys_reg = &PIK_SYSTEM->PCLKSCP_DIV1,
264             .rate_table = rate_table_pclkscp,
265             .rate_count = FWK_ARRAY_SIZE(rate_table_pclkscp),
266             .initial_rate = 400 * FWK_MHZ,
267         }),
268     },
269     [CLOCK_PIK_IDX_SYSPERCLK] = {
270         .name = "SYSPERCLK",
271         .data = &((struct mod_pik_clock_dev_config) {
272             .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE,
273             .is_group_member = false,
274             .control_reg = &PIK_SYSTEM->SYSPERCLK_CTRL,
275             .divsys_reg = &PIK_SYSTEM->SYSPERCLK_DIV1,
276             .rate_table = rate_table_sysperclk,
277             .rate_count = FWK_ARRAY_SIZE(rate_table_sysperclk),
278             .initial_rate = 500 * FWK_MHZ,
279         }),
280     },
281     [CLOCK_PIK_IDX_UARTCLK] = {
282         .name = "UARTCLK",
283         .data = &((struct mod_pik_clock_dev_config) {
284             .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE,
285             .is_group_member = false,
286             .control_reg = &PIK_SYSTEM->UARTCLK_CTRL,
287             .divsys_reg = &PIK_SYSTEM->UARTCLK_DIV1,
288             .rate_table = rate_table_uartclk,
289             .rate_count = FWK_ARRAY_SIZE(rate_table_uartclk),
290             .initial_rate = 250 * FWK_MHZ,
291         }),
292     },
293     [CLOCK_PIK_IDX_COUNT] = { 0 }, /* Termination description. */
294 };
295 
pik_clock_get_element_table(fwk_id_t module_id)296 static const struct fwk_element *pik_clock_get_element_table
297     (fwk_id_t module_id)
298 {
299     return pik_clock_element_table;
300 }
301 
302 const struct fwk_module_config config_pik_clock = {
303     .elements = FWK_MODULE_DYNAMIC_ELEMENTS(pik_clock_get_element_table),
304 };
305