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