1 /* 2 * Arm SCP/MCP Software 3 * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved. 4 * 5 * SPDX-License-Identifier: BSD-3-Clause 6 * 7 * Description: 8 * Definitions and utility functions for the CMN BOOKER module. 9 */ 10 11 /* The use of "manager" may not be in sync with older versions of TRM */ 12 13 #ifndef CMN_BOOKER_H 14 #define CMN_BOOKER_H 15 16 #include <fwk_macros.h> 17 18 #include <stdbool.h> 19 #include <stdint.h> 20 21 /* Max Node Counts */ 22 #define MAX_HNF_COUNT 64 23 #define MAX_RND_COUNT 32 24 #define MAX_RNI_COUNT 32 25 #define MAX_RNF_COUNT 64 26 27 #define MAX_PORTS_COUNT 6 28 29 /* Maximum System Cache Group regions supported by CMN-BOOKER */ 30 #define MAX_SCG_COUNT 4 31 32 /* SAM Granularity of RN-SAM and HN-F SAM */ 33 #define SAM_GRANULARITY (64 * FWK_MIB) 34 35 /* Macros to split 64 bit value two 32 bit values */ 36 #define HIGH_WORD(x) ((unsigned int)((((x) & 0xFFFFFFFF00000000ULL) >> 32))) 37 #define LOW_WORD(x) ((unsigned int)((x) & 0xFFFFFFFF)) 38 39 /* External nodes that require RN-SAM mapping during run-time */ 40 struct external_rnsam_tuple { 41 unsigned int node_id; 42 struct cmn_booker_rnsam_reg *node; 43 }; 44 45 enum node_type { 46 NODE_TYPE_INVALID = 0x0, 47 NODE_TYPE_DVM = 0x1, 48 NODE_TYPE_CFG = 0x2, 49 NODE_TYPE_DTC = 0x3, 50 NODE_TYPE_HN_I = 0x4, 51 NODE_TYPE_HN_F = 0x5, 52 NODE_TYPE_XP = 0x6, 53 NODE_TYPE_SBSX = 0x7, 54 NODE_TYPE_MPAM_S = 0x8, 55 NODE_TYPE_MPAM_NS = 0x9, 56 NODE_TYPE_RN_I = 0xA, 57 NODE_TYPE_RN_D = 0xD, 58 NODE_TYPE_RN_SAM = 0xF, 59 NODE_TYPE_MTU = 0x10, 60 /* Coherent Multichip Link (CML) node types */ 61 NODE_TYPE_CML_BASE = 0x100, 62 NODE_TYPE_CXRA = 0x100, 63 NODE_TYPE_CXHA = 0x101, 64 NODE_TYPE_CXLA = 0x102, 65 }; 66 67 enum device_type { 68 DEVICE_TYPE_CXHA = 0x11, // 0b10001 69 DEVICE_TYPE_CXRA = 0x12, // 0b10010 70 DEVICE_TYPE_CXRH = 0x13, // 0b10011 71 }; 72 73 /* Common node header */ 74 struct node_header { 75 FWK_R uint64_t NODE_INFO; 76 uint8_t RESERVED0[0x80 - 0x8]; 77 FWK_R uint64_t CHILD_INFO; 78 uint8_t RESERVED1[0x100 - 0x88]; 79 FWK_R uint64_t CHILD_POINTER[256]; 80 }; 81 82 enum sam_node_type { 83 SAM_NODE_TYPE_HN_F = 0, 84 SAM_NODE_TYPE_HN_I = 1, 85 SAM_NODE_TYPE_CXRA = 2, 86 SAM_NODE_TYPE_COUNT 87 }; 88 89 /* 90 * Request Node System Address Map (RN-SAM) registers 91 */ 92 struct cmn_booker_rnsam_reg { 93 FWK_R uint64_t NODE_INFO; 94 uint8_t RESERVED0[0x80 - 0x8]; 95 FWK_R uint64_t CHILD_INFO; 96 uint8_t RESERVED1[0x900 - 0x88]; 97 FWK_R uint64_t UNIT_INFO; 98 uint8_t RESERVED2[0xC00 - 0x908]; 99 FWK_RW uint64_t NON_HASH_MEM_REGION[20]; 100 uint8_t RESERVED3[0xD80 - 0xCA0]; 101 FWK_RW uint64_t NON_HASH_TGT_NODEID[5]; 102 uint8_t RESERVED4[0xE00 - 0xDA8]; 103 FWK_RW uint64_t SYS_CACHE_GRP_REGION[4]; 104 uint8_t RESERVED5[0xEA0 - 0xE20]; 105 FWK_RW uint64_t SYS_CACHE_GRP_HN_COUNT; 106 uint8_t RESERVED6[0xF00 - 0xEA8]; 107 FWK_RW uint64_t SYS_CACHE_GRP_HN_NODEID[16]; 108 uint8_t RESERVED7[0x1000 - 0xF80]; 109 FWK_RW uint64_t SYS_CACHE_GRP_SN_NODEID[16]; 110 uint8_t RESERVED8[0x1100 - 0x1080]; 111 FWK_RW uint64_t STATUS; 112 uint8_t RESERVED9[0x1120 - 0x1108]; 113 FWK_RW uint64_t SYS_CACHE_GRP_CAL_MODE; 114 }; 115 116 /* 117 * Fully Coherent Home Node (HN-F) registers 118 */ 119 struct cmn_booker_hnf_reg { 120 FWK_R uint64_t NODE_INFO; 121 uint8_t RESERVED0[0x80 - 0x8]; 122 FWK_R uint64_t CHILD_INFO; 123 uint8_t RESERVED1[0x900 - 0x88]; 124 FWK_R uint64_t UNIT_INFO; 125 uint8_t RESERVED2[0xD00 - 0x908]; 126 FWK_RW uint64_t SAM_CONTROL; 127 FWK_RW uint64_t SAM_MEMREGION[2]; 128 uint8_t RESERVED8[0x1C00 - 0xD18]; 129 FWK_RW uint64_t PPU_PWPR; 130 }; 131 132 /* 133 * Configuration manager registers 134 */ 135 struct cmn_booker_cfgm_reg { 136 FWK_R uint64_t NODE_INFO; 137 FWK_RW uint64_t PERIPH_ID[4]; 138 FWK_RW uint64_t COMPONENT_ID[2]; 139 uint8_t RESERVED0[0x80 - 0x38]; 140 FWK_R uint64_t CHILD_INFO; 141 }; 142 143 /* 144 * Crosspoint (XP) registers 145 */ 146 struct cmn_booker_mxp_reg { 147 FWK_R uint64_t NODE_INFO; 148 FWK_R uint64_t PORT_CONNECT_INFO[2]; 149 uint8_t RESERVED0[0x80 - 0x18]; 150 FWK_R uint64_t CHILD_INFO; 151 uint8_t RESERVED1[0x100 - 0x88]; 152 FWK_R uint64_t CHILD_POINTER[16]; 153 }; 154 155 /* 156 * Home Node I/O (HN-I) registers 157 */ 158 struct cmn_booker_hni_reg { 159 FWK_R uint64_t NODE_INFO; 160 uint8_t RESERVED0[0x80 - 0x8]; 161 FWK_R uint64_t CHILD_INFO; 162 uint8_t RESERVED1[0x900 - 0x88]; 163 FWK_R uint64_t UNIT_INFO; 164 uint8_t RESERVED2[0x980 - 0x908]; 165 FWK_RW uint64_t SECURE_REGISTER_GROUPS_OVERRIDE; 166 uint8_t RESERVED3[0xA00 - 0x988]; 167 FWK_RW uint64_t CFG_CTL; 168 FWK_RW uint64_t AUX_CTL; 169 uint8_t RESERVED4[0xC00 - 0xA10]; 170 FWK_RW uint64_t SAM_ADDRREGION_CFG[4]; 171 uint8_t RESERVED5[0x2000 - 0xC20]; 172 FWK_RW uint64_t PMU_EVENT_SEL; 173 uint8_t RESERVED6[0x3000 - 0x2008]; 174 FWK_R uint64_t ERRFR; 175 FWK_RW uint64_t ERRCTL; 176 FWK_RW uint64_t ERRSTATUS; 177 FWK_RW uint64_t ERRADDR; 178 FWK_RW uint64_t ERRMISC; 179 uint8_t RESERVED7[0x3100 - 0x3028]; 180 FWK_R uint64_t ERRFR_NS; 181 FWK_RW uint64_t ERRCTL_NS; 182 FWK_RW uint64_t ERRSTATUS_NS; 183 FWK_RW uint64_t ERRADDR_NS; 184 FWK_RW uint64_t ERRMISC_NS; 185 }; 186 187 #define CMN_BOOKER_NODE_INFO_TYPE UINT64_C(0x000000000000FFFF) 188 #define CMN_BOOKER_NODE_INFO_ID UINT64_C(0x00000000FFFF0000) 189 #define CMN_BOOKER_NODE_INFO_ID_POS 16 190 #define CMN_BOOKER_NODE_INFO_LOGICAL_ID UINT64_C(0x0000FFFF00000000) 191 #define CMN_BOOKER_NODE_INFO_LOGICAL_ID_POS 32 192 193 #define CMN_BOOKER_CHILD_INFO_COUNT UINT64_C(0x000000000000FFFF) 194 195 #define CMN_BOOKER_CHILD_POINTER_OFFSET UINT64_C(0x000000000FFFFFFF) 196 #define CMN_BOOKER_CHILD_POINTER_EXT UINT64_C(0x0000000080000000) 197 198 /* External child node */ 199 #define CMN_BOOKER_CHILD_POINTER_EXT_REGISTER_OFFSET UINT64_C(0x00003FFF) 200 #define CMN_BOOKER_CHILD_POINTER_EXT_NODE_POINTER UINT64_C(0x0FFFC000) 201 #define CMN_BOOKER_CHILD_POINTER_EXT_NODE_POINTER_POS 14 202 203 /* Used by NON_HASH_MEM_REGIONx and SYS_CACHE_GRP_REGIONx group registers */ 204 #define CMN_BOOKER_RNSAM_REGION_ENTRY_TYPE_POS 2 205 #define CMN_BOOKER_RNSAM_REGION_ENTRY_SIZE_POS 56 206 #define CMN_BOOKER_RNSAM_REGION_ENTRY_BASE_POS 26 207 #define CMN_BOOKER_RNSAM_REGION_ENTRY_BITS_WIDTH 64 208 #define CMN_BOOKER_RNSAM_REGION_ENTRY_VALID UINT64_C(0x0000000000000001) 209 #define CMN_BOOKER_RNSAM_REGION_ENTRIES_PER_GROUP 1 210 #define CMN_BOOKER_RNSAM_SYS_CACHE_GRP_SN_NODEID_ENTRIES_PER_GROUP 4 211 #define CMN_BOOKER_RNSAM_SCG_HNF_CAL_MODE_EN UINT64_C(0x01) 212 #define CMN_BOOKER_RNSAM_SCG_HNF_CAL_MODE_SHIFT 16 213 214 #define CMN_BOOKER_RNSAM_STATUS_UNSTALL UINT64_C(0x0000000000000002) 215 #define CMN_BOOKER_RNSAM_STATUS_DEFAULT_NODEID_POS 48 216 217 #define CMN_BOOKER_RNSAM_NON_HASH_TGT_NODEID_ENTRY_BITS_WIDTH 12 218 #define CMN_BOOKER_RNSAM_NON_HASH_TGT_NODEID_ENTRY_MASK UINT64_C(0xFFF) 219 #define CMN_BOOKER_RNSAM_NON_HASH_TGT_NODEID_ENTRIES_PER_GROUP 4 220 221 #define CMN_BOOKER_HNF_SAM_MEMREGION_SIZE_POS 12 222 #define CMN_BOOKER_HNF_SAM_MEMREGION_BASE_POS 26 223 #define CMN_BOOKER_HNF_SAM_MEMREGION_VALID UINT64_C(0x8000000000000000) 224 225 #define CMN_BOOKER_HNF_CACHE_GROUP_ENTRIES_MAX 64 226 #define CMN_BOOKER_HNF_CACHE_GROUP_ENTRIES_PER_GROUP 4 227 #define CMN_BOOKER_HNF_CACHE_GROUP_ENTRY_BITS_WIDTH 12 228 229 #define CMN_BOOKER_PPU_PWPR_POLICY_OFF UINT64_C(0x0000000000000000) 230 #define CMN_BOOKER_PPU_PWPR_POLICY_MEM_RET UINT64_C(0x0000000000000002) 231 #define CMN_BOOKER_PPU_PWPR_POLICY_FUNC_RET UINT64_C(0x000000000000007) 232 #define CMN_BOOKER_PPU_PWPR_POLICY_ON UINT64_C(0x0000000000000008) 233 #define CMN_BOOKER_PPU_PWPR_OPMODE_NOSFSLC UINT64_C(0x0000000000000000) 234 #define CMN_BOOKER_PPU_PWPR_OPMODE_SFONLY UINT64_C(0x0000000000000010) 235 #define CMN_BOOKER_PPU_PWPR_OPMODE_HAM UINT64_C(0x0000000000000020) 236 #define CMN_BOOKER_PPU_PWPR_OPMODE_FAM UINT64_C(0x0000000000000030) 237 #define CMN_BOOKER_PPU_PWPR_DYN_EN UINT64_C(0x0000000000000100) 238 239 /* Mesh and Node ID mapping */ 240 #define CMN_BOOKER_MESH_X_MAX 8 241 #define CMN_BOOKER_MESH_Y_MAX 8 242 243 #define CMN_BOOKER_NODE_ID_PORT_POS 1 244 #define CMN_BOOKER_NODE_ID_PORT_MASK 0x3 245 #define CMN_BOOKER_NODE_ID_Y_POS 3 246 247 #define CMN_BOOKER_MXP_PORT_CONNECT_INFO_DEVICE_TYPE_MASK UINT64_C(0x1F) 248 249 #define CMN_BOOKER_ROOT_NODE_OFFSET_PORT_POS 16 250 #define CMN_BOOKER_ROOT_NODE_OFFSET_Y_POS 22 251 252 /* 253 * Retrieve the number of child nodes of a given node 254 * 255 * \param node_base Pointer to the node descriptor 256 * \pre The node pointer must be valid 257 * 258 * \return Number of child nodes 259 */ 260 unsigned int get_node_child_count(void *node_base); 261 262 /* 263 * Retrieve node type identifier 264 * 265 * \param node_base Pointer to the node descriptor 266 * \pre The node pointer must be valid 267 * 268 * \return Node's type identifier 269 */ 270 enum node_type get_node_type(void *node_base); 271 272 /* 273 * Retrieve the physical identifier of a node from its hardware node descriptor. 274 * This identifier encodes the node's position in the mesh. 275 * 276 * Note: Multiple node descriptors can share the same identifier if they are 277 * related to the same device node in the mesh. 278 * 279 * \param node_base Pointer to the node descriptor 280 * \pre The node pointer must be valid 281 * 282 * \return Node's physical identifier 283 */ 284 unsigned int get_node_id(void *node_base); 285 286 /* 287 * Retrieve the logical identifier of a node from its hardware node descriptor. 288 * This is an unique identifier (index) among nodes of the same type in the 289 * system. 290 * 291 * \param node_base Pointer to the node base address 292 * \pre The node pointer must be valid 293 * 294 * \return An integer representing the node's logical identifier 295 */ 296 unsigned int get_node_logical_id(void *node_base); 297 298 /* 299 * Retrieve a child node given a node and child index 300 * 301 * \param node_base Pointer to the node descriptor 302 * \pre The node pointer must be valid 303 * \param child_index Child index 304 * \pre The child index must be valid 305 * 306 * \return Pointer to the child's node descriptor 307 */ 308 void *get_child_node(uintptr_t base, void *node_base, unsigned int child_index); 309 310 /* 311 * Retrieve the physical identifier of a node using its child pointer in the 312 * parent's node hardware descriptor 313 * 314 * This function is used to extract a node's identifier without accessing the 315 * node descriptor. This is specially useful for external nodes that are in an 316 * unavailable power or clock domain. 317 * 318 * \param node_base Pointer to the parent node descriptor 319 * \pre The node pointer must be valid 320 * \param child_index Child index 321 * \pre The child index must be valid 322 * 323 * \return Physical child node identifier 324 */ 325 unsigned int get_child_node_id(void *node_base, unsigned int child_index); 326 327 /* 328 * Verify if a child node (given a parent node base and child index) is an 329 * external node from the CMN BOOKER instance point of view. 330 * 331 * \param node_base Pointer to the parent node descriptor 332 * \pre The node pointer must be valid 333 * \param child_index Child index 334 * \pre The child index must be valid 335 * 336 * \retval true if the node is external 337 * \retval false if the node is internal 338 */ 339 bool is_child_external(void *node_base, unsigned int child_index); 340 341 /* 342 * Returns the port number from the child node id. 343 * 344 * \param child_node_id Child node id calculated from the child pointer. 345 * 346 * \retval port number (either 0 or 1). 347 */ 348 bool get_port_number(unsigned int child_node_id); 349 350 /* 351 * Returns the device type from the MXP's port connect info register. 352 * 353 * \param mxp_base Pointer to the cross point node descriptor 354 * \pre The cross point node pointer must be valid 355 * \param port Port number 356 * \pre The port number should be either 0 or 1. 357 * 358 * \retval device type (por_mxp_por_mxp_device_port_connect_info_p[port] & 0x1F) 359 */ 360 unsigned int get_device_type(void *mxp_base, bool port); 361 362 /* 363 * Convert a memory region size into a size format used by the CMN BOOKER 364 * registers. The format is the binary logarithm of the memory region size 365 * represented as blocks multiple of the CMN BOOKER's granularity: 366 * n = log2(size / SAM_GRANULARITY) 367 * 368 * \param size Memory region size to be converted 369 * \pre size must be a multiple of SAM_GRANULARITY 370 * 371 * \return log2(size / SAM_GRANULARITY) 372 */ 373 uint64_t sam_encode_region_size(uint64_t size); 374 375 /* 376 * Configure a memory region 377 * 378 * \param reg Pointer to the region group descriptor to be configured 379 * \pre Must be a valid pointer 380 * \param region Region entry in the region group descriptor 381 * \param base Region base address 382 * \param size Region size 383 * \param node_type Type of the target node 384 * 385 * \return None 386 */ 387 void configure_region(volatile uint64_t *reg, uint64_t base, uint64_t size, 388 enum sam_node_type node_type); 389 390 /* 391 * Retrieve the node type name 392 * 393 * \param node_type Node type 394 * 395 * \return Pointer to the node type name string 396 */ 397 const char *get_node_type_name(enum node_type node_type); 398 399 /* 400 * Retrieve the node's position in the mesh along the X-axis 401 * 402 * \param node_base Pointer to the node descriptor 403 * 404 * \return Zero-indexed position along the X-axis 405 */ 406 unsigned int get_node_pos_x(void *node_base); 407 408 /* 409 * Retrieve the node's position in the mesh along the Y-axis 410 * 411 * \param node_base Pointer to the node descriptor 412 * 413 * \return Zero-indexed position along the Y-axis 414 */ 415 unsigned int get_node_pos_y(void *node_base); 416 417 /* 418 * Get the root node descriptor based on the peripheral base, HN-D node 419 * identifier and mesh size. 420 * 421 * \param base CMN BOOKER peripheral base address 422 * \param hnd_node_id HN-D node identifier containing the global configuration 423 * \param mesh_size_x Size of the mesh along the x-axis 424 * \param mesh_size_y Size of the mesh along the y-axis 425 * \param mesh_size_y Device ports per XP 426 * 427 * \return Pointer to the root node descriptor 428 */ 429 struct cmn_booker_cfgm_reg *get_root_node( 430 uintptr_t base, 431 unsigned int hnd_node_id, 432 unsigned int mesh_size_x, 433 unsigned int mesh_size_y, 434 unsigned int ports_per_xp); 435 436 #endif /* CMN_BOOKER_H */ 437