1 /*
2 * Arm SCP/MCP Software
3 * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include <cmn700.h>
9 #include <cmn700_ccg.h>
10
11 #include <internal/cmn700_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 #include <stdint.h>
21
22 #define MOD_NAME "[CMN700_CCG] "
23
24 struct mod_cmn700_ccg_ctx {
25 /* RAID value common to all function */
26 uint8_t raid_value;
27
28 /* Port Aggregation context flag */
29 bool is_prog_for_port_agg;
30 };
31
32 static struct mod_cmn700_ccg_ctx cmn700_ccg_ctx;
33
34 /* Pointer to the current CCG configuration data */
35 static const struct mod_cmn700_ccg_config *config;
36
get_ldid(struct cmn700_device_ctx * ctx,bool program_for_port_aggregation)37 static unsigned int get_ldid(
38 struct cmn700_device_ctx *ctx,
39 bool program_for_port_aggregation)
40 {
41 unsigned int ldid;
42
43 ldid = (program_for_port_aggregation) ? config->port_aggregate_ldid :
44 config->ldid;
45
46 if (ldid >= ctx->ccg_node_count) {
47 FWK_LOG_ERR(MOD_NAME "Unexpected ldid: %d", ldid);
48 fwk_trap();
49 }
50
51 return ldid;
52 }
53
ccg_link_wait_condition(void * data)54 static bool ccg_link_wait_condition(void *data)
55 {
56 bool ret;
57 uint8_t linkid;
58 uint64_t val1;
59 uint64_t val2;
60 unsigned int ccg_ldid;
61 struct ccg_wait_condition_data *wait_data;
62 struct cmn700_ccg_ra_reg *ccg_ra_reg;
63 struct cmn700_ccg_ha_reg *ccg_ha_reg;
64 struct cmn700_device_ctx *ctx;
65
66 fwk_assert(data != NULL);
67
68 wait_data = (struct ccg_wait_condition_data *)data;
69 ctx = wait_data->ctx;
70
71 ccg_ldid = get_ldid(ctx, cmn700_ccg_ctx.is_prog_for_port_agg);
72 ccg_ra_reg = ctx->ccg_ra_reg_table[ccg_ldid].ccg_ra_reg;
73 ccg_ha_reg = ctx->ccg_ha_reg_table[ccg_ldid].ccg_ha_reg;
74 linkid = wait_data->linkid;
75
76 switch (wait_data->cond) {
77 case CCG_LINK_CTRL_EN_BIT_SET:
78 val1 = ccg_ra_reg->LINK_REGS[linkid].CCG_CCPRTCL_LINK_CTRL;
79 val2 = ccg_ha_reg->LINK_REGS[linkid].CCG_CCPRTCL_LINK_CTRL;
80 ret = ((val1 & CCG_LINK_CTRL_EN_MASK) > 0) &&
81 ((val2 & CCG_LINK_CTRL_EN_MASK) > 0);
82 break;
83
84 case CCG_LINK_CTRL_UP_BIT_CLR:
85 val1 = ccg_ra_reg->LINK_REGS[linkid].CCG_CCPRTCL_LINK_CTRL;
86 val2 = ccg_ha_reg->LINK_REGS[linkid].CCG_CCPRTCL_LINK_CTRL;
87 ret =
88 (((val1 & CCG_LINK_CTRL_UP_MASK) == 0) &&
89 ((val2 & CCG_LINK_CTRL_UP_MASK) == 0));
90 break;
91
92 case CCG_LINK_STATUS_DWN_BIT_SET:
93 val1 = ccg_ra_reg->LINK_REGS[linkid].CCG_CCPRTCL_LINK_STATUS;
94 val2 = ccg_ha_reg->LINK_REGS[linkid].CCG_CCPRTCL_LINK_STATUS;
95 ret = ((val1 & CCG_LINK_STATUS_DOWN_MASK) > 0) &&
96 ((val2 & CCG_LINK_STATUS_DOWN_MASK) > 0);
97 break;
98
99 case CCG_LINK_STATUS_DWN_BIT_CLR:
100 val1 = ccg_ra_reg->LINK_REGS[linkid].CCG_CCPRTCL_LINK_STATUS;
101 val2 = ccg_ha_reg->LINK_REGS[linkid].CCG_CCPRTCL_LINK_STATUS;
102 ret =
103 (((val1 & CCG_LINK_STATUS_DOWN_MASK) == 0) &&
104 ((val2 & CCG_LINK_STATUS_DOWN_MASK) == 0));
105 break;
106
107 case CCG_LINK_STATUS_ACK_BIT_SET:
108 val1 = ccg_ra_reg->LINK_REGS[linkid].CCG_CCPRTCL_LINK_STATUS;
109 val2 = ccg_ha_reg->LINK_REGS[linkid].CCG_CCPRTCL_LINK_STATUS;
110 ret = ((val1 & CCG_LINK_STATUS_ACK_MASK) > 0) &&
111 ((val2 & CCG_LINK_STATUS_ACK_MASK) > 0);
112 break;
113
114 case CCG_LINK_STATUS_ACK_BIT_CLR:
115 val1 = ccg_ra_reg->LINK_REGS[linkid].CCG_CCPRTCL_LINK_STATUS;
116 val2 = ccg_ha_reg->LINK_REGS[linkid].CCG_CCPRTCL_LINK_STATUS;
117 ret =
118 (((val1 & CCG_LINK_STATUS_ACK_MASK) == 0) &&
119 ((val2 & CCG_LINK_STATUS_ACK_MASK) == 0));
120 break;
121
122 case CCG_LINK_STATUS_HA_DVMDOMAIN_ACK_BIT_SET:
123 val1 = ccg_ha_reg->LINK_REGS[linkid].CCG_CCPRTCL_LINK_STATUS;
124 ret = (((val1 & CCG_LINK_STATUS_DVMDOMAIN_ACK_MASK)) != 0);
125 break;
126
127 case CCG_LINK_STATUS_RA_DVMDOMAIN_ACK_BIT_SET:
128 val1 = ccg_ra_reg->LINK_REGS[linkid].CCG_CCPRTCL_LINK_STATUS;
129 ret = (((val1 & CCG_LINK_STATUS_DVMDOMAIN_ACK_MASK)) != 0);
130 break;
131
132 default:
133 fwk_unexpected();
134 ret = false;
135 }
136
137 return ret;
138 }
139
program_ccg_ra_rnf_ldid_to_exp_raid_reg(struct cmn700_device_ctx * ctx,uint8_t ldid_value,uint8_t raid)140 static void program_ccg_ra_rnf_ldid_to_exp_raid_reg(
141 struct cmn700_device_ctx *ctx,
142 uint8_t ldid_value,
143 uint8_t raid)
144 {
145 uint32_t reg_offset = 0;
146 uint32_t ldid_value_offset = 0;
147 unsigned int ccg_ldid;
148 struct cmn700_ccg_ra_reg *ccg_ra_reg;
149
150 ccg_ldid = get_ldid(ctx, cmn700_ccg_ctx.is_prog_for_port_agg);
151 ccg_ra_reg = ctx->ccg_ra_reg_table[ccg_ldid].ccg_ra_reg;
152
153 /* Each 64-bit RA RNF LDID-to-RAID register holds 4 LDIDs */
154 reg_offset = ldid_value / 4;
155 ldid_value_offset = ldid_value % 4;
156
157 /* Adding raid_value into LDID-to-RAID register */
158 ccg_ra_reg->CCG_RA_RNF_LDID_TO_EXP_RAID_REG[reg_offset] |=
159 ((uint64_t)raid << (ldid_value_offset * NUM_BITS_RESERVED_FOR_RAID));
160
161 /* Set corresponding valid bit */
162 ccg_ra_reg->CCG_RA_RNF_LDID_TO_EXP_RAID_REG[reg_offset] |=
163 (LDID_TO_EXP_RAID_VALID_MASK)
164 << (ldid_value_offset * NUM_BITS_RESERVED_FOR_RAID);
165
166 cmn700_ccg_ctx.raid_value++;
167 }
168
program_ccg_ra_rni_ldid_to_exp_raid_reg(struct cmn700_device_ctx * ctx,uint8_t ldid_value,uint8_t raid)169 static void program_ccg_ra_rni_ldid_to_exp_raid_reg(
170 struct cmn700_device_ctx *ctx,
171 uint8_t ldid_value,
172 uint8_t raid)
173 {
174 uint32_t reg_offset = 0;
175 uint32_t ldid_value_offset = 0;
176 unsigned int ccg_ldid;
177 struct cmn700_ccg_ra_reg *ccg_ra_reg;
178
179 ccg_ldid = get_ldid(ctx, cmn700_ccg_ctx.is_prog_for_port_agg);
180 ccg_ra_reg = ctx->ccg_ra_reg_table[ccg_ldid].ccg_ra_reg;
181
182 /* Each 64-bit RA RNI LDID-to-RAID register holds 4 LDIDs */
183 reg_offset = ldid_value / 4;
184 ldid_value_offset = ldid_value % 4;
185
186 /* Adding raid_value into LDID-to-RAID register */
187 ccg_ra_reg->CCG_RA_RNI_LDID_TO_EXP_RAID_REG[reg_offset] |=
188 ((uint64_t)raid << (ldid_value_offset * NUM_BITS_RESERVED_FOR_RAID));
189
190 /* Set corresponding valid bit */
191 ccg_ra_reg->CCG_RA_RNI_LDID_TO_EXP_RAID_REG[reg_offset] |=
192 (LDID_TO_EXP_RAID_VALID_MASK)
193 << (ldid_value_offset * NUM_BITS_RESERVED_FOR_RAID);
194
195 cmn700_ccg_ctx.raid_value++;
196 }
197
program_ccg_ra_rnd_ldid_to_exp_raid_reg(struct cmn700_device_ctx * ctx,uint8_t ldid_value,uint8_t raid)198 static void program_ccg_ra_rnd_ldid_to_exp_raid_reg(
199 struct cmn700_device_ctx *ctx,
200 uint8_t ldid_value,
201 uint8_t raid)
202 {
203 uint32_t reg_offset = 0;
204 uint32_t ldid_value_offset = 0;
205 unsigned int ccg_ldid;
206 struct cmn700_ccg_ra_reg *ccg_ra_reg;
207
208 ccg_ldid = get_ldid(ctx, cmn700_ccg_ctx.is_prog_for_port_agg);
209 ccg_ra_reg = ctx->ccg_ra_reg_table[ccg_ldid].ccg_ra_reg;
210
211 /* Each 64-bit RA RND LDID-to-RAID register holds 4 LDIDs */
212 reg_offset = ldid_value / 4;
213 ldid_value_offset = ldid_value % 4;
214
215 /* Adding raid_value into LDID-to-RAID register */
216 ccg_ra_reg->CCG_RA_RND_LDID_TO_EXP_RAID_REG[reg_offset] |=
217 ((uint64_t)raid << (ldid_value_offset * NUM_BITS_RESERVED_FOR_RAID));
218
219 /* Set corresponding valid bit */
220 ccg_ra_reg->CCG_RA_RND_LDID_TO_EXP_RAID_REG[reg_offset] |=
221 (LDID_TO_EXP_RAID_VALID_MASK)
222 << (ldid_value_offset * NUM_BITS_RESERVED_FOR_RAID);
223
224 cmn700_ccg_ctx.raid_value++;
225 }
226
program_agentid_to_linkid_reg(struct cmn700_device_ctx * ctx,const struct mod_cmn700_ccg_config * config)227 static void program_agentid_to_linkid_reg(
228 struct cmn700_device_ctx *ctx,
229 const struct mod_cmn700_ccg_config *config)
230 {
231 uint8_t linkid = 0;
232 uint32_t agentid;
233 uint32_t reg_index = 0;
234 uint32_t agentid_bit_offset = 0;
235 unsigned int ccg_ldid;
236 unsigned int remote_agentid_start;
237 unsigned int remote_agentid_end;
238 struct cmn700_ccg_ra_reg *ccg_ra_reg;
239 struct cmn700_ccg_ha_reg *ccg_ha_reg;
240
241 ccg_ldid = get_ldid(ctx, cmn700_ccg_ctx.is_prog_for_port_agg);
242 ccg_ra_reg = ctx->ccg_ra_reg_table[ccg_ldid].ccg_ra_reg;
243 ccg_ha_reg = ctx->ccg_ha_reg_table[ccg_ldid].ccg_ha_reg;
244
245 for (linkid = 0; linkid < CMN700_MAX_CCG_PROTOCOL_LINKS; linkid++) {
246 remote_agentid_start =
247 config->remote_agentid_to_linkid_map[linkid].remote_agentid_start;
248 remote_agentid_end =
249 config->remote_agentid_to_linkid_map[linkid].remote_agentid_end;
250
251 /*
252 * Skip configuring link if both start and end are 0, indicating
253 * there's no link
254 */
255 if ((remote_agentid_start == 0) && (remote_agentid_end == 0)) {
256 continue;
257 }
258
259 FWK_LOG_INFO(
260 MOD_NAME " Remote [AgentID %d - AgentID %d] Link %d",
261 remote_agentid_start,
262 remote_agentid_end,
263 linkid);
264
265 for (agentid = remote_agentid_start; agentid <= remote_agentid_end;
266 agentid++) {
267 /* Each register is 64 bits and holds 8 AgentID/LinkID mappings */
268 reg_index = agentid / 8;
269 agentid_bit_offset = agentid % 8;
270
271 /* Writing AgentID-to-LinkID mappings */
272 ccg_ra_reg->CCG_RA_AGENTID_TO_LINKID_REG[reg_index] |=
273 ((uint64_t)linkid
274 << (agentid_bit_offset * NUM_BITS_RESERVED_FOR_LINKID));
275
276 ccg_ha_reg->CCG_HA_AGENTID_TO_LINKID_REG[reg_index] |=
277 ((uint64_t)linkid
278 << (agentid_bit_offset * NUM_BITS_RESERVED_FOR_LINKID));
279
280 /* Setting corresponding valid bits */
281 ccg_ra_reg->CCG_RA_AGENTID_TO_LINKID_VAL |=
282 (UINT64_C(0x1) << agentid);
283 ccg_ha_reg->CCG_HA_AGENTID_TO_LINKID_VAL |=
284 (UINT64_C(0x1) << agentid);
285 }
286 }
287 }
288
program_ccg_ha_id(struct cmn700_device_ctx * ctx)289 static void program_ccg_ha_id(struct cmn700_device_ctx *ctx)
290 {
291 struct cmn700_ccg_ha_reg *ccg_ha_reg;
292 unsigned int ccg_haid;
293 unsigned int ccg_ldid;
294
295 ccg_ldid = get_ldid(ctx, cmn700_ccg_ctx.is_prog_for_port_agg);
296 ccg_ha_reg = ctx->ccg_ha_reg_table[ccg_ldid].ccg_ha_reg;
297 ccg_haid = cmn700_ccg_ctx.is_prog_for_port_agg ?
298 config->port_aggregate_haid :
299 config->haid;
300 ccg_ha_reg->CCG_HA_ID = ccg_haid;
301
302 FWK_LOG_INFO(
303 MOD_NAME "HAID for CCG %d with nodeid %d: HAID %d",
304 ccg_ldid,
305 get_node_id(ccg_ha_reg),
306 ccg_haid);
307 }
308
program_ccg_ha_raid_to_ldid_lut(struct cmn700_device_ctx * ctx,uint8_t raid_id,uint8_t ldid_value)309 static void program_ccg_ha_raid_to_ldid_lut(
310 struct cmn700_device_ctx *ctx,
311 uint8_t raid_id,
312 uint8_t ldid_value)
313 {
314 uint32_t reg_index = 0;
315 uint32_t raid_bit_offset = 0;
316 unsigned int ccg_ldid;
317 struct cmn700_ccg_ha_reg *ccg_ha_reg;
318
319 ccg_ldid = get_ldid(ctx, cmn700_ccg_ctx.is_prog_for_port_agg);
320 ccg_ha_reg = ctx->ccg_ha_reg_table[ccg_ldid].ccg_ha_reg;
321
322 /* Each 64-bit RAID-to-LDID register holds 4 mappings, 16 bits each. */
323 reg_index = raid_id / 4;
324 raid_bit_offset = raid_id % 4;
325
326 /* Write RAID-to-LDID mapping (with RNF bit set) */
327 ccg_ha_reg->CCG_HA_RNF_EXP_RAID_TO_LDID_REG[reg_index] |=
328 ((uint64_t)(
329 ldid_value | CCG_HA_RAID_TO_LDID_RNF_MASK |
330 (EXP_RAID_TO_LDID_VALID_MASK))
331 << (raid_bit_offset * NUM_BITS_RESERVED_FOR_LDID));
332 }
333
program_hnf_ldid_to_chi_node_id_reg(struct cmn700_device_ctx * ctx,const struct mod_cmn700_ccg_config * config)334 static void program_hnf_ldid_to_chi_node_id_reg(
335 struct cmn700_device_ctx *ctx,
336 const struct mod_cmn700_ccg_config *config)
337 {
338 uint8_t linkid;
339 uint32_t agentid;
340 uint32_t reg_index;
341 uint32_t i;
342 uint32_t nodeid_ra;
343 unsigned int remote_agentid_start;
344 unsigned int remote_agentid_end;
345 struct cmn700_hnf_reg *hnf_reg;
346
347 linkid = 0;
348 reg_index = 0;
349 i = 0;
350
351 /* Assign the NodeID of CCHA as the RA's NodeID */
352 nodeid_ra = ctx->ccg_ha_reg_table[config->ldid].node_id;
353
354 if (cmn700_ccg_ctx.is_prog_for_port_agg) {
355 /*
356 * if programming for port aggregation support, reset the remote rnf
357 * ldid value to the previous iteration in order to program.
358 */
359 ctx->remote_rnf_ldid_value -= ctx->rnf_count;
360 }
361
362 for (linkid = 0; linkid < CMN700_MAX_CCG_PROTOCOL_LINKS; linkid++) {
363 remote_agentid_start =
364 config->remote_agentid_to_linkid_map[linkid].remote_agentid_start;
365 remote_agentid_end =
366 config->remote_agentid_to_linkid_map[linkid].remote_agentid_end;
367
368 /*
369 * Skip configuring link if both start and end are 0, indicating
370 * there's no link
371 */
372 if ((remote_agentid_start == 0) && (remote_agentid_end == 0)) {
373 continue;
374 }
375
376 FWK_LOG_INFO(
377 MOD_NAME " Remote [AgentID %d - AgentID %d] Node Id: %" PRIu32,
378 remote_agentid_start,
379 remote_agentid_end,
380 nodeid_ra);
381
382 for (agentid = remote_agentid_start; agentid <= remote_agentid_end;
383 agentid++) {
384 reg_index = ctx->remote_rnf_ldid_value;
385
386 for (i = 0; i < ctx->hnf_count; i++) {
387 hnf_reg = (struct cmn700_hnf_reg *)ctx->hnf_node[i];
388 /* Write CCHA NodeID, local/remote and valid bit */
389 hnf_reg->HNF_RN_CLUSTER_PHYSID[reg_index][0] |= ((uint64_t)(
390 nodeid_ra |
391 (REMOTE_CCG_NODE << HNF_RN_PHYS_RN_LOCAL_REMOTE_SHIFT_VAL) |
392 (UINT64_C(0x1) << HNF_RN_PHYS_RN_ID_VALID_SHIFT_VAL)));
393 }
394
395 ctx->remote_rnf_ldid_value++;
396 }
397 }
398 }
399
enable_smp_mode(struct cmn700_device_ctx * ctx,const struct mod_cmn700_ccg_config * config)400 static void enable_smp_mode(
401 struct cmn700_device_ctx *ctx,
402 const struct mod_cmn700_ccg_config *config)
403 {
404 unsigned int ccg_ldid;
405 struct cmn700_ccg_ra_reg *ccg_ra_reg;
406 struct cmn700_ccg_ha_reg *ccg_ha_reg;
407
408 ccg_ldid = get_ldid(ctx, cmn700_ccg_ctx.is_prog_for_port_agg);
409 ccg_ra_reg = ctx->ccg_ra_reg_table[ccg_ldid].ccg_ra_reg;
410 ccg_ha_reg = ctx->ccg_ha_reg_table[ccg_ldid].ccg_ha_reg;
411
412 ccg_ra_reg->LINK_REGS[0].CCG_CCPRTCL_LINK_CTRL |=
413 (1 << CCG_RA_CCPRTCL_LINK_CTRL_SMP_MODE_EN_SHIFT_VAL);
414 ccg_ha_reg->LINK_REGS[0].CCG_CCPRTCL_LINK_CTRL |=
415 (1 << CCG_HA_CCPRTCL_LINK_CTRL_SMP_MODE_EN_SHIFT_VAL);
416
417 FWK_LOG_INFO(MOD_NAME "SMP Mode Enabled");
418 }
419
420 /*
421 * Helper function to check the status of the Upper link layer direct connect
422 * (ull to ull) mode
423 */
ccla_ull_status_wait_condition(void * data)424 static bool ccla_ull_status_wait_condition(void *data)
425 {
426 bool ccla_ull_status_rx_in_run;
427 bool ccla_ull_status_tx_in_run;
428 unsigned int ccg_ldid;
429 struct cmn700_ccla_reg *ccla_reg;
430 struct cmn700_device_ctx *ctx;
431
432 ctx = (struct cmn700_device_ctx *)data;
433 ccg_ldid = get_ldid(ctx, cmn700_ccg_ctx.is_prog_for_port_agg);
434 ccla_reg = ctx->ccla_reg_table[ccg_ldid].ccla_reg;
435
436 ccla_ull_status_rx_in_run =
437 ((ccla_reg->CCLA_ULL_STATUS & CCLA_ULL_STATUS_SEND_RX_ULL_STATE_MASK) >
438 0);
439
440 ccla_ull_status_tx_in_run =
441 ((ccla_reg->CCLA_ULL_STATUS & CCLA_ULL_STATUS_SEND_TX_ULL_STATE_MASK) >
442 0);
443
444 return (ccla_ull_status_rx_in_run && ccla_ull_status_tx_in_run);
445 }
446
enable_ull_to_ull_mode(struct cmn700_device_ctx * ctx,const struct mod_cmn700_ccg_config * config)447 static int enable_ull_to_ull_mode(
448 struct cmn700_device_ctx *ctx,
449 const struct mod_cmn700_ccg_config *config)
450 {
451 int status;
452 unsigned int ccg_ldid;
453 struct cmn700_ccla_reg *ccla_reg;
454
455 ccg_ldid = get_ldid(ctx, cmn700_ccg_ctx.is_prog_for_port_agg);
456 ccla_reg = ctx->ccla_reg_table[ccg_ldid].ccla_reg;
457
458 FWK_LOG_INFO(MOD_NAME "Enabling CCG ULL to ULL mode...");
459
460 /* Enabling ULL-to-ULL mode */
461 ccla_reg->CCLA_ULL_CTL = (1 << CCLA_ULL_CTL_ULL_TO_ULL_MODE_EN_SHIFT_VAL);
462
463 /* Setting send_vd_init */
464 ccla_reg->CCLA_ULL_CTL |= (1 << CCLA_ULL_CTL_SEND_VD_INIT_SHIFT_VAL);
465
466 /* Wait until link enable bits are set */
467 status = ctx->timer_api->wait(
468 FWK_ID_ELEMENT(FWK_MODULE_IDX_TIMER, 0),
469 CCLA_ULL_STATUS_TIMEOUT,
470 ccla_ull_status_wait_condition,
471 ctx);
472
473 if (status != FWK_SUCCESS) {
474 if ((ccla_reg->CCLA_ULL_STATUS &
475 CCLA_ULL_STATUS_SEND_RX_ULL_STATE_MASK) == 0) {
476 FWK_LOG_ERR(MOD_NAME "Rx ULL is in Stop state");
477 }
478
479 if ((ccla_reg->CCLA_ULL_STATUS &
480 CCLA_ULL_STATUS_SEND_TX_ULL_STATE_MASK) == 0) {
481 FWK_LOG_ERR(MOD_NAME "Tx ULL is in Stop state");
482 }
483
484 FWK_LOG_ERR(MOD_NAME "Enabling CCG ULL to ULL mode... Failed");
485 return status;
486 }
487
488 FWK_LOG_INFO(MOD_NAME "Enabling CCG ULL to ULL mode... Done");
489 return status;
490 }
491
program_ccg_ra_sam_addr_region(struct cmn700_device_ctx * ctx,const struct mod_cmn700_ccg_config * config)492 static void program_ccg_ra_sam_addr_region(
493 struct cmn700_device_ctx *ctx,
494 const struct mod_cmn700_ccg_config *config)
495 {
496 uint64_t blocks;
497 uint64_t size;
498 unsigned int ccg_ldid;
499 unsigned int i;
500 unsigned int remote_haid;
501 struct cmn700_ccg_ra_reg *ccg_ra_reg;
502
503 ccg_ldid = get_ldid(ctx, cmn700_ccg_ctx.is_prog_for_port_agg);
504 ccg_ra_reg = ctx->ccg_ra_reg_table[ccg_ldid].ccg_ra_reg;
505
506 FWK_LOG_INFO(
507 MOD_NAME "Configuring RA SAM for CCRA NodeID %d",
508 get_node_id(ccg_ra_reg));
509
510 for (i = 0; i < CMN700_MAX_RA_SAM_ADDR_REGION; i++) {
511 /* If the size is zero, skip that entry */
512 if (config->ra_mmap_table[i].size == 0) {
513 continue;
514 }
515
516 /* Size must be a multiple of SAM_GRANULARITY */
517 fwk_assert((config->ra_mmap_table[i].size % (64 * FWK_KIB)) == 0);
518
519 /* Size also must be a power of two */
520 fwk_assert(
521 (config->ra_mmap_table[i].size &
522 (config->ra_mmap_table[i].size - 1)) == 0);
523
524 /* Region base should be naturally aligned to the region size */
525 fwk_assert(
526 config->ra_mmap_table[i].base % config->ra_mmap_table[i].size == 0);
527
528 if (cmn700_ccg_ctx.is_prog_for_port_agg) {
529 remote_haid = config->port_aggregate_remote_haid[i];
530 } else {
531 remote_haid = config->ra_mmap_table[i].remote_haid;
532 }
533
534 FWK_LOG_INFO(
535 MOD_NAME " [0x%llx - 0x%llx] HAID %d",
536 config->ra_mmap_table[i].base,
537 config->ra_mmap_table[i].base + config->ra_mmap_table[i].size - 1,
538 remote_haid);
539
540 blocks = config->ra_mmap_table[i].size / (64 * FWK_KIB);
541 size = fwk_math_log2(blocks);
542
543 ccg_ra_reg->CCG_RA_SAM_ADDR_REGION_REG[i] = size |
544 (config->ra_mmap_table[i].base) |
545 ((uint64_t)remote_haid << SAM_ADDR_TARGET_HAID_SHIFT) |
546 (SAM_ADDR_REG_VALID_MASK);
547 }
548 }
549
enable_and_start_ccg_link_up_sequence(struct cmn700_device_ctx * ctx,uint8_t linkid)550 static int enable_and_start_ccg_link_up_sequence(
551 struct cmn700_device_ctx *ctx,
552 uint8_t linkid)
553 {
554 int status;
555 unsigned int ccg_ldid;
556 struct ccg_wait_condition_data wait_data;
557 struct cmn700_ccg_ra_reg *ccg_ra_reg;
558 struct cmn700_ccg_ha_reg *ccg_ha_reg;
559
560 ccg_ldid = get_ldid(ctx, cmn700_ccg_ctx.is_prog_for_port_agg);
561 ccg_ra_reg = ctx->ccg_ra_reg_table[ccg_ldid].ccg_ra_reg;
562 ccg_ha_reg = ctx->ccg_ha_reg_table[ccg_ldid].ccg_ha_reg;
563
564 if (linkid > 2) {
565 return FWK_E_PARAM;
566 }
567
568 wait_data.ctx = ctx;
569 wait_data.linkid = linkid;
570
571 FWK_LOG_INFO(MOD_NAME "Enabling CCG link %d...", linkid);
572 /* Set link enable bit to enable the CCG link */
573 ccg_ra_reg->LINK_REGS[linkid].CCG_CCPRTCL_LINK_CTRL |=
574 CCG_LINK_CTRL_EN_MASK;
575 ccg_ha_reg->LINK_REGS[linkid].CCG_CCPRTCL_LINK_CTRL |=
576 CCG_LINK_CTRL_EN_MASK;
577
578 /* Wait until link enable bits are set */
579 wait_data.cond = CCG_LINK_CTRL_EN_BIT_SET;
580 status = ctx->timer_api->wait(
581 FWK_ID_ELEMENT(FWK_MODULE_IDX_TIMER, 0),
582 CCG_CCPRTCL_LINK_CTRL_TIMEOUT,
583 ccg_link_wait_condition,
584 &wait_data);
585 if (status != FWK_SUCCESS) {
586 FWK_LOG_ERR(MOD_NAME "Enabling CCG link %d... Failed", linkid);
587 return status;
588 }
589 FWK_LOG_INFO(MOD_NAME "Enabling CCG link %d... Done", linkid);
590
591 FWK_LOG_INFO(MOD_NAME "Verifying link down status...");
592 /* Wait till link up bits are cleared in control register */
593 wait_data.cond = CCG_LINK_CTRL_UP_BIT_CLR;
594 status = ctx->timer_api->wait(
595 FWK_ID_ELEMENT(FWK_MODULE_IDX_TIMER, 0),
596 CCG_CCPRTCL_LINK_CTRL_TIMEOUT,
597 ccg_link_wait_condition,
598 &wait_data);
599 if (status != FWK_SUCCESS) {
600 FWK_LOG_ERR(MOD_NAME "Verifying link down status... Failed");
601 return status;
602 }
603
604 /* Wait till link down bits are set in status register */
605 wait_data.cond = CCG_LINK_STATUS_DWN_BIT_SET;
606 status = ctx->timer_api->wait(
607 FWK_ID_ELEMENT(FWK_MODULE_IDX_TIMER, 0),
608 CCG_CCPRTCL_LINK_CTRL_TIMEOUT,
609 ccg_link_wait_condition,
610 &wait_data);
611 if (status != FWK_SUCCESS) {
612 FWK_LOG_ERR(MOD_NAME "Verifying link down status... Failed");
613 return status;
614 }
615
616 /* Wait till link ACK bits are cleared in status register */
617 wait_data.cond = CCG_LINK_STATUS_ACK_BIT_CLR;
618 status = ctx->timer_api->wait(
619 FWK_ID_ELEMENT(FWK_MODULE_IDX_TIMER, 0),
620 CCG_CCPRTCL_LINK_CTRL_TIMEOUT,
621 ccg_link_wait_condition,
622 &wait_data);
623 if (status != FWK_SUCCESS) {
624 FWK_LOG_ERR(MOD_NAME "Verifying link down status... Failed");
625 return status;
626 }
627 FWK_LOG_INFO(MOD_NAME "Verifying link down status... Done");
628
629 FWK_LOG_INFO(MOD_NAME "Bringing up link...");
630 /* Bring up link using link request bit */
631 ccg_ra_reg->LINK_REGS[linkid].CCG_CCPRTCL_LINK_CTRL |=
632 CCG_LINK_CTRL_REQ_MASK;
633 ccg_ha_reg->LINK_REGS[linkid].CCG_CCPRTCL_LINK_CTRL |=
634 CCG_LINK_CTRL_REQ_MASK;
635
636 /* Wait till link ACK bits are set in status register */
637 wait_data.cond = CCG_LINK_STATUS_ACK_BIT_SET;
638 status = ctx->timer_api->wait(
639 FWK_ID_ELEMENT(FWK_MODULE_IDX_TIMER, 0),
640 CCG_CCPRTCL_LINK_CTRL_TIMEOUT,
641 ccg_link_wait_condition,
642 &wait_data);
643 if (status != FWK_SUCCESS) {
644 FWK_LOG_ERR(MOD_NAME "Bringing up link... Failed");
645 return status;
646 }
647
648 /* Wait till link down bits are cleared in status register */
649 wait_data.cond = CCG_LINK_STATUS_DWN_BIT_CLR;
650 status = ctx->timer_api->wait(
651 FWK_ID_ELEMENT(FWK_MODULE_IDX_TIMER, 0),
652 CCG_CCPRTCL_LINK_CTRL_TIMEOUT,
653 ccg_link_wait_condition,
654 &wait_data);
655 if (status != FWK_SUCCESS) {
656 FWK_LOG_ERR(MOD_NAME "Bringing up link... Failed");
657 return status;
658 }
659 FWK_LOG_INFO(MOD_NAME "Bringing up link... Done");
660
661 return FWK_SUCCESS;
662 }
663
ccg_setup(const unsigned int chip_id,struct cmn700_device_ctx * ctx,const struct mod_cmn700_ccg_config * ccg_config)664 int ccg_setup(
665 const unsigned int chip_id,
666 struct cmn700_device_ctx *ctx,
667 const struct mod_cmn700_ccg_config *ccg_config)
668 {
669 int status;
670 uint8_t rnf_ldid;
671 uint8_t rni_ldid;
672 uint8_t rnd_ldid;
673 uint8_t agentid;
674 uint8_t remote_agentid;
675 uint8_t offset_id;
676 uint8_t local_ra_cnt;
677 unsigned int i;
678 unsigned int unique_remote_rnf_ldid_value;
679
680 FWK_LOG_INFO(MOD_NAME "Programming CCG gateway...");
681
682 /* Assign the max count among the RNs as local_ra_cnt */
683 if ((ctx->rnf_count > ctx->rnd_count) &&
684 (ctx->rnf_count > ctx->rni_count)) {
685 local_ra_cnt = ctx->rnf_count;
686 } else if (ctx->rnd_count > ctx->rni_count) {
687 local_ra_cnt = ctx->rnd_count;
688 } else {
689 local_ra_cnt = ctx->rni_count;
690 }
691
692 cmn700_ccg_ctx.is_prog_for_port_agg = false;
693
694 do {
695 /* Set the global config data */
696 config = ccg_config;
697
698 if (ccg_config->smp_mode) {
699 enable_smp_mode(ctx, ccg_config);
700 }
701
702 /*
703 * In order to assign unique AgentIDs across multiple chips, chip_id is
704 * used as factor to offset the AgentID value
705 */
706 cmn700_ccg_ctx.raid_value = 0;
707 offset_id = chip_id * local_ra_cnt;
708
709 for (rnf_ldid = 0; rnf_ldid < ctx->rnf_count; rnf_ldid++) {
710 agentid = cmn700_ccg_ctx.raid_value + offset_id;
711
712 /* Program RAID values in CCRA LDID to RAID LUT */
713 program_ccg_ra_rnf_ldid_to_exp_raid_reg(ctx, rnf_ldid, agentid);
714 }
715
716 /* Program agentid to linkid LUT for remote agents in CCRA/CCHA/CCLA */
717 program_agentid_to_linkid_reg(ctx, ccg_config);
718
719 /* Program HN-F ldid to CHI NodeID for remote RN-F agents */
720 program_hnf_ldid_to_chi_node_id_reg(ctx, ccg_config);
721
722 /*
723 * unique_remote_rnf_ldid_value is used to keep track of the
724 * ldid of the remote RNF agents
725 */
726 unique_remote_rnf_ldid_value = ctx->rnf_count;
727
728 if (ccg_config->remote_rnf_count && (ctx->rnf_count == 0)) {
729 FWK_LOG_ERR(
730 MOD_NAME
731 "Remote RN-F Count can't be %u when RN-F count is zero",
732 ccg_config->remote_rnf_count);
733 fwk_unexpected();
734 }
735
736 for (i = 0; i < ccg_config->remote_rnf_count; i++) {
737 /*
738 * The remote_agentid (RAID) should not include the current chip's
739 * AgentIDs. If `block` is less than the current chip_id, then
740 * include the AgentIDs starting from chip 0 till (not including)
741 * current chip. If the `block` is equal or greater than the current
742 * chip, then include the AgentIDs from next chip till the max chip.
743 */
744 if ((i / ctx->rnf_count) < chip_id) {
745 remote_agentid = (i % ctx->rnf_count) +
746 (local_ra_cnt * (i / ctx->rnf_count));
747 } else {
748 remote_agentid = (i % ctx->rnf_count) + local_ra_cnt +
749 (local_ra_cnt * (i / ctx->rnf_count));
750 }
751
752 /* Program the CCHA raid to ldid LUT */
753 program_ccg_ha_raid_to_ldid_lut(
754 ctx, remote_agentid, unique_remote_rnf_ldid_value);
755
756 unique_remote_rnf_ldid_value++;
757 }
758
759 /* Program the unique HAID for the CCHA block */
760 program_ccg_ha_id(ctx);
761
762 cmn700_ccg_ctx.raid_value = 0;
763 offset_id = chip_id * local_ra_cnt;
764
765 for (rnd_ldid = 0; rnd_ldid < ctx->rnd_count; rnd_ldid++) {
766 /* Determine agentid of the remote agents */
767 agentid = cmn700_ccg_ctx.raid_value + offset_id;
768
769 /* Program RAID values in CCRA LDID to RAID LUT */
770 program_ccg_ra_rnd_ldid_to_exp_raid_reg(ctx, rnd_ldid, agentid);
771 }
772
773 cmn700_ccg_ctx.raid_value = 0;
774 offset_id = chip_id * local_ra_cnt;
775
776 for (rni_ldid = 0; rni_ldid < ctx->rni_count; rni_ldid++) {
777 /* Determine agentid of the remote agents */
778 agentid = cmn700_ccg_ctx.raid_value + offset_id;
779
780 /* Program RAID values in CCRA LDID to RAID LUT */
781 program_ccg_ra_rni_ldid_to_exp_raid_reg(ctx, rni_ldid, agentid);
782 }
783
784 /*
785 * Program the CCRA SAM with the address range and the corresponding
786 * remote HAID
787 */
788 program_ccg_ra_sam_addr_region(ctx, ccg_config);
789
790 if (ccg_config->ull_to_ull_mode) {
791 status = enable_ull_to_ull_mode(ctx, ccg_config);
792 if (status != FWK_SUCCESS) {
793 return status;
794 }
795 }
796 /* Program the Link Control registers present in CCRA/CCHA/CCLA */
797 status = enable_and_start_ccg_link_up_sequence(ctx, 0);
798
799 if (config->port_aggregate && !cmn700_ccg_ctx.is_prog_for_port_agg) {
800 cmn700_ccg_ctx.is_prog_for_port_agg = true;
801 FWK_LOG_INFO(MOD_NAME
802 "Programming CCG gateway for Port Aggregation...");
803 } else {
804 cmn700_ccg_ctx.is_prog_for_port_agg = false;
805 }
806 } while (config->port_aggregate && cmn700_ccg_ctx.is_prog_for_port_agg);
807
808 return status;
809 }
810
ccg_exchange_protocol_credit(struct cmn700_device_ctx * ctx,const struct mod_cmn700_ccg_config * ccg_config)811 int ccg_exchange_protocol_credit(
812 struct cmn700_device_ctx *ctx,
813 const struct mod_cmn700_ccg_config *ccg_config)
814 {
815 int linkid;
816 unsigned int ccg_ldid;
817 struct cmn700_ccg_ra_reg *ccg_ra_reg;
818 struct cmn700_ccg_ha_reg *ccg_ha_reg;
819
820 cmn700_ccg_ctx.is_prog_for_port_agg = false;
821
822 do {
823 config = ccg_config;
824 ccg_ldid = get_ldid(ctx, cmn700_ccg_ctx.is_prog_for_port_agg);
825 ccg_ra_reg = ctx->ccg_ra_reg_table[ccg_ldid].ccg_ra_reg;
826 ccg_ha_reg = ctx->ccg_ha_reg_table[ccg_ldid].ccg_ha_reg;
827
828 /* Current support enables Link 0 only */
829 linkid = 0;
830
831 FWK_LOG_INFO(
832 MOD_NAME "Exchanging protocol credits for link %d...", linkid);
833 /* Exchange protocol credits using link up bit */
834 ccg_ra_reg->LINK_REGS[linkid].CCG_CCPRTCL_LINK_CTRL |=
835 CCG_LINK_CTRL_UP_MASK;
836 ccg_ha_reg->LINK_REGS[linkid].CCG_CCPRTCL_LINK_CTRL |=
837 CCG_LINK_CTRL_UP_MASK;
838 FWK_LOG_INFO(
839 MOD_NAME "Exchanging protocol credits for link %d... Done", linkid);
840
841 if (config->port_aggregate && !cmn700_ccg_ctx.is_prog_for_port_agg) {
842 cmn700_ccg_ctx.is_prog_for_port_agg = true;
843 FWK_LOG_INFO(MOD_NAME
844 "Exchange Protocol Credit for Port Aggregation...");
845 } else {
846 cmn700_ccg_ctx.is_prog_for_port_agg = false;
847 }
848 } while (config->port_aggregate && cmn700_ccg_ctx.is_prog_for_port_agg);
849
850 return FWK_SUCCESS;
851 }
852
ccg_enter_system_coherency(struct cmn700_device_ctx * ctx,const struct mod_cmn700_ccg_config * ccg_config)853 int ccg_enter_system_coherency(
854 struct cmn700_device_ctx *ctx,
855 const struct mod_cmn700_ccg_config *ccg_config)
856 {
857 int status;
858 int linkid;
859 unsigned int ccg_ldid;
860 struct ccg_wait_condition_data wait_data;
861 struct cmn700_ccg_ha_reg *ccg_ha_reg;
862
863 cmn700_ccg_ctx.is_prog_for_port_agg = false;
864
865 do {
866 config = ccg_config;
867 ccg_ldid = get_ldid(ctx, cmn700_ccg_ctx.is_prog_for_port_agg);
868 ccg_ha_reg = ctx->ccg_ha_reg_table[ccg_ldid].ccg_ha_reg;
869
870 /* Current support enables Link 0 only */
871 linkid = 0;
872
873 wait_data.ctx = ctx;
874 wait_data.linkid = linkid;
875
876 FWK_LOG_INFO(
877 MOD_NAME "Entering system coherency for link %d...", linkid);
878 /* Enter system coherency by setting DVMDOMAIN request bit */
879 ccg_ha_reg->LINK_REGS[linkid].CCG_CCPRTCL_LINK_CTRL |=
880 CCG_LINK_CTRL_DVMDOMAIN_REQ_MASK;
881
882 /* Wait till DVMDOMAIN ACK bit is set in status register */
883 wait_data.cond = CCG_LINK_STATUS_HA_DVMDOMAIN_ACK_BIT_SET;
884 status = ctx->timer_api->wait(
885 FWK_ID_ELEMENT(FWK_MODULE_IDX_TIMER, 0),
886 CCG_CCPRTCL_LINK_DVMDOMAIN_TIMEOUT,
887 ccg_link_wait_condition,
888 &wait_data);
889 if (status != FWK_SUCCESS) {
890 FWK_LOG_ERR(
891 MOD_NAME "Entering system coherency for link %d... Failed",
892 linkid);
893 return status;
894 }
895 FWK_LOG_INFO(
896 MOD_NAME "Entering system coherency for link %d... Done", linkid);
897
898 if (config->port_aggregate && !cmn700_ccg_ctx.is_prog_for_port_agg) {
899 cmn700_ccg_ctx.is_prog_for_port_agg = true;
900 FWK_LOG_INFO(MOD_NAME
901 "Enter system coherency for Port Aggregation...");
902 } else {
903 cmn700_ccg_ctx.is_prog_for_port_agg = false;
904 }
905 } while (config->port_aggregate && cmn700_ccg_ctx.is_prog_for_port_agg);
906
907 return FWK_SUCCESS;
908 }
909
ccg_enter_dvm_domain(struct cmn700_device_ctx * ctx,const struct mod_cmn700_ccg_config * ccg_config)910 int ccg_enter_dvm_domain(
911 struct cmn700_device_ctx *ctx,
912 const struct mod_cmn700_ccg_config *ccg_config)
913 {
914 int status;
915 int linkid;
916 unsigned int ccg_ldid;
917 struct ccg_wait_condition_data wait_data;
918 struct cmn700_ccg_ra_reg *ccg_ra_reg;
919
920 cmn700_ccg_ctx.is_prog_for_port_agg = false;
921
922 do {
923 config = ccg_config;
924 ccg_ldid = get_ldid(ctx, cmn700_ccg_ctx.is_prog_for_port_agg);
925 ccg_ra_reg = ctx->ccg_ra_reg_table[ccg_ldid].ccg_ra_reg;
926
927 /* Current support enables Link 0 only */
928 linkid = 0;
929
930 wait_data.ctx = ctx;
931 wait_data.linkid = linkid;
932
933 FWK_LOG_INFO(MOD_NAME "Entering DVM domain for link %d...", linkid);
934 /* DVM domain entry by setting DVMDOMAIN request bit */
935 ccg_ra_reg->LINK_REGS[linkid].CCG_CCPRTCL_LINK_CTRL |=
936 CCG_LINK_CTRL_DVMDOMAIN_REQ_MASK;
937
938 /* Wait till DVMDOMAIN ACK bit is set in status register */
939 wait_data.cond = CCG_LINK_STATUS_RA_DVMDOMAIN_ACK_BIT_SET;
940 status = ctx->timer_api->wait(
941 FWK_ID_ELEMENT(FWK_MODULE_IDX_TIMER, 0),
942 CCG_CCPRTCL_LINK_DVMDOMAIN_TIMEOUT,
943 ccg_link_wait_condition,
944 &wait_data);
945 if (status != FWK_SUCCESS) {
946 FWK_LOG_ERR(
947 MOD_NAME "Entering DVM domain for link %d... Failed", linkid);
948 return status;
949 }
950 FWK_LOG_INFO(
951 MOD_NAME "Entering DVM domain for link %d... Done", linkid);
952
953 if (config->port_aggregate && !cmn700_ccg_ctx.is_prog_for_port_agg) {
954 cmn700_ccg_ctx.is_prog_for_port_agg = true;
955 FWK_LOG_INFO(MOD_NAME
956 "Entering DVM domain for Port Aggregation...");
957 } else {
958 cmn700_ccg_ctx.is_prog_for_port_agg = false;
959 }
960 } while (config->port_aggregate && cmn700_ccg_ctx.is_prog_for_port_agg);
961
962 return FWK_SUCCESS;
963 }
964