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