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