1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2022-2023, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "clock_soc.h"
9 #include "cpu_pik.h"
10 #include "dpu_pik.h"
11 #include "scp_pik.h"
12 #include "system_pik.h"
13
14 #include <mod_pik_clock.h>
15
16 #include <fwk_element.h>
17 #include <fwk_id.h>
18 #include <fwk_macros.h>
19 #include <fwk_module.h>
20
21 /*
22 * Rate lookup tables
23 */
24 static const struct mod_pik_clock_rate rate_table_cpu_group_hayes[1] = {
25 {
26 .rate = 1537 * FWK_MHZ,
27 .source = MOD_PIK_CLOCK_CLUSCLK_SOURCE_TC2_PLL0,
28 .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_EXT,
29 .divider = 1, /* Rate adjusted via CPU PLL */
30 },
31 };
32
33 static const struct mod_pik_clock_rate rate_table_cpu_group_hunter[1] = {
34 {
35 .rate = 1893 * FWK_MHZ,
36 .source = MOD_PIK_CLOCK_CLUSCLK_SOURCE_TC2_PLL1,
37 .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_EXT,
38 .divider = 1, /* Rate adjusted via CPU PLL */
39 },
40 };
41
42 static const struct mod_pik_clock_rate rate_table_cpu_group_hunter_elp[1] = {
43 {
44 .rate = 2176 * FWK_MHZ,
45 .source = MOD_PIK_CLOCK_CLUSCLK_SOURCE_TC2_PLL2,
46 .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_EXT,
47 .divider = 1, /* Rate adjusted via CPU PLL */
48 },
49 };
50
51 static const struct mod_pik_clock_rate rate_table_gicclk[1] = {
52 {
53 .rate = 2000 * FWK_MHZ,
54 .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK,
55 .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS,
56 .divider = CLOCK_RATE_SYSPLLCLK / (2000 * FWK_MHZ),
57 },
58 };
59
60 static const struct mod_pik_clock_rate rate_table_pclkscp[1] = {
61 {
62 .rate = 2000 * FWK_MHZ,
63 .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK,
64 .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS,
65 .divider = CLOCK_RATE_SYSPLLCLK / (2000 * FWK_MHZ),
66 },
67 };
68
69 static const struct mod_pik_clock_rate rate_table_sysperclk[1] = {
70 {
71 .rate = 2000 * FWK_MHZ,
72 .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK,
73 .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS,
74 .divider = CLOCK_RATE_SYSPLLCLK / (2000 * FWK_MHZ),
75 },
76 };
77
78 static const struct mod_pik_clock_rate rate_table_uartclk[1] = {
79 {
80 .rate = 2000 * FWK_MHZ,
81 .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK,
82 .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS,
83 .divider = CLOCK_RATE_SYSPLLCLK / (2000 * FWK_MHZ),
84 },
85 };
86
87 static const struct mod_pik_clock_rate rate_table_dpu[1] = {
88 {
89 .rate = 600 * FWK_MHZ,
90 .source = MOD_PIK_CLOCK_ACLKDPU_SOURCE_DISPLAYPLLCLK,
91 .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_EXT,
92 .divider = 1, /* Rate adjusted via display PLL */
93 },
94 };
95
96 static const struct fwk_element pik_clock_element_table[
97 CLOCK_PIK_IDX_COUNT + 1] = {
98
99 [CLOCK_PIK_IDX_CLUS0_CPU0] = {
100 .name = "CLUS0_CPU0",
101 .data = &((struct mod_pik_clock_dev_config) {
102 .type = MOD_PIK_CLOCK_TYPE_CLUSTER,
103 .is_group_member = true,
104 .control_reg = &CLUSTER_PIK_PTR->CORECLK[0].CTRL,
105 .divext_reg = &CLUSTER_PIK_PTR->CORECLK[0].DIV,
106 .modulator_reg = &CLUSTER_PIK_PTR->CORECLK[0].MOD,
107 .rate_table = rate_table_cpu_group_hayes,
108 .rate_count = FWK_ARRAY_SIZE(rate_table_cpu_group_hayes),
109 }),
110 },
111 [CLOCK_PIK_IDX_CLUS0_CPU1] = {
112 .name = "CLUS0_CPU1",
113 .data = &((struct mod_pik_clock_dev_config) {
114 .type = MOD_PIK_CLOCK_TYPE_CLUSTER,
115 .is_group_member = true,
116 .control_reg = &CLUSTER_PIK_PTR->CORECLK[1].CTRL,
117 .divext_reg = &CLUSTER_PIK_PTR->CORECLK[1].DIV,
118 .modulator_reg = &CLUSTER_PIK_PTR->CORECLK[1].MOD,
119 .rate_table = rate_table_cpu_group_hayes,
120 .rate_count = FWK_ARRAY_SIZE(rate_table_cpu_group_hayes),
121 }),
122 },
123 [CLOCK_PIK_IDX_CLUS0_CPU2] = {
124 .name = "CLUS0_CPU2",
125 .data = &((struct mod_pik_clock_dev_config) {
126 .type = MOD_PIK_CLOCK_TYPE_CLUSTER,
127 .is_group_member = true,
128 .control_reg = &CLUSTER_PIK_PTR->CORECLK[2].CTRL,
129 .divext_reg = &CLUSTER_PIK_PTR->CORECLK[2].DIV,
130 .modulator_reg = &CLUSTER_PIK_PTR->CORECLK[2].MOD,
131 .rate_table = rate_table_cpu_group_hayes,
132 .rate_count = FWK_ARRAY_SIZE(rate_table_cpu_group_hayes),
133 }),
134 },
135 [CLOCK_PIK_IDX_CLUS0_CPU3] = {
136 .name = "CLUS0_CPU3",
137 .data = &((struct mod_pik_clock_dev_config) {
138 .type = MOD_PIK_CLOCK_TYPE_CLUSTER,
139 .is_group_member = true,
140 .control_reg = &CLUSTER_PIK_PTR->CORECLK[3].CTRL,
141 .divext_reg = &CLUSTER_PIK_PTR->CORECLK[3].DIV,
142 .modulator_reg = &CLUSTER_PIK_PTR->CORECLK[3].MOD,
143 .rate_table = rate_table_cpu_group_hayes,
144 .rate_count = FWK_ARRAY_SIZE(rate_table_cpu_group_hayes),
145 }),
146 },
147 [CLOCK_PIK_IDX_CLUS0_CPU4] = {
148 .name = "CLUS0_CPU4",
149 .data = &((struct mod_pik_clock_dev_config) {
150 .type = MOD_PIK_CLOCK_TYPE_CLUSTER,
151 .is_group_member = true,
152 .control_reg = &CLUSTER_PIK_PTR->CORECLK[4].CTRL,
153 .divext_reg = &CLUSTER_PIK_PTR->CORECLK[4].DIV,
154 .modulator_reg = &CLUSTER_PIK_PTR->CORECLK[4].MOD,
155 .rate_table = rate_table_cpu_group_hunter,
156 .rate_count = FWK_ARRAY_SIZE(rate_table_cpu_group_hunter),
157 }),
158 },
159 [CLOCK_PIK_IDX_CLUS0_CPU5] = {
160 .name = "CLUS0_CPU5",
161 .data = &((struct mod_pik_clock_dev_config) {
162 .type = MOD_PIK_CLOCK_TYPE_CLUSTER,
163 .is_group_member = true,
164 .control_reg = &CLUSTER_PIK_PTR->CORECLK[5].CTRL,
165 .divext_reg = &CLUSTER_PIK_PTR->CORECLK[5].DIV,
166 .modulator_reg = &CLUSTER_PIK_PTR->CORECLK[5].MOD,
167 .rate_table = rate_table_cpu_group_hunter,
168 .rate_count = FWK_ARRAY_SIZE(rate_table_cpu_group_hunter),
169 }),
170 },
171 [CLOCK_PIK_IDX_CLUS0_CPU6] = {
172 .name = "CLUS0_CPU6",
173 .data = &((struct mod_pik_clock_dev_config) {
174 .type = MOD_PIK_CLOCK_TYPE_CLUSTER,
175 .is_group_member = true,
176 .control_reg = &CLUSTER_PIK_PTR->CORECLK[6].CTRL,
177 .divext_reg = &CLUSTER_PIK_PTR->CORECLK[6].DIV,
178 .modulator_reg = &CLUSTER_PIK_PTR->CORECLK[6].MOD,
179 .rate_table = rate_table_cpu_group_hunter,
180 .rate_count = FWK_ARRAY_SIZE(rate_table_cpu_group_hunter),
181 }),
182 },
183 [CLOCK_PIK_IDX_CLUS0_CPU7] = {
184 .name = "CLUS0_CPU7",
185 .data = &((struct mod_pik_clock_dev_config) {
186 .type = MOD_PIK_CLOCK_TYPE_CLUSTER,
187 .is_group_member = true,
188 .control_reg = &CLUSTER_PIK_PTR->CORECLK[7].CTRL,
189 .divext_reg = &CLUSTER_PIK_PTR->CORECLK[7].DIV,
190 .modulator_reg = &CLUSTER_PIK_PTR->CORECLK[7].MOD,
191 .rate_table = rate_table_cpu_group_hunter_elp,
192 .rate_count = FWK_ARRAY_SIZE(rate_table_cpu_group_hunter_elp),
193 }),
194 },
195 [CLOCK_PIK_IDX_GIC] = {
196 .name = "GIC",
197 .data = &((struct mod_pik_clock_dev_config) {
198 .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE,
199 .is_group_member = false,
200 .control_reg = &SYSTEM_PIK_PTR->GICCLK_CTRL,
201 .divsys_reg = &SYSTEM_PIK_PTR->GICCLK_DIV1,
202 .rate_table = rate_table_gicclk,
203 .rate_count = FWK_ARRAY_SIZE(rate_table_gicclk),
204 .initial_rate = 2000 * FWK_MHZ,
205 }),
206 },
207 [CLOCK_PIK_IDX_PCLKSCP] = {
208 .name = "PCLKSCP",
209 .data = &((struct mod_pik_clock_dev_config) {
210 .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE,
211 .is_group_member = false,
212 .control_reg = &SYSTEM_PIK_PTR->PCLKSCP_CTRL,
213 .divsys_reg = &SYSTEM_PIK_PTR->PCLKSCP_DIV1,
214 .rate_table = rate_table_pclkscp,
215 .rate_count = FWK_ARRAY_SIZE(rate_table_pclkscp),
216 .initial_rate = 2000 * FWK_MHZ,
217 }),
218 },
219 [CLOCK_PIK_IDX_SYSPERCLK] = {
220 .name = "SYSPERCLK",
221 .data = &((struct mod_pik_clock_dev_config) {
222 .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE,
223 .is_group_member = false,
224 .control_reg = &SYSTEM_PIK_PTR->SYSPERCLK_CTRL,
225 .divsys_reg = &SYSTEM_PIK_PTR->SYSPERCLK_DIV1,
226 .rate_table = rate_table_sysperclk,
227 .rate_count = FWK_ARRAY_SIZE(rate_table_sysperclk),
228 .initial_rate = 2000 * FWK_MHZ,
229 }),
230 },
231 [CLOCK_PIK_IDX_UARTCLK] = {
232 .name = "UARTCLK",
233 .data = &((struct mod_pik_clock_dev_config) {
234 .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE,
235 .is_group_member = false,
236 .control_reg = &SYSTEM_PIK_PTR->UARTCLK_CTRL,
237 .divsys_reg = &SYSTEM_PIK_PTR->UARTCLK_DIV1,
238 .rate_table = rate_table_uartclk,
239 .rate_count = FWK_ARRAY_SIZE(rate_table_uartclk),
240 .initial_rate = 2000 * FWK_MHZ,
241 }),
242 },
243 [CLOCK_PIK_IDX_DPU] = {
244 .name = "DPU",
245 .data = &((struct mod_pik_clock_dev_config) {
246 .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE,
247 .is_group_member = true,
248 .control_reg = &DPU_PIK_PTR->ACLKDP_CTRL,
249 .divsys_reg = &DPU_PIK_PTR->ACLKDP_DIV1,
250 .divext_reg = &DPU_PIK_PTR->ACLKDP_DIV2,
251 .rate_table = rate_table_dpu,
252 .rate_count = FWK_ARRAY_SIZE(rate_table_dpu),
253 .initial_rate = 600 * FWK_MHZ,
254 .defer_initialization = true,
255 }),
256 },
257 [CLOCK_PIK_IDX_COUNT] = { 0 }, /* Termination description. */
258 };
259
pik_clock_get_element_table(fwk_id_t module_id)260 static const struct fwk_element *pik_clock_get_element_table(fwk_id_t module_id)
261 {
262 return pik_clock_element_table;
263 }
264
265 const struct fwk_module_config config_pik_clock = {
266 .elements = FWK_MODULE_DYNAMIC_ELEMENTS(pik_clock_get_element_table),
267 };
268