ccn.c 21 KB

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