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