1 /*
2  * Arm SCP/MCP Software
3  * Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include "synquacer_ddr.h"
9 
10 #include <internal/ccn512.h>
11 
12 #include <mod_ccn512.h>
13 
14 #include <fwk_assert.h>
15 #include <fwk_id.h>
16 #include <fwk_log.h>
17 #include <fwk_module.h>
18 #include <fwk_module_idx.h>
19 #include <fwk_status.h>
20 
21 #include <fmw_cmsis.h>
22 
23 #include <stddef.h>
24 #include <stdint.h>
25 
26 #define HNF_COUNT 8
27 #define SNF_ID_DMC1 0x8ULL
28 #define SNF_ID_DMC3 0x1AULL
29 
30 #define SNF_MP_ID_DMC0 0x8ULL
31 #define SNF_MP_ID_DMC1 0x1AULL
32 
ccn512_qos_init(ccn512_reg_t * ccn512)33 static void ccn512_qos_init(ccn512_reg_t *ccn512)
34 {
35     /*
36      * Setting QOS priority for each CPU cluster to 0xE and setting the
37      * enable bit so the new setting takes effect.  This function must be
38      * called when there are no ongoing transactions on the ports being
39      * configured, so it must be called after powering on SYSTOP and before
40      * the applications cores/clusters are released from reset.
41      *
42      * See "Device 0 Port QoS Control register" in the Corelink CCN512 Cache
43      * Coherent Network technical reference manual.
44      */
45     ccn512->XP_ID_0.DEV0_QOS_CONTROL = 0xE0004; /* Cluster 0   */
46     ccn512->XP_ID_1.DEV0_QOS_CONTROL = 0; /* not Cluster */
47     ccn512->XP_ID_2.DEV0_QOS_CONTROL = 0; /* not Cluster */
48     ccn512->XP_ID_3.DEV0_QOS_CONTROL = 0; /* not Cluster */
49     ccn512->XP_ID_4.DEV0_QOS_CONTROL = 0; /* not Cluster */
50     ccn512->XP_ID_5.DEV0_QOS_CONTROL = 0xE0004; /* PCIE1       */
51     ccn512->XP_ID_6.DEV0_QOS_CONTROL = 0xE0004; /* Cluster 6   */
52     ccn512->XP_ID_7.DEV0_QOS_CONTROL = 0xE0004; /* Cluster 8   */
53     ccn512->XP_ID_8.DEV0_QOS_CONTROL = 0; /* not Cluster */
54     ccn512->XP_ID_9.DEV0_QOS_CONTROL = 0xE0004; /* Cluster 1   */
55     ccn512->XP_ID_10.DEV0_QOS_CONTROL = 0; /* not Cluster */
56     ccn512->XP_ID_11.DEV0_QOS_CONTROL = 0; /* not Cluster */
57     ccn512->XP_ID_12.DEV0_QOS_CONTROL = 0; /* not Cluster */
58     ccn512->XP_ID_13.DEV0_QOS_CONTROL = 0; /* not Cluster */
59     ccn512->XP_ID_14.DEV0_QOS_CONTROL = 0; /* not Cluster */
60     ccn512->XP_ID_15.DEV0_QOS_CONTROL = 0xE0004; /* Cluster 7   */
61     ccn512->XP_ID_16.DEV0_QOS_CONTROL = 0xE0004; /* Cluster 9   */
62     ccn512->XP_ID_17.DEV0_QOS_CONTROL = 0;
63 
64     ccn512->XP_ID_0.DEV1_QOS_CONTROL = 0; /* not Cluster */
65     ccn512->XP_ID_1.DEV1_QOS_CONTROL = 0; /* not Cluster */
66     ccn512->XP_ID_2.DEV1_QOS_CONTROL = 0; /* not Cluster */
67     ccn512->XP_ID_3.DEV1_QOS_CONTROL = 0; /* not Cluster */
68     ccn512->XP_ID_4.DEV1_QOS_CONTROL = 0; /* not Cluster */
69     ccn512->XP_ID_5.DEV1_QOS_CONTROL = 0xE0004; /* Cluster 2   */
70     ccn512->XP_ID_6.DEV1_QOS_CONTROL = 0; /* not Cluster */
71     ccn512->XP_ID_7.DEV1_QOS_CONTROL = 0xE0004; /* Cluster 10  */
72     ccn512->XP_ID_8.DEV1_QOS_CONTROL = 0xE0004; /* Cluster 5   */
73     ccn512->XP_ID_9.DEV1_QOS_CONTROL = 0xE0004; /* PCIE0       */
74     ccn512->XP_ID_10.DEV1_QOS_CONTROL = 0; /* not Cluster */
75     ccn512->XP_ID_11.DEV1_QOS_CONTROL = 0; /* not Cluster */
76     ccn512->XP_ID_12.DEV1_QOS_CONTROL = 0; /* not Cluster */
77     ccn512->XP_ID_13.DEV1_QOS_CONTROL = 0; /* not Cluster */
78     ccn512->XP_ID_14.DEV1_QOS_CONTROL = 0xE0004; /* Cluster 3   */
79     ccn512->XP_ID_15.DEV1_QOS_CONTROL = 0; /* not Cluster */
80     ccn512->XP_ID_16.DEV1_QOS_CONTROL = 0xE0004; /* Cluster 11  */
81     ccn512->XP_ID_17.DEV1_QOS_CONTROL = 0xE0004; /* Cluster 4   */
82 }
83 
ccn512_dmc_init(ccn512_reg_t * ccn512)84 static void ccn512_dmc_init(ccn512_reg_t *ccn512)
85 {
86     unsigned int i;
87     ccn5xx_hnf_reg_t *hnf = &ccn512->HNF_ID_2;
88     uint64_t ddr_ch0_id, ddr_ch1_id;
89 
90     uint8_t ddr_memory_used_ch;
91     ddr_memory_used_ch = fw_get_used_memory_ch();
92 
93     ddr_ch0_id = SNF_MP_ID_DMC0;
94     ddr_ch1_id = SNF_MP_ID_DMC1;
95 
96     /*
97      * On SynQuacer, there are only 2 DMCs (IDs 1 and 3).
98      * All traffic from the first half of the HN-Fs must go to DMC1 and the
99      * second half to DMC3.
100      * If this setup is not done, the traffic for the DMCs that do not
101      * exist will lock-up the system.
102      */
103     for (i = 0; i < HNF_COUNT; i++) {
104         if (ddr_memory_used_ch == DDR_USE_CH0) {
105             hnf[i].HNF_SAM_CONTROL = ddr_ch0_id;
106         } else if (ddr_memory_used_ch == DDR_USE_CH1) {
107             hnf[i].HNF_SAM_CONTROL = ddr_ch1_id;
108         } else {
109             hnf[i].HNF_SAM_CONTROL =
110                 (i < (HNF_COUNT / 2) ? ddr_ch0_id : ddr_ch1_id);
111         }
112     }
113 }
114 
ccn512_secure_init(ccn512_reg_t * ccn512)115 static void ccn512_secure_init(ccn512_reg_t *ccn512)
116 {
117     /* set Non-secure access enable */
118     ccn512->MN_ID_34.SECURE_ACCESS |= 0x1;
119 }
120 
fw_ccn512_init(ccn512_reg_t * ccn512)121 void fw_ccn512_init(ccn512_reg_t *ccn512)
122 {
123     ccn512_secure_init(ccn512);
124     ccn512_qos_init(ccn512);
125     ccn512_dmc_init(ccn512);
126 
127     /* Wait for write operations to finish. */
128     __DMB();
129 }
130 
fw_ccn512_exit(void)131 void fw_ccn512_exit(void)
132 {
133     const struct mod_ccn512_module_config *module_config;
134     ccn512_reg_t *ccn512;
135     unsigned int i;
136 
137     module_config = fwk_module_get_data(fwk_module_id_ccn512);
138     fwk_assert(module_config != NULL);
139 
140     ccn512 = module_config->reg_base;
141 
142     ccn5xx_hnf_reg_t *hnf = &ccn512->HNF_ID_2;
143 
144     FWK_LOG_INFO("[CCN512] CCN512 exit.");
145 
146     /* exit ALL CA53 CPU SNOOP */
147     for (i = 0; i < HNF_COUNT; i++)
148         hnf[i].SNOOP_DOMAIN_CTL_CLR = hnf[i].SNOOP_DOMAIN_CTL;
149 
150     /* Wait for write operations to finish. */
151     __DMB();
152 
153     FWK_LOG_INFO("[CCN512] CCN512 exit end.");
154 }
155 
ccn512_config(ccn512_reg_t * ccn512)156 static int ccn512_config(ccn512_reg_t *ccn512)
157 {
158     FWK_LOG_INFO("[CCN512] Initialising ccn512 at 0x%x", (uintptr_t)ccn512);
159 
160     fw_ccn512_init(ccn512);
161 
162     FWK_LOG_INFO("[CCN512] CCN512 init done.");
163 
164     return FWK_SUCCESS;
165 }
166 
167 static struct mod_ccn512_api module_api = {
168     .ccn512_exit = fw_ccn512_exit,
169 };
170 
171 /* Framework API */
mod_ccn512_init(fwk_id_t module_id,unsigned int element_count,const void * data)172 static int mod_ccn512_init(
173     fwk_id_t module_id,
174     unsigned int element_count,
175     const void *data)
176 {
177     return FWK_SUCCESS;
178 }
179 
mod_ccn512_element_init(fwk_id_t element_id,unsigned int unused,const void * data)180 static int mod_ccn512_element_init(
181     fwk_id_t element_id,
182     unsigned int unused,
183     const void *data)
184 {
185     fwk_assert(data != NULL);
186 
187     return FWK_SUCCESS;
188 }
189 
mod_ccn512_bind(fwk_id_t id,unsigned int round)190 static int mod_ccn512_bind(fwk_id_t id, unsigned int round)
191 {
192     /* Nothing to do in the second round of calls. */
193     if (round == 1)
194         return FWK_SUCCESS;
195 
196     /* Nothing to do in case of elements. */
197     if (fwk_module_is_valid_element_id(id))
198         return FWK_SUCCESS;
199 
200     return FWK_SUCCESS;
201 }
202 
mod_ccn512_start(fwk_id_t id)203 static int mod_ccn512_start(fwk_id_t id)
204 {
205     const struct mod_ccn512_module_config *module_config;
206     ccn512_reg_t *ccn512;
207 
208     module_config = fwk_module_get_data(fwk_module_id_ccn512);
209     fwk_assert(module_config != NULL);
210 
211     ccn512 = module_config->reg_base;
212 
213     return ccn512_config(ccn512);
214 }
215 
mod_ccn512_process_bind_request(fwk_id_t requester_id,fwk_id_t target_id,fwk_id_t api_id,const void ** api)216 static int mod_ccn512_process_bind_request(
217     fwk_id_t requester_id,
218     fwk_id_t target_id,
219     fwk_id_t api_id,
220     const void **api)
221 {
222     *api = &module_api;
223 
224     return FWK_SUCCESS;
225 }
226 
227 const struct fwk_module module_ccn512 = {
228     .type = FWK_MODULE_TYPE_DRIVER,
229     .init = mod_ccn512_init,
230     .element_init = mod_ccn512_element_init,
231     .bind = mod_ccn512_bind,
232     .start = mod_ccn512_start,
233     .process_bind_request = mod_ccn512_process_bind_request,
234     .api_count = 1,
235     .event_count = 0,
236 };
237