1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2017-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 "rdn1e1_pik_cpu.h"
10 #include "rdn1e1_pik_scp.h"
11 #include "rdn1e1_pik_system.h"
12 #include "scp_rdn1e1_pik.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