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 <cmn650.h>
9 #include <cmn650_ccix.h>
10
11 #include <internal/cmn650_ctx.h>
12
13 #include <mod_timer.h>
14
15 #include <fwk_assert.h>
16 #include <fwk_log.h>
17 #include <fwk_math.h>
18
19 #include <inttypes.h>
20
21 #define MOD_NAME "[CMN650_CCIX] "
22
23 struct mod_cmn650_ccix_ctx {
24 /* RAID value common to all function */
25 uint8_t raid_value;
26
27 /* Port Aggregation context flag */
28 bool is_prog_for_port_agg;
29 };
30
31 static struct mod_cmn650_ccix_ctx cmn650_ccix_ctx;
32
33 static uint8_t port_aggregate_group_id;
34
35 /* Pointer to the current CCIX configuration data */
36 static const struct mod_cmn650_ccix_config *config;
37
get_ldid(bool program_for_port_aggregation)38 static unsigned int get_ldid(bool program_for_port_aggregation)
39 {
40 return (program_for_port_aggregation) ? config->port_aggregate_ldid :
41 config->ldid;
42 }
43
cxg_link_wait_condition(void * data)44 static bool cxg_link_wait_condition(void *data)
45 {
46 uint64_t val1;
47 uint64_t val2;
48 uint8_t linkid;
49 struct cmn650_cxg_ra_reg *cxg_ra_reg;
50 struct cmn650_cxg_ha_reg *cxg_ha_reg;
51
52 fwk_assert(data != NULL);
53
54 struct cxg_wait_condition_data *wait_data =
55 (struct cxg_wait_condition_data *)data;
56 struct cmn650_device_ctx *ctx = wait_data->ctx;
57 unsigned int cxg_ldid = get_ldid(cmn650_ccix_ctx.is_prog_for_port_agg);
58 linkid = wait_data->linkid;
59
60 cxg_ra_reg = ctx->cxg_ra_reg_table[cxg_ldid].cxg_ra_reg;
61 cxg_ha_reg = ctx->cxg_ha_reg_table[cxg_ldid].cxg_ha_reg;
62
63 switch (wait_data->cond) {
64 case CXG_LINK_CTRL_EN_BIT_SET:
65 val1 = cxg_ra_reg->LINK_REGS[linkid].CXG_PRTCL_LINK_CTRL;
66 val2 = cxg_ha_reg->LINK_REGS[linkid].CXG_PRTCL_LINK_CTRL;
67 return (
68 ((val1 & CXG_LINK_CTRL_EN_MASK) &&
69 (val2 & CXG_LINK_CTRL_EN_MASK)) != 0);
70
71 case CXG_LINK_CTRL_UP_BIT_CLR:
72 val1 = cxg_ra_reg->LINK_REGS[linkid].CXG_PRTCL_LINK_CTRL;
73 val2 = cxg_ha_reg->LINK_REGS[linkid].CXG_PRTCL_LINK_CTRL;
74 return (
75 (((val1 & CXG_LINK_CTRL_UP_MASK) == 0) &&
76 ((val2 & CXG_LINK_CTRL_UP_MASK) == 0)) != 0);
77
78 case CXG_LINK_STATUS_DWN_BIT_SET:
79 val1 = cxg_ra_reg->LINK_REGS[linkid].CXG_PRTCL_LINK_STATUS;
80 val2 = cxg_ha_reg->LINK_REGS[linkid].CXG_PRTCL_LINK_STATUS;
81 return (
82 ((val1 & CXG_LINK_STATUS_DOWN_MASK) &&
83 (val2 & CXG_LINK_STATUS_DOWN_MASK)) != 0);
84
85 case CXG_LINK_STATUS_DWN_BIT_CLR:
86 val1 = cxg_ra_reg->LINK_REGS[linkid].CXG_PRTCL_LINK_STATUS;
87 val2 = cxg_ha_reg->LINK_REGS[linkid].CXG_PRTCL_LINK_STATUS;
88 return (
89 (((val1 & CXG_LINK_STATUS_DOWN_MASK) == 0) &&
90 ((val2 & CXG_LINK_STATUS_DOWN_MASK) == 0)) != 0);
91
92 case CXG_LINK_STATUS_ACK_BIT_SET:
93 val1 = cxg_ra_reg->LINK_REGS[linkid].CXG_PRTCL_LINK_STATUS;
94 val2 = cxg_ha_reg->LINK_REGS[linkid].CXG_PRTCL_LINK_STATUS;
95 return (
96 ((val1 & CXG_LINK_STATUS_ACK_MASK) &&
97 (val2 & CXG_LINK_STATUS_ACK_MASK)) != 0);
98
99 case CXG_LINK_STATUS_ACK_BIT_CLR:
100 val1 = cxg_ra_reg->LINK_REGS[linkid].CXG_PRTCL_LINK_STATUS;
101 val2 = cxg_ha_reg->LINK_REGS[linkid].CXG_PRTCL_LINK_STATUS;
102 return (
103 (((val1 & CXG_LINK_STATUS_ACK_MASK) == 0) &&
104 ((val2 & CXG_LINK_STATUS_ACK_MASK) == 0)) != 0);
105
106 case CXG_LINK_STATUS_HA_DVMDOMAIN_ACK_BIT_SET:
107 val1 = cxg_ha_reg->LINK_REGS[linkid].CXG_PRTCL_LINK_STATUS;
108 return (((val1 & CXG_LINK_STATUS_DVMDOMAIN_ACK_MASK)) != 0);
109
110 case CXG_LINK_STATUS_RA_DVMDOMAIN_ACK_BIT_SET:
111 val1 = cxg_ra_reg->LINK_REGS[linkid].CXG_PRTCL_LINK_STATUS;
112 return (((val1 & CXG_LINK_STATUS_DVMDOMAIN_ACK_MASK)) != 0);
113
114 default:
115 fwk_unexpected();
116 return false;
117 }
118 }
119
program_cxg_ra_rnf_ldid_to_raid_reg(struct cmn650_device_ctx * ctx,uint8_t ldid_value,uint8_t raid)120 static void program_cxg_ra_rnf_ldid_to_raid_reg(
121 struct cmn650_device_ctx *ctx,
122 uint8_t ldid_value,
123 uint8_t raid)
124 {
125 uint32_t reg_offset = 0;
126 uint32_t ldid_value_offset = 0;
127 struct cmn650_cxg_ra_reg *cxg_ra_reg;
128 unsigned int cxg_ldid = get_ldid(cmn650_ccix_ctx.is_prog_for_port_agg);
129
130 cxg_ra_reg = ctx->cxg_ra_reg_table[cxg_ldid].cxg_ra_reg;
131
132 /* Each 64-bit RA RNF LDID-to-RAID register holds 8 LDIDs */
133 reg_offset = ldid_value / 8;
134 ldid_value_offset = ldid_value % 8;
135
136 /* Adding raid_value into LDID-to-RAID register */
137 cxg_ra_reg->CXG_RA_RNF_LDID_TO_RAID_REG[reg_offset] |=
138 ((uint64_t)raid << (ldid_value_offset * NUM_BITS_RESERVED_FOR_RAID));
139
140 /* Set corresponding valid bit */
141 cxg_ra_reg->CXG_RA_RNF_LDID_TO_RAID_VAL |= ((uint64_t)0x1 << ldid_value);
142
143 cmn650_ccix_ctx.raid_value++;
144 }
145
program_cxg_ra_rni_ldid_to_raid_reg(struct cmn650_device_ctx * ctx,uint8_t ldid_value,uint8_t raid)146 static void program_cxg_ra_rni_ldid_to_raid_reg(
147 struct cmn650_device_ctx *ctx,
148 uint8_t ldid_value,
149 uint8_t raid)
150 {
151 uint32_t reg_offset = 0;
152 uint32_t ldid_value_offset = 0;
153 struct cmn650_cxg_ra_reg *cxg_ra_reg;
154 unsigned int cxg_ldid = get_ldid(cmn650_ccix_ctx.is_prog_for_port_agg);
155
156 cxg_ra_reg = ctx->cxg_ra_reg_table[cxg_ldid].cxg_ra_reg;
157
158 /* Each 64-bit RA RNI LDID-to-RAID register holds 8 LDIDs */
159 reg_offset = ldid_value / 8;
160 ldid_value_offset = ldid_value % 8;
161
162 /* Adding raid_value into LDID-to-RAID register */
163 cxg_ra_reg->CXG_RA_RNI_LDID_TO_RAID_REG[reg_offset] |=
164 ((uint64_t)raid << (ldid_value_offset * NUM_BITS_RESERVED_FOR_RAID));
165
166 /* Set corresponding valid bit */
167 cxg_ra_reg->CXG_RA_RNI_LDID_TO_RAID_VAL |= ((uint64_t)0x1 << ldid_value);
168
169 cmn650_ccix_ctx.raid_value++;
170 }
171
program_cxg_ra_rnd_ldid_to_raid_reg(struct cmn650_device_ctx * ctx,uint8_t ldid_value,uint8_t raid)172 static void program_cxg_ra_rnd_ldid_to_raid_reg(
173 struct cmn650_device_ctx *ctx,
174 uint8_t ldid_value,
175 uint8_t raid)
176 {
177 uint32_t reg_offset = 0;
178 uint32_t ldid_value_offset = 0;
179 struct cmn650_cxg_ra_reg *cxg_ra_reg;
180 unsigned int cxg_ldid = get_ldid(cmn650_ccix_ctx.is_prog_for_port_agg);
181
182 cxg_ra_reg = ctx->cxg_ra_reg_table[cxg_ldid].cxg_ra_reg;
183
184 /* Each 64-bit RA RND LDID-to-RAID register holds 8 LDIDs */
185 reg_offset = ldid_value / 8;
186 ldid_value_offset = ldid_value % 8;
187
188 /* Adding raid_value into LDID-to-RAID register */
189 cxg_ra_reg->CXG_RA_RND_LDID_TO_RAID_REG[reg_offset] |=
190 ((uint64_t)raid << (ldid_value_offset * NUM_BITS_RESERVED_FOR_RAID));
191
192 /* Set corresponding valid bit */
193 cxg_ra_reg->CXG_RA_RND_LDID_TO_RAID_VAL |= ((uint64_t)0x1 << ldid_value);
194
195 cmn650_ccix_ctx.raid_value++;
196 }
197
program_agentid_to_linkid_reg(struct cmn650_device_ctx * ctx,const struct mod_cmn650_ccix_config * config)198 static void program_agentid_to_linkid_reg(
199 struct cmn650_device_ctx *ctx,
200 const struct mod_cmn650_ccix_config *config)
201 {
202 uint32_t agentid;
203 uint32_t reg_index = 0;
204 uint8_t linkid = 0;
205 uint32_t agentid_bit_offset = 0;
206 struct cmn650_cxg_ra_reg *cxg_ra_reg;
207 struct cmn650_cxg_ha_reg *cxg_ha_reg;
208 struct cmn650_cxla_reg *cxla_reg;
209 unsigned int remote_agentid_start;
210 unsigned int remote_agentid_end;
211 unsigned int cxg_ldid = get_ldid(cmn650_ccix_ctx.is_prog_for_port_agg);
212
213 cxg_ra_reg = ctx->cxg_ra_reg_table[cxg_ldid].cxg_ra_reg;
214 cxg_ha_reg = ctx->cxg_ha_reg_table[cxg_ldid].cxg_ha_reg;
215 cxla_reg = ctx->cxla_reg_table[cxg_ldid].cxla_reg;
216
217 for (linkid = 0; linkid < CMN650_MAX_CCIX_PROTOCOL_LINKS; linkid++) {
218 remote_agentid_start =
219 config->remote_agentid_to_linkid_map[linkid].remote_agentid_start;
220 remote_agentid_end =
221 config->remote_agentid_to_linkid_map[linkid].remote_agentid_end;
222
223 /*
224 * Skip configuring link if both start and end are 0, indicating
225 * there's no link
226 */
227 if ((remote_agentid_start == 0) && (remote_agentid_end == 0))
228 continue;
229
230 FWK_LOG_INFO(
231 MOD_NAME " Remote [AgentID %d - AgentID %d] Link %d",
232 remote_agentid_start,
233 remote_agentid_end,
234 linkid);
235
236 for (agentid = remote_agentid_start; agentid <= remote_agentid_end;
237 agentid++) {
238 /* Each register is 64 bits and holds 8 AgentID/LinkID mappings */
239 reg_index = agentid / 8;
240 agentid_bit_offset = agentid % 8;
241
242 /* Writing AgentID-to-LinkID mappings */
243 cxg_ra_reg->CXG_RA_AGENTID_TO_LINKID_REG[reg_index] |=
244 ((uint64_t)linkid
245 << (agentid_bit_offset * NUM_BITS_RESERVED_FOR_LINKID));
246
247 cxg_ha_reg->CXG_HA_AGENTID_TO_LINKID_REG[reg_index] |=
248 ((uint64_t)linkid
249 << (agentid_bit_offset * NUM_BITS_RESERVED_FOR_LINKID));
250
251 cxla_reg->CXLA_AGENTID_TO_LINKID_REG[reg_index] |=
252 ((uint64_t)linkid
253 << (agentid_bit_offset * NUM_BITS_RESERVED_FOR_LINKID));
254
255 /* Setting corresponding valid bits */
256 cxg_ra_reg->CXG_RA_AGENTID_TO_LINKID_VAL |=
257 ((uint64_t)0x1 << agentid);
258 cxg_ha_reg->CXG_HA_AGENTID_TO_LINKID_VAL |=
259 ((uint64_t)0x1 << agentid);
260 cxla_reg->CXLA_AGENTID_TO_LINKID_VAL |= ((uint64_t)0x1 << agentid);
261 }
262 }
263 }
264
program_cxg_ha_id(struct cmn650_device_ctx * ctx)265 static void program_cxg_ha_id(struct cmn650_device_ctx *ctx)
266 {
267 struct cmn650_cxg_ha_reg *cxg_ha_reg;
268 unsigned int cxg_haid;
269 unsigned int cxg_ldid = get_ldid(cmn650_ccix_ctx.is_prog_for_port_agg);
270
271 cxg_ha_reg = ctx->cxg_ha_reg_table[cxg_ldid].cxg_ha_reg;
272 cxg_haid = cmn650_ccix_ctx.is_prog_for_port_agg ?
273 config->port_aggregate_haid :
274 config->haid;
275 cxg_ha_reg->CXG_HA_ID = cxg_haid;
276
277 FWK_LOG_INFO(
278 MOD_NAME "HAID for CCIX %d with nodeid %d: HAID %d",
279 cxg_ldid,
280 get_node_id(cxg_ha_reg),
281 cxg_haid);
282 }
283
program_cxg_ha_raid_to_ldid_lut(struct cmn650_device_ctx * ctx,uint8_t raid_id,uint8_t ldid_value)284 static void program_cxg_ha_raid_to_ldid_lut(
285 struct cmn650_device_ctx *ctx,
286 uint8_t raid_id,
287 uint8_t ldid_value)
288 {
289 uint32_t reg_index = 0;
290 uint32_t raid_bit_offset = 0;
291 struct cmn650_cxg_ha_reg *cxg_ha_reg;
292 unsigned int cxg_ldid = get_ldid(cmn650_ccix_ctx.is_prog_for_port_agg);
293
294 cxg_ha_reg = ctx->cxg_ha_reg_table[cxg_ldid].cxg_ha_reg;
295
296 /* Each 64-bit RAID-to-LDID register holds 8 mappings, 8 bits each. */
297 reg_index = raid_id / 8;
298 raid_bit_offset = raid_id % 8;
299
300 /* Write RAID-to-LDID mapping (with RNF bit set) */
301 cxg_ha_reg->CXG_HA_RNF_RAID_TO_LDID_REG[reg_index] |=
302 ((uint64_t)(ldid_value | CXG_HA_RAID_TO_LDID_RNF_MASK)
303 << (raid_bit_offset * NUM_BITS_RESERVED_FOR_LDID));
304
305 /* Set corresponding valid bit */
306 cxg_ha_reg->CXG_HA_RNF_RAID_TO_LDID_VAL |= ((uint64_t)0x1 << raid_id);
307 }
308
program_hnf_ldid_to_chi_node_id_reg(struct cmn650_device_ctx * ctx,const struct mod_cmn650_ccix_config * config)309 static void program_hnf_ldid_to_chi_node_id_reg(
310 struct cmn650_device_ctx *ctx,
311 const struct mod_cmn650_ccix_config *config)
312 {
313 uint32_t agentid;
314 uint32_t reg_index = 0;
315 uint32_t reg_bit_offset = 0;
316 uint32_t i = 0;
317 struct cmn650_hnf_reg *hnf_reg = NULL;
318 uint32_t nodeid_ra, cpa_nodeid_ra;
319 uint8_t linkid = 0;
320
321 unsigned int remote_agentid_start;
322 unsigned int remote_agentid_end;
323 unsigned int bit_pos;
324 unsigned int group;
325
326 /* Assign the NodeID of CXHA as the RA's NodeID */
327 nodeid_ra = ctx->cxg_ha_reg_table[config->ldid].node_id;
328 cpa_nodeid_ra = ctx->cxg_ha_reg_table[config->port_aggregate_ldid].node_id;
329
330 if (cmn650_ccix_ctx.is_prog_for_port_agg) {
331 /*
332 * if programming for port aggregation support, reset the remote rnf
333 * ldid value to the previous iteration in order to program .
334 */
335 ctx->remote_rnf_ldid_value -= ctx->rnf_count;
336 }
337
338 for (linkid = 0; linkid < CMN650_MAX_CCIX_PROTOCOL_LINKS; linkid++) {
339 remote_agentid_start =
340 config->remote_agentid_to_linkid_map[linkid].remote_agentid_start;
341 remote_agentid_end =
342 config->remote_agentid_to_linkid_map[linkid].remote_agentid_end;
343
344 /*
345 * Skip configuring link if both start and end are 0, indicating
346 * there's no link
347 */
348 if ((remote_agentid_start == 0) && (remote_agentid_end == 0))
349 continue;
350
351 FWK_LOG_INFO(
352 MOD_NAME " Remote [AgentID %d - AgentID %d] Node Id: %" PRIu32,
353 remote_agentid_start,
354 remote_agentid_end,
355 nodeid_ra);
356
357 for (agentid = remote_agentid_start; agentid <= remote_agentid_end;
358 agentid++) {
359 /* Each 64-bit register holds 2 sets of config data, 32 bits each */
360 reg_index = ctx->remote_rnf_ldid_value / 2;
361 reg_bit_offset = ctx->remote_rnf_ldid_value % 2;
362
363 for (i = 0; i < ctx->hnf_count; i++) {
364 hnf_reg = (struct cmn650_hnf_reg *)ctx->hnf_node[i];
365 /* Write CXHA NodeID, local/remote and valid bit */
366 hnf_reg->RN_PHYS_ID[reg_index] |=
367 ((uint64_t)(
368 nodeid_ra |
369 (REMOTE_CCIX_NODE
370 << HNF_RN_PHYS_RN_LOCAL_REMOTE_SHIFT_VAL) |
371 (port_aggregate_group_id
372 << HNF_RN_PHYS_CPA_GRP_RA_SHIFT_VAL) |
373 ((uint64_t)(config->port_aggregate)
374 << HNF_RN_PHYS_CPA_EN_RA_SHIFT_VAL) |
375 (UINT64_C(0x1) << HNF_RN_PHYS_RN_ID_VALID_SHIFT_VAL))
376 << (reg_bit_offset * NUM_BITS_RESERVED_FOR_PHYS_ID));
377
378 if (config->port_aggregate) {
379 group =
380 (port_aggregate_group_id * NUM_PORTS_PER_CPA_GROUP) /
381 CMN_PORT_AGGR_GRP_PAG_TGTID_PER_GROUP;
382 bit_pos =
383 ((port_aggregate_group_id * NUM_PORTS_PER_CPA_GROUP) *
384 CMN_PORT_AGGR_GRP_PAG_TGTID_WIDTH);
385
386 hnf_reg->CML_PORT_AGGR_GRP[group] |= ((uint64_t)nodeid_ra)
387 << bit_pos;
388
389 group =
390 ((port_aggregate_group_id * NUM_PORTS_PER_CPA_GROUP) +
391 1) /
392 CMN_PORT_AGGR_GRP_PAG_TGTID_PER_GROUP;
393 bit_pos =
394 ((((port_aggregate_group_id * NUM_PORTS_PER_CPA_GROUP) +
395 1) *
396 CMN_PORT_AGGR_GRP_PAG_TGTID_WIDTH) %
397 CMN_PORT_AGGR_GRP_PAG_TGTID_WIDTH_PER_GROUP);
398
399 hnf_reg->CML_PORT_AGGR_GRP[group] |= (uint64_t)cpa_nodeid_ra
400 << bit_pos;
401 }
402 }
403
404 ctx->remote_rnf_ldid_value++;
405 }
406 }
407
408 if (cmn650_ccix_ctx.is_prog_for_port_agg) {
409 for (i = 0; i < ctx->hnf_count; i++) {
410 hnf_reg = (struct cmn650_hnf_reg *)ctx->hnf_node[i];
411
412 /* Considering only 2 port support */
413 hnf_reg->CML_PORT_AGGR_CTRL |= UINT64_C(0x1)
414 << (port_aggregate_group_id *
415 CML_PORT_AGGR_CTRL_NUM_CXG_PAG_WIDTH);
416 }
417
418 /* Finally increment the group id for the next group utilization */
419 port_aggregate_group_id++;
420 }
421 }
422
enable_smp_mode(struct cmn650_device_ctx * ctx,const struct mod_cmn650_ccix_config * config)423 static int enable_smp_mode(
424 struct cmn650_device_ctx *ctx,
425 const struct mod_cmn650_ccix_config *config)
426 {
427 struct cmn650_cxg_ra_reg *cxg_ra_reg;
428 struct cmn650_cxg_ha_reg *cxg_ha_reg;
429 struct cmn650_cxla_reg *cxla_reg;
430 unsigned int cxg_ldid = get_ldid(cmn650_ccix_ctx.is_prog_for_port_agg);
431
432 cxg_ra_reg = ctx->cxg_ra_reg_table[cxg_ldid].cxg_ra_reg;
433 cxg_ha_reg = ctx->cxg_ha_reg_table[cxg_ldid].cxg_ha_reg;
434 cxla_reg = ctx->cxla_reg_table[cxg_ldid].cxla_reg;
435
436 cxg_ra_reg->CXG_RA_AUX_CTRL |= (1 << CXG_RA_AUX_CTRL_SMP_MODE_EN_SHIFT_VAL);
437 cxg_ha_reg->CXG_HA_AUX_CTRL |= (1 << CXG_HA_AUX_CTRL_SMP_MODE_EN_SHIFT_VAL);
438 cxla_reg->CXLA_AUX_CTRL |=
439 (UINT64_C(0x1) << CXLA_AUX_CTRL_SMP_MODE_EN_SHIFT_VAL);
440
441 FWK_LOG_INFO(MOD_NAME "SMP Mode Enabled");
442 return FWK_SUCCESS;
443 }
444
program_cxg_ra_sam_addr_region(struct cmn650_device_ctx * ctx,const struct mod_cmn650_ccix_config * config)445 static void program_cxg_ra_sam_addr_region(
446 struct cmn650_device_ctx *ctx,
447 const struct mod_cmn650_ccix_config *config)
448 {
449 unsigned int i, remote_haid;
450 uint64_t blocks;
451 uint64_t size;
452 struct cmn650_cxg_ra_reg *cxg_ra_reg;
453 unsigned int cxg_ldid = get_ldid(cmn650_ccix_ctx.is_prog_for_port_agg);
454
455 cxg_ra_reg = ctx->cxg_ra_reg_table[cxg_ldid].cxg_ra_reg;
456
457 FWK_LOG_INFO(
458 MOD_NAME "Configuring RA SAM for CXRA NodeID %d",
459 get_node_id(cxg_ra_reg));
460
461 for (i = 0; i < CMN650_MAX_RA_SAM_ADDR_REGION; i++) {
462 /* If the size is zero, skip that entry */
463 if (config->ra_mmap_table[i].size == 0)
464 continue;
465
466 /* Size must be a multiple of SAM_GRANULARITY */
467 fwk_assert((config->ra_mmap_table[i].size % (64 * FWK_KIB)) == 0);
468
469 /* Size also must be a power of two */
470 fwk_assert(
471 (config->ra_mmap_table[i].size &
472 (config->ra_mmap_table[i].size - 1)) == 0);
473
474 /* Region base should be naturally aligned to the region size */
475 fwk_assert(
476 config->ra_mmap_table[i].base % config->ra_mmap_table[i].size == 0);
477
478 if (cmn650_ccix_ctx.is_prog_for_port_agg)
479 remote_haid = config->port_aggregate_remote_haid[i];
480 else
481 remote_haid = config->ra_mmap_table[i].remote_haid;
482
483 FWK_LOG_INFO(
484 MOD_NAME " [0x%llx - 0x%llx] HAID %d",
485 config->ra_mmap_table[i].base,
486 config->ra_mmap_table[i].base + config->ra_mmap_table[i].size - 1,
487 remote_haid);
488
489 blocks = config->ra_mmap_table[i].size / (64 * FWK_KIB);
490 size = fwk_math_log2(blocks);
491
492 cxg_ra_reg->CXG_RA_SAM_ADDR_REGION_REG[i] = size |
493 (config->ra_mmap_table[i].base) |
494 ((uint64_t)remote_haid << SAM_ADDR_TARGET_HAID_SHIFT) |
495 (SAM_ADDR_REG_VALID_MASK);
496
497 i++;
498 }
499 }
500
enable_and_start_ccix_link_up_sequence(struct cmn650_device_ctx * ctx,uint8_t linkid)501 static int enable_and_start_ccix_link_up_sequence(
502 struct cmn650_device_ctx *ctx,
503 uint8_t linkid)
504 {
505 int status;
506 struct cxg_wait_condition_data wait_data;
507 struct cmn650_cxg_ra_reg *cxg_ra_reg;
508 struct cmn650_cxg_ha_reg *cxg_ha_reg;
509 unsigned int cxg_ldid = get_ldid(cmn650_ccix_ctx.is_prog_for_port_agg);
510
511 cxg_ra_reg = ctx->cxg_ra_reg_table[cxg_ldid].cxg_ra_reg;
512 cxg_ha_reg = ctx->cxg_ha_reg_table[cxg_ldid].cxg_ha_reg;
513
514 if (linkid > 2)
515 return FWK_E_PARAM;
516
517 wait_data.ctx = ctx;
518 wait_data.linkid = linkid;
519
520 FWK_LOG_INFO(MOD_NAME "Enabling CCIX link %d...", linkid);
521 /* Set link enable bit to enable the CCIX link */
522 cxg_ra_reg->LINK_REGS[linkid].CXG_PRTCL_LINK_CTRL = CXG_LINK_CTRL_EN_MASK;
523 cxg_ha_reg->LINK_REGS[linkid].CXG_PRTCL_LINK_CTRL = CXG_LINK_CTRL_EN_MASK;
524
525 /* Wait until link enable bits are set */
526 wait_data.cond = CXG_LINK_CTRL_EN_BIT_SET;
527 status = ctx->timer_api->wait(
528 FWK_ID_ELEMENT(FWK_MODULE_IDX_TIMER, 0),
529 CXG_PRTCL_LINK_CTRL_TIMEOUT,
530 cxg_link_wait_condition,
531 &wait_data);
532 if (status != FWK_SUCCESS) {
533 FWK_LOG_ERR(MOD_NAME "Enabling CCIX link %d... Failed", linkid);
534 return status;
535 }
536 FWK_LOG_INFO(MOD_NAME "Enabling CCIX link %d... Done", linkid);
537
538 FWK_LOG_INFO(MOD_NAME "Verifying link down status...");
539 /* Wait till link up bits are cleared in control register */
540 wait_data.cond = CXG_LINK_CTRL_UP_BIT_CLR;
541 status = ctx->timer_api->wait(
542 FWK_ID_ELEMENT(FWK_MODULE_IDX_TIMER, 0),
543 CXG_PRTCL_LINK_CTRL_TIMEOUT,
544 cxg_link_wait_condition,
545 &wait_data);
546 if (status != FWK_SUCCESS) {
547 FWK_LOG_ERR(MOD_NAME "Verifying link down status... Failed");
548 return status;
549 }
550
551 /* Wait till link down bits are set in status register */
552 wait_data.cond = CXG_LINK_STATUS_DWN_BIT_SET;
553 status = ctx->timer_api->wait(
554 FWK_ID_ELEMENT(FWK_MODULE_IDX_TIMER, 0),
555 CXG_PRTCL_LINK_CTRL_TIMEOUT,
556 cxg_link_wait_condition,
557 &wait_data);
558 if (status != FWK_SUCCESS) {
559 FWK_LOG_ERR(MOD_NAME "Verifying link down status... Failed");
560 return status;
561 }
562
563 /* Wait till link ACK bits are cleared in status register */
564 wait_data.cond = CXG_LINK_STATUS_ACK_BIT_CLR;
565 status = ctx->timer_api->wait(
566 FWK_ID_ELEMENT(FWK_MODULE_IDX_TIMER, 0),
567 CXG_PRTCL_LINK_CTRL_TIMEOUT,
568 cxg_link_wait_condition,
569 &wait_data);
570 if (status != FWK_SUCCESS) {
571 FWK_LOG_ERR(MOD_NAME "Verifying link down status... Failed");
572 return status;
573 }
574 FWK_LOG_INFO(MOD_NAME "Verifying link down status... Done");
575
576 FWK_LOG_INFO(MOD_NAME "Bringing up link...");
577 /* Bring up link using link request bit */
578 cxg_ra_reg->LINK_REGS[linkid].CXG_PRTCL_LINK_CTRL |= CXG_LINK_CTRL_REQ_MASK;
579 cxg_ha_reg->LINK_REGS[linkid].CXG_PRTCL_LINK_CTRL |= CXG_LINK_CTRL_REQ_MASK;
580
581 /* Wait till link ACK bits are set in status register */
582 wait_data.cond = CXG_LINK_STATUS_ACK_BIT_SET;
583 status = ctx->timer_api->wait(
584 FWK_ID_ELEMENT(FWK_MODULE_IDX_TIMER, 0),
585 CXG_PRTCL_LINK_CTRL_TIMEOUT,
586 cxg_link_wait_condition,
587 &wait_data);
588 if (status != FWK_SUCCESS) {
589 FWK_LOG_ERR(MOD_NAME "Bringing up link... Failed");
590 return status;
591 }
592
593 /* Wait till link down bits are cleared in status register */
594 wait_data.cond = CXG_LINK_STATUS_DWN_BIT_CLR;
595 status = ctx->timer_api->wait(
596 FWK_ID_ELEMENT(FWK_MODULE_IDX_TIMER, 0),
597 CXG_PRTCL_LINK_CTRL_TIMEOUT,
598 cxg_link_wait_condition,
599 &wait_data);
600 if (status != FWK_SUCCESS) {
601 FWK_LOG_ERR(MOD_NAME "Bringing up link... Failed");
602 return status;
603 }
604 FWK_LOG_INFO(MOD_NAME "Bringing up link... Done");
605
606 return FWK_SUCCESS;
607 }
608
ccix_setup(const unsigned int chip_id,struct cmn650_device_ctx * ctx,const struct mod_cmn650_ccix_config * ccix_config)609 int ccix_setup(
610 const unsigned int chip_id,
611 struct cmn650_device_ctx *ctx,
612 const struct mod_cmn650_ccix_config *ccix_config)
613 {
614 unsigned int i;
615 unsigned int unique_remote_rnf_ldid_value;
616 uint8_t rnf_ldid;
617 uint8_t rni_ldid;
618 uint8_t rnd_ldid;
619 uint8_t agentid;
620 uint8_t remote_agentid;
621 uint8_t offset_id;
622 uint8_t local_ra_cnt;
623 int status;
624
625 FWK_LOG_INFO(MOD_NAME "Programming CCIX gateway...");
626
627 /* Assign the max count among the RNs as local_ra_cnt */
628 if ((ctx->rnf_count > ctx->rnd_count) && (ctx->rnf_count > ctx->rni_count))
629 local_ra_cnt = ctx->rnf_count;
630 else if (ctx->rnd_count > ctx->rni_count)
631 local_ra_cnt = ctx->rnd_count;
632 else
633 local_ra_cnt = ctx->rni_count;
634
635 cmn650_ccix_ctx.is_prog_for_port_agg = false;
636
637 do {
638 /* Set the global config data */
639 config = ccix_config;
640
641 if (ccix_config->smp_mode) {
642 status = enable_smp_mode(ctx, ccix_config);
643 if (status != FWK_SUCCESS)
644 return status;
645 }
646
647 /*
648 * In order to assign unique AgentIDs across multiple chips, chip_id is
649 * used as factor to offset the AgentID value
650 */
651 cmn650_ccix_ctx.raid_value = 0;
652 offset_id = chip_id * local_ra_cnt;
653
654 for (rnf_ldid = 0; rnf_ldid < ctx->rnf_count; rnf_ldid++) {
655 agentid = cmn650_ccix_ctx.raid_value + offset_id;
656
657 /* Program RAID values in CXRA LDID to RAID LUT */
658 program_cxg_ra_rnf_ldid_to_raid_reg(ctx, rnf_ldid, agentid);
659 }
660
661 /* Program agentid to linkid LUT for remote agents in CXRA/CXHA/CXLA */
662 program_agentid_to_linkid_reg(ctx, ccix_config);
663
664 /* Program HN-F ldid to CHI NodeID for remote RN-F agents */
665 program_hnf_ldid_to_chi_node_id_reg(ctx, ccix_config);
666
667 /*
668 * unique_remote_rnf_ldid_value is used to keep track of the
669 * ldid of the remote RNF agents
670 */
671 unique_remote_rnf_ldid_value = ctx->rnf_count;
672
673 if (ccix_config->remote_rnf_count && (ctx->rnf_count == 0)) {
674 FWK_LOG_ERR(
675 MOD_NAME
676 "Remote RN-F Count can't be %u when RN-F count is zero",
677 ccix_config->remote_rnf_count);
678 fwk_unexpected();
679 }
680
681 for (i = 0; i < ccix_config->remote_rnf_count; i++) {
682 /*
683 * The remote_agentid should not include the current chip's
684 * AgentIDs. If `block` is less than the current chip_id, then
685 * include the AgentIDs starting from chip 0 till (not including)
686 * current chip. If the `block` is equal or greater than the current
687 * chip, then include the AgentIDs from next chip till the max chip.
688 */
689 if ((i / ctx->rnf_count) < chip_id)
690 remote_agentid = i;
691 else
692 remote_agentid = i + ctx->rnf_count;
693
694 /* Program the CXHA raid to ldid LUT */
695 program_cxg_ha_raid_to_ldid_lut(
696 ctx, remote_agentid, unique_remote_rnf_ldid_value);
697
698 unique_remote_rnf_ldid_value++;
699 }
700
701 /* Program the unique HAID for the CXHA block */
702 program_cxg_ha_id(ctx);
703
704 cmn650_ccix_ctx.raid_value = 0;
705 offset_id = chip_id * local_ra_cnt;
706
707 for (rnd_ldid = 0; rnd_ldid < ctx->rnd_count; rnd_ldid++) {
708 /* Determine agentid of the remote agents */
709 agentid = cmn650_ccix_ctx.raid_value + offset_id;
710
711 /* Program RAID values in CXRA LDID to RAID LUT */
712 program_cxg_ra_rnd_ldid_to_raid_reg(ctx, rnd_ldid, agentid);
713 }
714
715 cmn650_ccix_ctx.raid_value = 0;
716 offset_id = chip_id * local_ra_cnt;
717
718 for (rni_ldid = 0; rni_ldid < ctx->rni_count; rni_ldid++) {
719 /* Determine agentid of the remote agents */
720 agentid = cmn650_ccix_ctx.raid_value + offset_id;
721
722 /* Program RAID values in CXRA LDID to RAID LUT */
723 program_cxg_ra_rni_ldid_to_raid_reg(ctx, rni_ldid, agentid);
724 }
725
726 /*
727 * Program the CXRA SAM with the address range and the corresponding
728 * remote HAID
729 */
730 program_cxg_ra_sam_addr_region(ctx, ccix_config);
731
732 /* Program the Link Control registers present in CXRA/CXHA/CXLA */
733 status = enable_and_start_ccix_link_up_sequence(ctx, 0);
734
735 if (config->port_aggregate &&
736 cmn650_ccix_ctx.is_prog_for_port_agg == false) {
737 cmn650_ccix_ctx.is_prog_for_port_agg = true;
738 FWK_LOG_INFO(MOD_NAME
739 "Programming CCIX gateway for Port Aggregation...");
740 } else
741 cmn650_ccix_ctx.is_prog_for_port_agg = false;
742 } while (config->port_aggregate && cmn650_ccix_ctx.is_prog_for_port_agg);
743
744 return status;
745 }
746
ccix_exchange_protocol_credit(struct cmn650_device_ctx * ctx,const struct mod_cmn650_ccix_config * ccix_config)747 int ccix_exchange_protocol_credit(
748 struct cmn650_device_ctx *ctx,
749 const struct mod_cmn650_ccix_config *ccix_config)
750 {
751 int linkid;
752 struct cmn650_cxg_ra_reg *cxg_ra_reg;
753 struct cmn650_cxg_ha_reg *cxg_ha_reg;
754 unsigned int cxg_ldid;
755
756 cmn650_ccix_ctx.is_prog_for_port_agg = false;
757
758 do {
759 config = ccix_config;
760 cxg_ldid = get_ldid(cmn650_ccix_ctx.is_prog_for_port_agg);
761 cxg_ra_reg = ctx->cxg_ra_reg_table[cxg_ldid].cxg_ra_reg;
762 cxg_ha_reg = ctx->cxg_ha_reg_table[cxg_ldid].cxg_ha_reg;
763
764 /* TODO Add support to enable multiple links */
765 linkid = 0;
766
767 FWK_LOG_INFO(
768 MOD_NAME "Exchanging protocol credits for link %d...", linkid);
769 /* Exchange protocol credits using link up bit */
770 cxg_ra_reg->LINK_REGS[linkid].CXG_PRTCL_LINK_CTRL |=
771 CXG_LINK_CTRL_UP_MASK;
772 cxg_ha_reg->LINK_REGS[linkid].CXG_PRTCL_LINK_CTRL |=
773 CXG_LINK_CTRL_UP_MASK;
774 FWK_LOG_INFO(
775 MOD_NAME "Exchanging protocol credits for link %d... Done", linkid);
776
777 if (config->port_aggregate &&
778 cmn650_ccix_ctx.is_prog_for_port_agg == false) {
779 cmn650_ccix_ctx.is_prog_for_port_agg = true;
780 FWK_LOG_INFO(MOD_NAME
781 "Exchange Protocol Credit for Port Aggregation...");
782 } else
783 cmn650_ccix_ctx.is_prog_for_port_agg = false;
784 } while (config->port_aggregate && cmn650_ccix_ctx.is_prog_for_port_agg);
785
786 return FWK_SUCCESS;
787 }
788
ccix_enter_system_coherency(struct cmn650_device_ctx * ctx,const struct mod_cmn650_ccix_config * ccix_config)789 int ccix_enter_system_coherency(
790 struct cmn650_device_ctx *ctx,
791 const struct mod_cmn650_ccix_config *ccix_config)
792 {
793 struct cxg_wait_condition_data wait_data;
794 int status;
795 int linkid;
796 struct cmn650_cxg_ha_reg *cxg_ha_reg;
797 unsigned int cxg_ldid;
798
799 cmn650_ccix_ctx.is_prog_for_port_agg = false;
800
801 do {
802 config = ccix_config;
803 cxg_ldid = get_ldid(cmn650_ccix_ctx.is_prog_for_port_agg);
804 cxg_ha_reg = ctx->cxg_ha_reg_table[cxg_ldid].cxg_ha_reg;
805
806 /* TODO Add support to enable multiple links */
807 linkid = 0;
808
809 wait_data.ctx = ctx;
810 wait_data.linkid = linkid;
811
812 FWK_LOG_INFO(
813 MOD_NAME "Entering system coherency for link %d...", linkid);
814 /* Enter system coherency by setting DVMDOMAIN request bit */
815 cxg_ha_reg->LINK_REGS[linkid].CXG_PRTCL_LINK_CTRL |=
816 CXG_LINK_CTRL_DVMDOMAIN_REQ_MASK;
817
818 /* Wait till DVMDOMAIN ACK bit is set in status register */
819 wait_data.cond = CXG_LINK_STATUS_HA_DVMDOMAIN_ACK_BIT_SET;
820 status = ctx->timer_api->wait(
821 FWK_ID_ELEMENT(FWK_MODULE_IDX_TIMER, 0),
822 CXG_PRTCL_LINK_DVMDOMAIN_TIMEOUT,
823 cxg_link_wait_condition,
824 &wait_data);
825 if (status != FWK_SUCCESS) {
826 FWK_LOG_ERR(
827 MOD_NAME "Entering system coherency for link %d... Failed",
828 linkid);
829 return status;
830 }
831 FWK_LOG_INFO(
832 MOD_NAME "Entering system coherency for link %d... Done", linkid);
833
834 if (config->port_aggregate &&
835 cmn650_ccix_ctx.is_prog_for_port_agg == false) {
836 cmn650_ccix_ctx.is_prog_for_port_agg = true;
837 FWK_LOG_INFO(MOD_NAME
838 "Enter system coherency for Port Aggregation...");
839 } else
840 cmn650_ccix_ctx.is_prog_for_port_agg = false;
841 } while (config->port_aggregate && cmn650_ccix_ctx.is_prog_for_port_agg);
842
843 return FWK_SUCCESS;
844 }
845
ccix_enter_dvm_domain(struct cmn650_device_ctx * ctx,const struct mod_cmn650_ccix_config * ccix_config)846 int ccix_enter_dvm_domain(
847 struct cmn650_device_ctx *ctx,
848 const struct mod_cmn650_ccix_config *ccix_config)
849 {
850 struct cxg_wait_condition_data wait_data;
851 int status;
852 int linkid;
853 struct cmn650_cxg_ra_reg *cxg_ra_reg;
854 unsigned int cxg_ldid;
855
856 cmn650_ccix_ctx.is_prog_for_port_agg = false;
857
858 do {
859 config = ccix_config;
860 cxg_ldid = get_ldid(cmn650_ccix_ctx.is_prog_for_port_agg);
861 cxg_ra_reg = ctx->cxg_ra_reg_table[cxg_ldid].cxg_ra_reg;
862
863 /* TODO Add support to enable multiple links */
864 linkid = 0;
865
866 wait_data.ctx = ctx;
867 wait_data.linkid = linkid;
868
869 FWK_LOG_INFO(MOD_NAME "Entering DVM domain for link %d...", linkid);
870 /* DVM domain entry by setting DVMDOMAIN request bit */
871 cxg_ra_reg->LINK_REGS[linkid].CXG_PRTCL_LINK_CTRL |=
872 CXG_LINK_CTRL_DVMDOMAIN_REQ_MASK;
873
874 /* Wait till DVMDOMAIN ACK bit is set in status register */
875 wait_data.cond = CXG_LINK_STATUS_RA_DVMDOMAIN_ACK_BIT_SET;
876 status = ctx->timer_api->wait(
877 FWK_ID_ELEMENT(FWK_MODULE_IDX_TIMER, 0),
878 CXG_PRTCL_LINK_DVMDOMAIN_TIMEOUT,
879 cxg_link_wait_condition,
880 &wait_data);
881 if (status != FWK_SUCCESS) {
882 FWK_LOG_ERR(
883 MOD_NAME "Entering DVM domain for link %d... Failed", linkid);
884 return status;
885 }
886 FWK_LOG_INFO(
887 MOD_NAME "Entering DVM domain for link %d... Done", linkid);
888
889 if (config->port_aggregate &&
890 cmn650_ccix_ctx.is_prog_for_port_agg == false) {
891 cmn650_ccix_ctx.is_prog_for_port_agg = true;
892 FWK_LOG_INFO(MOD_NAME
893 "Entering DVM domain for Port Aggregation...");
894 } else
895 cmn650_ccix_ctx.is_prog_for_port_agg = false;
896 } while (config->port_aggregate && cmn650_ccix_ctx.is_prog_for_port_agg);
897
898 return FWK_SUCCESS;
899 }
900