• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <errno.h>
9 #include <stdbool.h>
10 
11 #include <arch.h>
12 #include <common/debug.h>
13 #include <drivers/arm/ccn.h>
14 #include <lib/bakery_lock.h>
15 #include <lib/mmio.h>
16 
17 #include "ccn_private.h"
18 
19 static const ccn_desc_t *ccn_plat_desc;
20 #if defined(IMAGE_BL31) || (!defined(__aarch64__) && defined(IMAGE_BL32))
21 DEFINE_BAKERY_LOCK(ccn_lock);
22 #endif
23 
24 /*******************************************************************************
25  * This function takes the base address of the CCN's programmer's view (PV), a
26  * region ID of one of the 256 regions (0-255) and a register offset within the
27  * region. It converts the first two parameters into a base address and uses it
28  * to read the register at the offset.
29  ******************************************************************************/
ccn_reg_read(uintptr_t periphbase,unsigned int region_id,unsigned int register_offset)30 static inline unsigned long long ccn_reg_read(uintptr_t periphbase,
31 			     unsigned int region_id,
32 			     unsigned int register_offset)
33 {
34 	uintptr_t region_base;
35 
36 	assert(periphbase);
37 	assert(region_id < REGION_ID_LIMIT);
38 
39 	region_base = periphbase + region_id_to_base(region_id);
40 	return mmio_read_64(region_base + register_offset);
41 }
42 
43 /*******************************************************************************
44  * This function takes the base address of the CCN's programmer's view (PV), a
45  * region ID of one of the 256 regions (0-255), a register offset within the
46  * region and a value. It converts the first two parameters into a base address
47  * and uses it to write the value in the register at the offset.
48  ******************************************************************************/
ccn_reg_write(uintptr_t periphbase,unsigned int region_id,unsigned int register_offset,unsigned long long value)49 static inline void ccn_reg_write(uintptr_t periphbase,
50 			  unsigned int region_id,
51 			  unsigned int register_offset,
52 			  unsigned long long value)
53 {
54 	uintptr_t region_base;
55 
56 	assert(periphbase);
57 	assert(region_id < REGION_ID_LIMIT);
58 
59 	region_base = periphbase + region_id_to_base(region_id);
60 	mmio_write_64(region_base + register_offset, value);
61 }
62 
63 #if ENABLE_ASSERTIONS
64 
65 typedef struct rn_info {
66 		unsigned char node_desc[MAX_RN_NODES];
67 	} rn_info_t;
68 
69 /*******************************************************************************
70  * This function takes the base address of the CCN's programmer's view (PV) and
71  * the node ID of a Request Node (RN-D or RN-I). It returns the maximum number
72  * of master interfaces resident on that node. This number is equal to the least
73  * significant two bits of the node type ID + 1.
74  ******************************************************************************/
ccn_get_rni_mcount(uintptr_t periphbase,unsigned int rn_id)75 static unsigned int ccn_get_rni_mcount(uintptr_t periphbase,
76 				       unsigned int rn_id)
77 {
78 	unsigned int rn_type_id;
79 
80 	/* Use the node id to find the type of RN-I/D node */
81 	rn_type_id = get_node_type(ccn_reg_read(periphbase,
82 						rn_id + RNI_REGION_ID_START,
83 						REGION_ID_OFFSET));
84 
85 	/* Return the number master interfaces based on node type */
86 	return rn_type_id_to_master_cnt(rn_type_id);
87 }
88 
89 /*******************************************************************************
90  * This function reads the CCN registers to find the following information about
91  * the ACE/ACELite/ACELite+DVM/CHI interfaces resident on the various types of
92  * Request Nodes (RN-Fs, RN-Is and RN-Ds) in the system:
93  *
94  * 1. The total number of such interfaces that this CCN IP supports. This is the
95  *    cumulative number of interfaces across all Request node types. It is
96  *    passed back as the return value of this function.
97  *
98  * 2. The maximum number of interfaces of a type resident on a Request node of
99  *    one of the three types. This information is populated in the 'info'
100  *    array provided by the caller as described next.
101  *
102  *    The array has 64 entries. Each entry corresponds to a Request node. The
103  *    Miscellaneous node's programmer's view has RN-F, RN-I and RN-D ID
104  *    registers. For each RN-I and RN-D ID indicated as being present in these
105  *    registers, its identification register (offset 0xFF00) is read. This
106  *    register specifies the maximum number of master interfaces the node
107  *    supports. For RN-Fs it is assumed that there can be only a single fully
108  *    coherent master resident on each node. The counts for each type of node
109  *    are use to populate the array entry at the index corresponding to the node
110  *    ID i.e. rn_info[node ID] = <number of master interfaces>
111  ******************************************************************************/
ccn_get_rn_master_info(uintptr_t periphbase,rn_info_t * info)112 static unsigned int ccn_get_rn_master_info(uintptr_t periphbase,
113 					   rn_info_t *info)
114 {
115 	unsigned int num_masters = 0;
116 	rn_types_t rn_type;
117 
118 	assert (info);
119 
120 	for (rn_type = RN_TYPE_RNF; rn_type < NUM_RN_TYPES; rn_type++) {
121 		unsigned int mn_reg_off, node_id;
122 		unsigned long long rn_bitmap;
123 
124 		/*
125 		 * RN-F, RN-I, RN-D node registers in the MN region occupy
126 		 * contiguous 16 byte apart offsets.
127 		 */
128 		mn_reg_off = MN_RNF_NODEID_OFFSET + (rn_type << 4);
129 		rn_bitmap = ccn_reg_read(periphbase, MN_REGION_ID, mn_reg_off);
130 
131 		FOR_EACH_PRESENT_NODE_ID(node_id, rn_bitmap) {
132 			unsigned int node_mcount;
133 
134 			/*
135 			 * A RN-F does not have a node type since it does not
136 			 * export a programmer's interface. It can only have a
137 			 * single fully coherent master residing on it. If the
138 			 * offset of the MN(Miscellaneous Node) register points
139 			 * to a RN-I/D node then the master count is set to the
140 			 * maximum number of master interfaces that can possibly
141 			 * reside on the node.
142 			 */
143 			node_mcount = (mn_reg_off == MN_RNF_NODEID_OFFSET ? 1 :
144 				       ccn_get_rni_mcount(periphbase, node_id));
145 
146 			/*
147 			 * Use this value to increment the maximum possible
148 			 * master interfaces in the system.
149 			 */
150 			num_masters += node_mcount;
151 
152 			/*
153 			 * Update the entry in 'info' for this node ID with
154 			 * the maximum number of masters than can sit on
155 			 * it. This information will be used to validate the
156 			 * node information passed by the platform later.
157 			 */
158 			info->node_desc[node_id] = node_mcount;
159 		}
160 	}
161 
162 	return num_masters;
163 }
164 
165 /*******************************************************************************
166  * This function validates parameters passed by the platform (in a debug build).
167  * It collects information about the maximum number of master interfaces that:
168  * a) the CCN IP can accommodate and
169  * b) can exist on each Request node.
170  * It compares this with the information provided by the platform to determine
171  * the validity of the latter.
172  ******************************************************************************/
ccn_validate_plat_params(const ccn_desc_t * plat_desc)173 static void __init ccn_validate_plat_params(const ccn_desc_t *plat_desc)
174 {
175 	unsigned int master_id, num_rn_masters;
176 	rn_info_t info = { {0} };
177 
178 	assert(plat_desc);
179 	assert(plat_desc->periphbase);
180 	assert(plat_desc->master_to_rn_id_map);
181 	assert(plat_desc->num_masters);
182 	assert(plat_desc->num_masters < CCN_MAX_RN_MASTERS);
183 
184 	/*
185 	 * Find the number and properties of fully coherent, IO coherent and IO
186 	 * coherent + DVM master interfaces
187 	 */
188 	num_rn_masters = ccn_get_rn_master_info(plat_desc->periphbase, &info);
189 	assert(plat_desc->num_masters < num_rn_masters);
190 
191 	/*
192 	 * Iterate through the Request nodes specified by the platform.
193 	 * Decrement the count of the masters in the 'info' array for each
194 	 * Request node encountered. If the count would drop below 0 then the
195 	 * platform's view of this aspect of CCN configuration is incorrect.
196 	 */
197 	for (master_id = 0; master_id < plat_desc->num_masters; master_id++) {
198 		unsigned int node_id;
199 
200 		node_id = plat_desc->master_to_rn_id_map[master_id];
201 		assert(node_id < MAX_RN_NODES);
202 		assert(info.node_desc[node_id]);
203 		info.node_desc[node_id]--;
204 	}
205 }
206 #endif /* ENABLE_ASSERTIONS */
207 
208 /*******************************************************************************
209  * This function validates parameters passed by the platform (in a debug build)
210  * and initialises its internal data structures. A lock is required to prevent
211  * simultaneous CCN operations at runtime (only BL31) to add and remove Request
212  * nodes from coherency.
213  ******************************************************************************/
ccn_init(const ccn_desc_t * plat_desc)214 void __init ccn_init(const ccn_desc_t *plat_desc)
215 {
216 #if ENABLE_ASSERTIONS
217 	ccn_validate_plat_params(plat_desc);
218 #endif
219 
220 	ccn_plat_desc = plat_desc;
221 }
222 
223 /*******************************************************************************
224  * This function converts a bit map of master interface IDs to a bit map of the
225  * Request node IDs that they reside on.
226  ******************************************************************************/
ccn_master_to_rn_id_map(unsigned long long master_map)227 static unsigned long long ccn_master_to_rn_id_map(unsigned long long master_map)
228 {
229 	unsigned long long rn_id_map = 0;
230 	unsigned int node_id, iface_id;
231 
232 	assert(master_map);
233 	assert(ccn_plat_desc);
234 
235 	FOR_EACH_PRESENT_MASTER_INTERFACE(iface_id, master_map) {
236 		assert(iface_id < ccn_plat_desc->num_masters);
237 
238 		/* Convert the master ID into the node ID */
239 		node_id = ccn_plat_desc->master_to_rn_id_map[iface_id];
240 
241 		/* Set the bit corresponding to this node ID */
242 		rn_id_map |= (1ULL << node_id);
243 	}
244 
245 	return rn_id_map;
246 }
247 
248 /*******************************************************************************
249  * This function executes the necessary operations to add or remove Request node
250  * IDs specified in the 'rn_id_map' bitmap from the snoop/DVM domains specified
251  * in the 'hn_id_map'. The 'region_id' specifies the ID of the first HN-F/MN
252  * on which the operation should be performed. 'op_reg_offset' specifies the
253  * type of operation (add/remove). 'stat_reg_offset' specifies the register
254  * which should be polled to determine if the operation has completed or not.
255  ******************************************************************************/
ccn_snoop_dvm_do_op(unsigned long long rn_id_map,unsigned long long hn_id_map,unsigned int region_id,unsigned int op_reg_offset,unsigned int stat_reg_offset)256 static void ccn_snoop_dvm_do_op(unsigned long long rn_id_map,
257 				unsigned long long hn_id_map,
258 				unsigned int region_id,
259 				unsigned int op_reg_offset,
260 				unsigned int stat_reg_offset)
261 {
262 	unsigned int start_region_id;
263 
264 	assert(ccn_plat_desc);
265 	assert(ccn_plat_desc->periphbase);
266 
267 #if defined(IMAGE_BL31) || (!defined(__aarch64__) && defined(IMAGE_BL32))
268 	bakery_lock_get(&ccn_lock);
269 #endif
270 	start_region_id = region_id;
271 	FOR_EACH_PRESENT_REGION_ID(start_region_id, hn_id_map) {
272 		ccn_reg_write(ccn_plat_desc->periphbase,
273 			      start_region_id,
274 			      op_reg_offset,
275 			      rn_id_map);
276 	}
277 
278 	start_region_id = region_id;
279 
280 	FOR_EACH_PRESENT_REGION_ID(start_region_id, hn_id_map) {
281 		WAIT_FOR_DOMAIN_CTRL_OP_COMPLETION(start_region_id,
282 						   stat_reg_offset,
283 						   op_reg_offset,
284 						   rn_id_map);
285 	}
286 
287 #if defined(IMAGE_BL31) || (!defined(__aarch64__) && defined(IMAGE_BL32))
288 	bakery_lock_release(&ccn_lock);
289 #endif
290 }
291 
292 /*******************************************************************************
293  * The following functions provide the boot and runtime API to the platform for
294  * adding and removing master interfaces from the snoop/DVM domains. A bitmap of
295  * master interfaces IDs is passed as a parameter. It is converted into a bitmap
296  * of Request node IDs using the mapping provided by the platform while
297  * initialising the driver.
298  * For example, consider a dual cluster system where the clusters have values 0
299  * & 1 in the affinity level 1 field of their respective MPIDRs. While
300  * initialising this driver, the platform provides the mapping between each
301  * cluster and the corresponding Request node. To add or remove a cluster from
302  * the snoop and dvm domain, the bit position corresponding to the cluster ID
303  * should be set in the 'master_iface_map' i.e. to remove both clusters the
304  * bitmap would equal 0x11.
305  ******************************************************************************/
ccn_enter_snoop_dvm_domain(unsigned long long master_iface_map)306 void ccn_enter_snoop_dvm_domain(unsigned long long master_iface_map)
307 {
308 	unsigned long long rn_id_map;
309 
310 	rn_id_map = ccn_master_to_rn_id_map(master_iface_map);
311 	ccn_snoop_dvm_do_op(rn_id_map,
312 			    CCN_GET_HN_NODEID_MAP(ccn_plat_desc->periphbase,
313 						  MN_HNF_NODEID_OFFSET),
314 			    HNF_REGION_ID_START,
315 			    HNF_SDC_SET_OFFSET,
316 			    HNF_SDC_STAT_OFFSET);
317 
318 	ccn_snoop_dvm_do_op(rn_id_map,
319 			    CCN_GET_MN_NODEID_MAP(ccn_plat_desc->periphbase),
320 			    MN_REGION_ID,
321 			    MN_DDC_SET_OFFSET,
322 			    MN_DDC_STAT_OFFSET);
323 }
324 
ccn_exit_snoop_dvm_domain(unsigned long long master_iface_map)325 void ccn_exit_snoop_dvm_domain(unsigned long long master_iface_map)
326 {
327 	unsigned long long rn_id_map;
328 
329 	rn_id_map = ccn_master_to_rn_id_map(master_iface_map);
330 	ccn_snoop_dvm_do_op(rn_id_map,
331 			    CCN_GET_HN_NODEID_MAP(ccn_plat_desc->periphbase,
332 						  MN_HNF_NODEID_OFFSET),
333 			    HNF_REGION_ID_START,
334 			    HNF_SDC_CLR_OFFSET,
335 			    HNF_SDC_STAT_OFFSET);
336 
337 	ccn_snoop_dvm_do_op(rn_id_map,
338 			    CCN_GET_MN_NODEID_MAP(ccn_plat_desc->periphbase),
339 			    MN_REGION_ID,
340 			    MN_DDC_CLR_OFFSET,
341 			    MN_DDC_STAT_OFFSET);
342 }
343 
ccn_enter_dvm_domain(unsigned long long master_iface_map)344 void ccn_enter_dvm_domain(unsigned long long master_iface_map)
345 {
346 	unsigned long long rn_id_map;
347 
348 	rn_id_map = ccn_master_to_rn_id_map(master_iface_map);
349 	ccn_snoop_dvm_do_op(rn_id_map,
350 			    CCN_GET_MN_NODEID_MAP(ccn_plat_desc->periphbase),
351 			    MN_REGION_ID,
352 			    MN_DDC_SET_OFFSET,
353 			    MN_DDC_STAT_OFFSET);
354 }
355 
ccn_exit_dvm_domain(unsigned long long master_iface_map)356 void ccn_exit_dvm_domain(unsigned long long master_iface_map)
357 {
358 	unsigned long long rn_id_map;
359 
360 	rn_id_map = ccn_master_to_rn_id_map(master_iface_map);
361 	ccn_snoop_dvm_do_op(rn_id_map,
362 			    CCN_GET_MN_NODEID_MAP(ccn_plat_desc->periphbase),
363 			    MN_REGION_ID,
364 			    MN_DDC_CLR_OFFSET,
365 			    MN_DDC_STAT_OFFSET);
366 }
367 
368 /*******************************************************************************
369  * This function returns the run mode of all the L3 cache partitions in the
370  * system. The state is expected to be one of NO_L3, SF_ONLY, L3_HAM or
371  * L3_FAM. Instead of comparing the states reported by all HN-Fs, the state of
372  * the first present HN-F node is reported. Since the driver does not export an
373  * interface to program them separately, there is no reason to perform this
374  * check. An HN-F could report that the L3 cache is transitioning from one mode
375  * to another e.g. HNF_PM_NOL3_2_SFONLY. In this case, the function waits for
376  * the transition to complete and reports the final state.
377  ******************************************************************************/
ccn_get_l3_run_mode(void)378 unsigned int ccn_get_l3_run_mode(void)
379 {
380 	unsigned long long hnf_pstate_stat;
381 
382 	assert(ccn_plat_desc);
383 	assert(ccn_plat_desc->periphbase);
384 
385 	/*
386 	 * Wait for a L3 cache partition to enter any run mode. The pstate
387 	 * parameter is read from an HN-F P-state status register. A non-zero
388 	 * value in bits[1:0] means that the cache is transitioning to a run
389 	 * mode.
390 	 */
391 	do {
392 		hnf_pstate_stat = ccn_reg_read(ccn_plat_desc->periphbase,
393 					       HNF_REGION_ID_START,
394 					       HNF_PSTATE_STAT_OFFSET);
395 	} while (hnf_pstate_stat & 0x3);
396 
397 	return PSTATE_TO_RUN_MODE(hnf_pstate_stat);
398 }
399 
400 /*******************************************************************************
401  * This function sets the run mode of all the L3 cache partitions in the
402  * system to one of NO_L3, SF_ONLY, L3_HAM or L3_FAM depending upon the state
403  * specified by the 'mode' argument.
404  ******************************************************************************/
ccn_set_l3_run_mode(unsigned int mode)405 void ccn_set_l3_run_mode(unsigned int mode)
406 {
407 	unsigned long long mn_hnf_id_map, hnf_pstate_stat;
408 	unsigned int region_id;
409 
410 	assert(ccn_plat_desc);
411 	assert(ccn_plat_desc->periphbase);
412 	assert(mode <= CCN_L3_RUN_MODE_FAM);
413 
414 	mn_hnf_id_map = ccn_reg_read(ccn_plat_desc->periphbase,
415 				     MN_REGION_ID,
416 				     MN_HNF_NODEID_OFFSET);
417 	region_id = HNF_REGION_ID_START;
418 
419 	/* Program the desired run mode */
420 	FOR_EACH_PRESENT_REGION_ID(region_id, mn_hnf_id_map) {
421 		ccn_reg_write(ccn_plat_desc->periphbase,
422 			      region_id,
423 			      HNF_PSTATE_REQ_OFFSET,
424 			      mode);
425 	}
426 
427 	/* Wait for the caches to transition to the run mode */
428 	region_id = HNF_REGION_ID_START;
429 	FOR_EACH_PRESENT_REGION_ID(region_id, mn_hnf_id_map) {
430 		/*
431 		 * Wait for a L3 cache partition to enter a target run
432 		 * mode. The pstate parameter is read from an HN-F P-state
433 		 * status register.
434 		 */
435 		do {
436 			hnf_pstate_stat = ccn_reg_read(ccn_plat_desc->periphbase,
437 					       region_id,
438 					       HNF_PSTATE_STAT_OFFSET);
439 		} while (((hnf_pstate_stat & HNF_PSTATE_MASK) >> 2) != mode);
440 	}
441 }
442 
443 /*******************************************************************************
444  * This function configures system address map and provides option to enable the
445  * 3SN striping mode of Slave node operation. The Slave node IDs and the Top
446  * Address bit1 and bit0 are provided as parameters to this function. This
447  * configuration is needed only if network contains a single SN-F or 3 SN-F and
448  * must be completed before the first request by the system to normal memory.
449  ******************************************************************************/
ccn_program_sys_addrmap(unsigned int sn0_id,unsigned int sn1_id,unsigned int sn2_id,unsigned int top_addr_bit0,unsigned int top_addr_bit1,unsigned char three_sn_en)450 void ccn_program_sys_addrmap(unsigned int sn0_id,
451 		 unsigned int sn1_id,
452 		 unsigned int sn2_id,
453 		 unsigned int top_addr_bit0,
454 		 unsigned int top_addr_bit1,
455 		 unsigned char three_sn_en)
456 {
457 	unsigned long long mn_hnf_id_map, hnf_sam_ctrl_value;
458 	unsigned int region_id;
459 
460 	assert(ccn_plat_desc);
461 	assert(ccn_plat_desc->periphbase);
462 
463 	mn_hnf_id_map = ccn_reg_read(ccn_plat_desc->periphbase,
464 				     MN_REGION_ID,
465 				     MN_HNF_NODEID_OFFSET);
466 	region_id = HNF_REGION_ID_START;
467 	hnf_sam_ctrl_value = MAKE_HNF_SAM_CTRL_VALUE(sn0_id,
468 						     sn1_id,
469 						     sn2_id,
470 						     top_addr_bit0,
471 						     top_addr_bit1,
472 						     three_sn_en);
473 
474 	FOR_EACH_PRESENT_REGION_ID(region_id, mn_hnf_id_map) {
475 
476 		/* Program the SAM control register */
477 		ccn_reg_write(ccn_plat_desc->periphbase,
478 			      region_id,
479 			      HNF_SAM_CTRL_OFFSET,
480 			      hnf_sam_ctrl_value);
481 	}
482 
483 }
484 
485 /*******************************************************************************
486  * This function returns the part0 id from the peripheralID 0 register
487  * in CCN. This id can be used to distinguish the CCN variant present in the
488  * system.
489  ******************************************************************************/
ccn_get_part0_id(uintptr_t periphbase)490 int ccn_get_part0_id(uintptr_t periphbase)
491 {
492 	assert(periphbase);
493 	return (int)(mmio_read_64(periphbase
494 			+ MN_PERIPH_ID_0_1_OFFSET) & 0xFF);
495 }
496 
497 /*******************************************************************************
498  * This function returns the region id corresponding to a node_id of node_type.
499  ******************************************************************************/
get_region_id_for_node(node_types_t node_type,unsigned int node_id)500 static unsigned int get_region_id_for_node(node_types_t node_type,
501 						unsigned int node_id)
502 {
503 	unsigned int mn_reg_off, region_id;
504 	unsigned long long node_bitmap;
505 	unsigned int loc_node_id, node_pos_in_map = 0;
506 
507 	assert(node_type < NUM_NODE_TYPES);
508 	assert(node_id < MAX_RN_NODES);
509 
510 	switch (node_type) {
511 	case NODE_TYPE_RNI:
512 		region_id = RNI_REGION_ID_START;
513 		break;
514 	case NODE_TYPE_HNF:
515 		region_id = HNF_REGION_ID_START;
516 		break;
517 	case NODE_TYPE_HNI:
518 		region_id = HNI_REGION_ID_START;
519 		break;
520 	case NODE_TYPE_SN:
521 		region_id = SBSX_REGION_ID_START;
522 		break;
523 	default:
524 		ERROR("Un-supported Node Type = %d.\n", node_type);
525 		assert(false);
526 		return REGION_ID_LIMIT;
527 	}
528 	/*
529 	 * RN-I, HN-F, HN-I, SN node registers in the MN region
530 	 * occupy contiguous 16 byte apart offsets.
531 	 *
532 	 * RN-F and RN-D node are not supported as
533 	 * none of them exposes any memory map to
534 	 * configure any of their offset registers.
535 	 */
536 
537 	mn_reg_off = MN_RNF_NODEID_OFFSET + (node_type << 4);
538 	node_bitmap = ccn_reg_read(ccn_plat_desc->periphbase,
539 					MN_REGION_ID, mn_reg_off);
540 
541 	assert((node_bitmap & (1ULL << (node_id))) != 0U);
542 
543 
544 	FOR_EACH_PRESENT_NODE_ID(loc_node_id, node_bitmap) {
545 		INFO("Index = %u with loc_nod=%u and input nod=%u\n",
546 					node_pos_in_map, loc_node_id, node_id);
547 		if (loc_node_id == node_id)
548 			break;
549 		node_pos_in_map++;
550 	}
551 
552 	if (node_pos_in_map == CCN_MAX_RN_MASTERS) {
553 		ERROR("Node Id = %d, is not found.\n", node_id);
554 		assert(false);
555 		return REGION_ID_LIMIT;
556 	}
557 
558 	/*
559 	 * According to section 3.1.1 in CCN specification, region offset for
560 	 * the RN-I components is calculated as (128 + NodeID of RN-I).
561 	 */
562 	if (node_type == NODE_TYPE_RNI)
563 		region_id += node_id;
564 	else
565 		region_id += node_pos_in_map;
566 
567 	return region_id;
568 }
569 
570 /*******************************************************************************
571  * This function sets the value 'val' to the register at register_offset from
572  * the base address pointed to by the region_id.
573  * where, region id is mapped to a node_id of node_type.
574  ******************************************************************************/
ccn_write_node_reg(node_types_t node_type,unsigned int node_id,unsigned int reg_offset,unsigned long long val)575 void ccn_write_node_reg(node_types_t node_type, unsigned int node_id,
576 			unsigned int reg_offset, unsigned long long val)
577 {
578 	unsigned int region_id = get_region_id_for_node(node_type, node_id);
579 
580 	if (reg_offset > REGION_ID_OFFSET) {
581 		ERROR("Invalid Register offset 0x%x is provided.\n",
582 								reg_offset);
583 		assert(false);
584 		return;
585 	}
586 
587 	/* Setting the value of Auxiliary Control Register of the Node */
588 	ccn_reg_write(ccn_plat_desc->periphbase, region_id, reg_offset, val);
589 	VERBOSE("Value is successfully written at address 0x%lx.\n",
590 			(ccn_plat_desc->periphbase
591 			+ region_id_to_base(region_id))
592 			+ reg_offset);
593 }
594 
595 /*******************************************************************************
596  * This function read the value 'val' stored in the register at register_offset
597  * from the base address pointed to by the region_id.
598  * where, region id is mapped to a node_id of node_type.
599  ******************************************************************************/
ccn_read_node_reg(node_types_t node_type,unsigned int node_id,unsigned int reg_offset)600 unsigned long long ccn_read_node_reg(node_types_t node_type,
601 					unsigned int node_id,
602 					unsigned int reg_offset)
603 {
604 	unsigned long long val;
605 	unsigned int region_id = get_region_id_for_node(node_type, node_id);
606 
607 	if (reg_offset > REGION_ID_OFFSET) {
608 		ERROR("Invalid Register offset 0x%x is provided.\n",
609 								reg_offset);
610 		assert(false);
611 		return ULL(0);
612 	}
613 
614 	/* Setting the value of Auxiliary Control Register of the Node */
615 	val = ccn_reg_read(ccn_plat_desc->periphbase, region_id, reg_offset);
616 	VERBOSE("Value is successfully read from address 0x%lx.\n",
617 			(ccn_plat_desc->periphbase
618 			+ region_id_to_base(region_id))
619 			+ reg_offset);
620 
621 	return val;
622 }
623