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