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