1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2020-2022, 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 "platform_core.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 #include <stdbool.h>
22
23 #define CLOCK_PLL_CLUSn_CPU(n) \
24 [CLOCK_PIK_IDX_CLUS##n##_CPU0] = { \
25 .name = "CLUS" #n "_CPU0", \
26 .data = &((struct mod_pik_clock_dev_config){ \
27 .type = MOD_PIK_CLOCK_TYPE_CLUSTER, \
28 .is_group_member = true, \
29 .control_reg = &CLUSTER_PIK_PTR(n)->CORECLK_CTRL, \
30 .divext_reg = &CLUSTER_PIK_PTR(n)->CORECLK_DIV1, \
31 .modulator_reg = &CLUSTER_PIK_PTR(n)->CORECLK_MOD1, \
32 .rate_table = rate_table_cpu_group, \
33 .rate_count = FWK_ARRAY_SIZE(rate_table_cpu_group), \
34 }), \
35 }
36
37 /*
38 * Rate lookup tables
39 */
40 static struct mod_pik_clock_rate rate_table_cpu_group[] = {
41 {
42 .rate = 2600 * FWK_MHZ,
43 .source = MOD_PIK_CLOCK_CLUSCLK_SOURCE_PLL0,
44 .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_EXT,
45 .divider = 1,
46 },
47 };
48
49 static const struct mod_pik_clock_rate rate_table_sys_intclk[] = {
50 {
51 .rate = 2000 * FWK_MHZ,
52 .source = MOD_PIK_CLOCK_INTCLK_SOURCE_INTPLL,
53 .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_EXT,
54 .divider = 1,
55 },
56 };
57
58 static const struct mod_pik_clock_rate rate_table_sys_dmcclk[] = {
59 {
60 .rate = 1600 * FWK_MHZ,
61 .source = MOD_PIK_CLOCK_DMCCLK_SOURCE_DDRPLL,
62 .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_EXT,
63 .divider = 1,
64 },
65 };
66
67 static const struct mod_pik_clock_rate rate_table_scp[] = {
68 {
69 .rate = 800 * 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 / (800 * FWK_MHZ),
73 },
74 };
75
76 static const struct mod_pik_clock_rate rate_table_gicclk[] = {
77 {
78 .rate = 1000 * FWK_MHZ,
79 .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK,
80 .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS,
81 .divider = CLOCK_RATE_SYSPLLCLK / (1000 * FWK_MHZ),
82 },
83 };
84
85 static const struct mod_pik_clock_rate rate_table_pclkscp[] = {
86 {
87 .rate = 400 * FWK_MHZ,
88 .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK,
89 .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS,
90 .divider = CLOCK_RATE_SYSPLLCLK / (400 * FWK_MHZ),
91 },
92 };
93
94 static const struct mod_pik_clock_rate rate_table_sysperclk[] = {
95 {
96 .rate = 500 * FWK_MHZ,
97 .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK,
98 .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS,
99 .divider = CLOCK_RATE_SYSPLLCLK / (500 * FWK_MHZ),
100 },
101 };
102
103 static const struct mod_pik_clock_rate rate_table_uartclk[] = {
104 {
105 .rate = 250 * FWK_MHZ,
106 .source = MOD_PIK_CLOCK_MSCLOCK_SOURCE_SYSPLLCLK,
107 .divider_reg = MOD_PIK_CLOCK_MSCLOCK_DIVIDER_DIV_SYS,
108 .divider = CLOCK_RATE_SYSPLLCLK / (250 * FWK_MHZ),
109 },
110 };
111
112 static const struct fwk_element pik_clock_element_table[] = {
113 CLOCK_PLL_CLUSn_CPU(0),
114 CLOCK_PLL_CLUSn_CPU(1),
115 CLOCK_PLL_CLUSn_CPU(2),
116 CLOCK_PLL_CLUSn_CPU(3),
117 #if (NUMBER_OF_CLUSTERS > 4)
118 CLOCK_PLL_CLUSn_CPU(4),
119 CLOCK_PLL_CLUSn_CPU(5),
120 CLOCK_PLL_CLUSn_CPU(6),
121 CLOCK_PLL_CLUSn_CPU(7),
122 # if (NUMBER_OF_CLUSTERS > 8)
123 CLOCK_PLL_CLUSn_CPU(8),
124 CLOCK_PLL_CLUSn_CPU(9),
125 CLOCK_PLL_CLUSn_CPU(10),
126 CLOCK_PLL_CLUSn_CPU(11),
127 CLOCK_PLL_CLUSn_CPU(12),
128 CLOCK_PLL_CLUSn_CPU(13),
129 CLOCK_PLL_CLUSn_CPU(14),
130 CLOCK_PLL_CLUSn_CPU(15),
131 # endif
132 #endif
133 [CLOCK_PIK_IDX_DMC] = {
134 .name = "DMC",
135 .data = &((struct mod_pik_clock_dev_config) {
136 .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE,
137 .is_group_member = false,
138 .control_reg = &SYSTEM_PIK_PTR->DMCCLK_CTRL,
139 .divext_reg = &SYSTEM_PIK_PTR->DMCCLK_DIV1,
140 .rate_table = rate_table_sys_dmcclk,
141 .rate_count = FWK_ARRAY_SIZE(rate_table_sys_dmcclk),
142 .initial_rate = 1600 * FWK_MHZ,
143 }),
144 },
145 [CLOCK_PIK_IDX_INTERCONNECT] = {
146 .name = "INTERCONNECT",
147 .data = &((struct mod_pik_clock_dev_config) {
148 .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE,
149 .is_group_member = false,
150 .control_reg = &SYSTEM_PIK_PTR->INTCLK_CTRL,
151 .divext_reg = &SYSTEM_PIK_PTR->INTCLK_DIV1,
152 .rate_table = rate_table_sys_intclk,
153 .rate_count = FWK_ARRAY_SIZE(rate_table_sys_intclk),
154 .initial_rate = 2000 * FWK_MHZ,
155 }),
156 },
157 [CLOCK_PIK_IDX_SCP] = {
158 .name = "SCP",
159 .data = &((struct mod_pik_clock_dev_config) {
160 .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE,
161 .is_group_member = false,
162 .control_reg = &SCP_PIK_PTR->CORECLK_CTRL,
163 .divsys_reg = &SCP_PIK_PTR->CORECLK_DIV1,
164 .rate_table = rate_table_scp,
165 .rate_count = FWK_ARRAY_SIZE(rate_table_scp),
166 .initial_rate = 800 * FWK_MHZ,
167 }),
168 },
169 [CLOCK_PIK_IDX_GIC] = {
170 .name = "GIC",
171 .data = &((struct mod_pik_clock_dev_config) {
172 .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE,
173 .is_group_member = false,
174 .control_reg = &SYSTEM_PIK_PTR->GICCLK_CTRL,
175 .divsys_reg = &SYSTEM_PIK_PTR->GICCLK_DIV1,
176 .rate_table = rate_table_gicclk,
177 .rate_count = FWK_ARRAY_SIZE(rate_table_gicclk),
178 .initial_rate = 1000 * FWK_MHZ,
179 }),
180 },
181 [CLOCK_PIK_IDX_PCLKSCP] = {
182 .name = "PCLKSCP",
183 .data = &((struct mod_pik_clock_dev_config) {
184 .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE,
185 .is_group_member = false,
186 .control_reg = &SYSTEM_PIK_PTR->SCPPIKCLK_CTRL,
187 .divsys_reg = &SYSTEM_PIK_PTR->SCPPIKCLK_DIV1,
188 .rate_table = rate_table_pclkscp,
189 .rate_count = FWK_ARRAY_SIZE(rate_table_pclkscp),
190 .initial_rate = 400 * FWK_MHZ,
191 }),
192 },
193 [CLOCK_PIK_IDX_SYSPERCLK] = {
194 .name = "SYSPERCLK",
195 .data = &((struct mod_pik_clock_dev_config) {
196 .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE,
197 .is_group_member = false,
198 .control_reg = &SYSTEM_PIK_PTR->SYSPERCLK_CTRL,
199 .divsys_reg = &SYSTEM_PIK_PTR->SYSPERCLK_DIV1,
200 .rate_table = rate_table_sysperclk,
201 .rate_count = FWK_ARRAY_SIZE(rate_table_sysperclk),
202 .initial_rate = 500 * FWK_MHZ,
203 }),
204 },
205 [CLOCK_PIK_IDX_UARTCLK] = {
206 .name = "UARTCLK",
207 .data = &((struct mod_pik_clock_dev_config) {
208 .type = MOD_PIK_CLOCK_TYPE_MULTI_SOURCE,
209 .is_group_member = false,
210 .control_reg = &SYSTEM_PIK_PTR->APUARTCLK_CTRL,
211 .divsys_reg = &SYSTEM_PIK_PTR->APUARTCLK_DIV1,
212 .rate_table = rate_table_uartclk,
213 .rate_count = FWK_ARRAY_SIZE(rate_table_uartclk),
214 .initial_rate = 250 * FWK_MHZ,
215 }),
216 },
217 [CLOCK_PIK_IDX_COUNT] = { 0 }, /* Termination description. */
218 };
219
pik_clock_get_element_table(fwk_id_t module_id)220 static const struct fwk_element *pik_clock_get_element_table(fwk_id_t module_id)
221 {
222 return pik_clock_element_table;
223 }
224
225 const struct fwk_module_config config_pik_clock = {
226 .elements = FWK_MODULE_DYNAMIC_ELEMENTS(pik_clock_get_element_table),
227 };
228