Achin Gupta | a80720f | 2015-07-20 22:28:23 +0100 | [diff] [blame] | 1 | /* |
Soby Mathew | a0fedc4 | 2016-06-16 14:52:04 +0100 | [diff] [blame] | 2 | * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. |
Achin Gupta | a80720f | 2015-07-20 22:28:23 +0100 | [diff] [blame] | 3 | * |
dp-arm | fa3cf0b | 2017-05-03 09:38:09 +0100 | [diff] [blame] | 4 | * SPDX-License-Identifier: BSD-3-Clause |
Achin Gupta | a80720f | 2015-07-20 22:28:23 +0100 | [diff] [blame] | 5 | */ |
| 6 | |
Antonio Nino Diaz | 5eb8837 | 2018-11-08 10:20:19 +0000 | [diff] [blame] | 7 | #ifndef CCN_PRIVATE_H |
| 8 | #define CCN_PRIVATE_H |
Achin Gupta | a80720f | 2015-07-20 22:28:23 +0100 | [diff] [blame] | 9 | |
| 10 | /* |
| 11 | * A CCN implementation can have a maximum of 64 Request nodes with node IDs |
| 12 | * from 0-63. These IDs are split across the three types of Request nodes |
| 13 | * i.e. RN-F, RN-D and RN-I. |
| 14 | */ |
| 15 | #define MAX_RN_NODES 64 |
| 16 | |
| 17 | /* Enum used to loop through the 3 types of Request nodes */ |
| 18 | typedef enum rn_types { |
| 19 | RN_TYPE_RNF = 0, |
| 20 | RN_TYPE_RNI, |
| 21 | RN_TYPE_RND, |
| 22 | NUM_RN_TYPES |
| 23 | } rn_types_t; |
| 24 | |
| 25 | /* Macro to convert a region id to its base address */ |
| 26 | #define region_id_to_base(id) ((id) << 16) |
| 27 | |
| 28 | /* |
| 29 | * Macro to calculate the number of master interfaces resident on a RN-I/RN-D. |
| 30 | * Value of first two bits of the RN-I/D node type + 1 == Maximum number of |
| 31 | * ACE-Lite or ACE-Lite+DVM interfaces supported on this node. E.g. |
| 32 | * |
| 33 | * 0x14 : RN-I with 1 ACE-Lite interface |
| 34 | * 0x15 : RN-I with 2 ACE-Lite interfaces |
| 35 | * 0x16 : RN-I with 3 ACE-Lite interfaces |
| 36 | */ |
| 37 | #define rn_type_id_to_master_cnt(id) (((id) & 0x3) + 1) |
| 38 | |
| 39 | /* |
| 40 | * Constants used to identify a region in the programmer's view. These are |
| 41 | * common for all regions. |
| 42 | */ |
| 43 | #define REGION_ID_LIMIT 256 |
| 44 | #define REGION_ID_OFFSET 0xFF00 |
| 45 | |
| 46 | #define REGION_NODE_ID_SHIFT 8 |
| 47 | #define REGION_NODE_ID_MASK 0x7f |
| 48 | #define get_node_id(id_reg) (((id_reg) >> REGION_NODE_ID_SHIFT) \ |
| 49 | & REGION_NODE_ID_MASK) |
| 50 | |
| 51 | #define REGION_NODE_TYPE_SHIFT 0 |
| 52 | #define REGION_NODE_TYPE_MASK 0x1f |
| 53 | #define get_node_type(id_reg) (((id_reg) >> REGION_NODE_TYPE_SHIFT) \ |
| 54 | & REGION_NODE_TYPE_MASK) |
| 55 | |
| 56 | /* Common offsets of registers to enter or exit a snoop/dvm domain */ |
| 57 | #define DOMAIN_CTRL_STAT_OFFSET 0x0200 |
| 58 | #define DOMAIN_CTRL_SET_OFFSET 0x0210 |
| 59 | #define DOMAIN_CTRL_CLR_OFFSET 0x0220 |
| 60 | |
| 61 | /* |
| 62 | * Thess macros are used to determine if an operation to add or remove a Request |
| 63 | * node from the snoop/dvm domain has completed. 'rn_id_map' is a bit map of |
| 64 | * nodes. It was used to program the SET or CLEAR control register. The type of |
| 65 | * register is specified by 'op_reg_offset'. 'status_reg' is the bit map of |
| 66 | * nodes currently present in the snoop/dvm domain. 'rn_id_map' and 'status_reg' |
| 67 | * are logically ANDed and the result it stored back in the 'status_reg'. There |
| 68 | * are two outcomes of this operation: |
| 69 | * |
| 70 | * 1. If the DOMAIN_CTRL_SET_OFFSET register was programmed, then the set bits in |
| 71 | * 'rn_id_map' should appear in 'status_reg' when the operation completes. So |
| 72 | * after the AND operation, at some point of time 'status_reg' should equal |
| 73 | * 'rn_id_map'. |
| 74 | * |
| 75 | * 2. If the DOMAIN_CTRL_CLR_OFFSET register was programmed, then the set bits in |
| 76 | * 'rn_id_map' should disappear in 'status_reg' when the operation |
| 77 | * completes. So after the AND operation, at some point of time 'status_reg' |
| 78 | * should equal 0. |
| 79 | */ |
| 80 | #define WAIT_FOR_DOMAIN_CTRL_OP_COMPLETION(region_id, stat_reg_offset, \ |
| 81 | op_reg_offset, rn_id_map) \ |
| 82 | { \ |
Soby Mathew | a0fedc4 | 2016-06-16 14:52:04 +0100 | [diff] [blame] | 83 | unsigned long long status_reg; \ |
Achin Gupta | a80720f | 2015-07-20 22:28:23 +0100 | [diff] [blame] | 84 | do { \ |
| 85 | status_reg = ccn_reg_read((ccn_plat_desc->periphbase), \ |
| 86 | (region_id), \ |
| 87 | (stat_reg_offset)); \ |
| 88 | status_reg &= (rn_id_map); \ |
| 89 | } while ((op_reg_offset) == DOMAIN_CTRL_SET_OFFSET ? \ |
| 90 | (rn_id_map) != status_reg : status_reg); \ |
| 91 | } |
| 92 | |
| 93 | /* |
| 94 | * Region ID of the Miscellaneous Node is always 0 as its located at the base of |
| 95 | * the programmer's view. |
| 96 | */ |
| 97 | #define MN_REGION_ID 0 |
| 98 | |
| 99 | #define MN_REGION_ID_START 0 |
| 100 | #define DEBUG_REGION_ID_START 1 |
| 101 | #define HNI_REGION_ID_START 8 |
| 102 | #define SBSX_REGION_ID_START 16 |
| 103 | #define HNF_REGION_ID_START 32 |
| 104 | #define XP_REGION_ID_START 64 |
| 105 | #define RNI_REGION_ID_START 128 |
| 106 | |
| 107 | /* Selected register offsets from the base of a HNF region */ |
| 108 | #define HNF_CFG_CTRL_OFFSET 0x0000 |
| 109 | #define HNF_SAM_CTRL_OFFSET 0x0008 |
| 110 | #define HNF_PSTATE_REQ_OFFSET 0x0010 |
| 111 | #define HNF_PSTATE_STAT_OFFSET 0x0018 |
| 112 | #define HNF_SDC_STAT_OFFSET DOMAIN_CTRL_STAT_OFFSET |
| 113 | #define HNF_SDC_SET_OFFSET DOMAIN_CTRL_SET_OFFSET |
| 114 | #define HNF_SDC_CLR_OFFSET DOMAIN_CTRL_CLR_OFFSET |
| 115 | #define HNF_AUX_CTRL_OFFSET 0x0500 |
| 116 | |
| 117 | /* Selected register offsets from the base of a MN region */ |
| 118 | #define MN_SAR_OFFSET 0x0000 |
| 119 | #define MN_RNF_NODEID_OFFSET 0x0180 |
| 120 | #define MN_RNI_NODEID_OFFSET 0x0190 |
| 121 | #define MN_RND_NODEID_OFFSET 0x01A0 |
| 122 | #define MN_HNF_NODEID_OFFSET 0x01B0 |
| 123 | #define MN_HNI_NODEID_OFFSET 0x01C0 |
| 124 | #define MN_SN_NODEID_OFFSET 0x01D0 |
| 125 | #define MN_DDC_STAT_OFFSET DOMAIN_CTRL_STAT_OFFSET |
Vikram Kanigiri | 4aceeb0 | 2016-01-04 16:23:22 +0000 | [diff] [blame] | 126 | #define MN_DDC_SET_OFFSET DOMAIN_CTRL_SET_OFFSET |
Achin Gupta | a80720f | 2015-07-20 22:28:23 +0100 | [diff] [blame] | 127 | #define MN_DDC_CLR_OFFSET DOMAIN_CTRL_CLR_OFFSET |
Soby Mathew | 095b9bc | 2016-03-23 17:14:57 +0000 | [diff] [blame] | 128 | #define MN_PERIPH_ID_0_1_OFFSET 0xFE0 |
Achin Gupta | a80720f | 2015-07-20 22:28:23 +0100 | [diff] [blame] | 129 | #define MN_ID_OFFSET REGION_ID_OFFSET |
| 130 | |
| 131 | /* HNF System Address Map register bit masks and shifts */ |
| 132 | #define HNF_SAM_CTRL_SN_ID_MASK 0x7f |
| 133 | #define HNF_SAM_CTRL_SN0_ID_SHIFT 0 |
| 134 | #define HNF_SAM_CTRL_SN1_ID_SHIFT 8 |
| 135 | #define HNF_SAM_CTRL_SN2_ID_SHIFT 16 |
| 136 | |
Antonio Nino Diaz | f94e40d | 2017-09-14 15:57:44 +0100 | [diff] [blame] | 137 | #define HNF_SAM_CTRL_TAB0_MASK ULL(0x3f) |
Achin Gupta | a80720f | 2015-07-20 22:28:23 +0100 | [diff] [blame] | 138 | #define HNF_SAM_CTRL_TAB0_SHIFT 48 |
Antonio Nino Diaz | f94e40d | 2017-09-14 15:57:44 +0100 | [diff] [blame] | 139 | #define HNF_SAM_CTRL_TAB1_MASK ULL(0x3f) |
Achin Gupta | a80720f | 2015-07-20 22:28:23 +0100 | [diff] [blame] | 140 | #define HNF_SAM_CTRL_TAB1_SHIFT 56 |
| 141 | |
| 142 | #define HNF_SAM_CTRL_3SN_ENB_SHIFT 32 |
Antonio Nino Diaz | f94e40d | 2017-09-14 15:57:44 +0100 | [diff] [blame] | 143 | #define HNF_SAM_CTRL_3SN_ENB_MASK ULL(0x01) |
Achin Gupta | a80720f | 2015-07-20 22:28:23 +0100 | [diff] [blame] | 144 | |
| 145 | /* |
| 146 | * Macro to create a value suitable for programming into a HNF SAM Control |
| 147 | * register for enabling 3SN striping. |
| 148 | */ |
| 149 | #define MAKE_HNF_SAM_CTRL_VALUE(sn0, sn1, sn2, tab0, tab1, three_sn_en) \ |
| 150 | ((((sn0) & HNF_SAM_CTRL_SN_ID_MASK) << HNF_SAM_CTRL_SN0_ID_SHIFT) | \ |
| 151 | (((sn1) & HNF_SAM_CTRL_SN_ID_MASK) << HNF_SAM_CTRL_SN1_ID_SHIFT) | \ |
| 152 | (((sn2) & HNF_SAM_CTRL_SN_ID_MASK) << HNF_SAM_CTRL_SN2_ID_SHIFT) | \ |
| 153 | (((tab0) & HNF_SAM_CTRL_TAB0_MASK) << HNF_SAM_CTRL_TAB0_SHIFT) | \ |
| 154 | (((tab1) & HNF_SAM_CTRL_TAB1_MASK) << HNF_SAM_CTRL_TAB1_SHIFT) | \ |
| 155 | (((three_sn_en) & HNF_SAM_CTRL_3SN_ENB_MASK) << HNF_SAM_CTRL_3SN_ENB_SHIFT)) |
| 156 | |
| 157 | /* Mask to read the power state value from an HN-F P-state register */ |
| 158 | #define HNF_PSTATE_MASK 0xf |
| 159 | |
| 160 | /* Macro to extract the run mode from a p-state value */ |
| 161 | #define PSTATE_TO_RUN_MODE(pstate) (((pstate) & HNF_PSTATE_MASK) >> 2) |
| 162 | |
| 163 | /* |
| 164 | * Helper macro that iterates through a given bit map. In each iteration, |
| 165 | * it returns the position of the set bit. |
| 166 | * It can be used by other utility macros to iterates through all nodes |
| 167 | * or masters given a bit map of them. |
| 168 | */ |
| 169 | #define FOR_EACH_BIT(bit_pos, bit_map) \ |
| 170 | for (bit_pos = __builtin_ctzll(bit_map); \ |
| 171 | bit_map; \ |
Antonio Nino Diaz | f94e40d | 2017-09-14 15:57:44 +0100 | [diff] [blame] | 172 | bit_map &= ~(1ULL << (bit_pos)), \ |
Achin Gupta | a80720f | 2015-07-20 22:28:23 +0100 | [diff] [blame] | 173 | bit_pos = __builtin_ctzll(bit_map)) |
| 174 | |
| 175 | /* |
| 176 | * Utility macro that iterates through a bit map of node IDs. In each |
| 177 | * iteration, it returns the ID of the next present node in the bit map. Node |
| 178 | * ID of a present node == Position of set bit == Number of zeroes trailing the |
| 179 | * bit. |
| 180 | */ |
| 181 | #define FOR_EACH_PRESENT_NODE_ID(node_id, bit_map) \ |
| 182 | FOR_EACH_BIT(node_id, bit_map) |
| 183 | |
| 184 | /* |
| 185 | * Helper function to return number of set bits in bitmap |
| 186 | */ |
Soby Mathew | a0fedc4 | 2016-06-16 14:52:04 +0100 | [diff] [blame] | 187 | static inline unsigned int count_set_bits(unsigned long long bitmap) |
Achin Gupta | a80720f | 2015-07-20 22:28:23 +0100 | [diff] [blame] | 188 | { |
| 189 | unsigned int count = 0; |
| 190 | |
| 191 | for (; bitmap; bitmap &= bitmap - 1) |
| 192 | ++count; |
| 193 | |
| 194 | return count; |
| 195 | } |
| 196 | |
| 197 | /* |
| 198 | * Utility macro that iterates through a bit map of node IDs. In each iteration, |
| 199 | * it returns the ID of the next present region corresponding to a node present |
| 200 | * in the bit map. Region ID of a present node is in between passed region id |
| 201 | * and region id + number of set bits in the bitmap i.e. the number of present |
| 202 | * nodes. |
| 203 | */ |
| 204 | #define FOR_EACH_PRESENT_REGION_ID(region_id, bit_map) \ |
| 205 | for (unsigned long long region_id_limit = count_set_bits(bit_map) \ |
| 206 | + region_id; \ |
| 207 | region_id < region_id_limit; \ |
| 208 | region_id++) |
| 209 | |
| 210 | /* |
| 211 | * Same macro as FOR_EACH_PRESENT_NODE, but renamed to indicate it traverses |
| 212 | * through a bit map of master interfaces. |
| 213 | */ |
| 214 | #define FOR_EACH_PRESENT_MASTER_INTERFACE(iface_id, bit_map) \ |
| 215 | FOR_EACH_BIT(iface_id, bit_map) |
Vikram Kanigiri | 4aceeb0 | 2016-01-04 16:23:22 +0000 | [diff] [blame] | 216 | |
| 217 | /* |
| 218 | * Macro that returns the node id bit map for the Miscellaneous Node |
| 219 | */ |
| 220 | #define CCN_GET_MN_NODEID_MAP(periphbase) \ |
| 221 | (1 << get_node_id(ccn_reg_read(periphbase, MN_REGION_ID, \ |
| 222 | REGION_ID_OFFSET))) |
| 223 | |
| 224 | /* |
| 225 | * This macro returns the bitmap of Home nodes on the basis of the |
| 226 | * 'mn_hn_id_reg_offset' parameter from the Miscellaneous node's (MN) |
| 227 | * programmer's view. The MN has a register which carries the bitmap of present |
| 228 | * Home nodes of each type i.e. HN-Fs, HN-Is & HN-Ds. |
| 229 | */ |
| 230 | #define CCN_GET_HN_NODEID_MAP(periphbase, mn_hn_id_reg_offset) \ |
| 231 | ccn_reg_read(periphbase, MN_REGION_ID, mn_hn_id_reg_offset) |
| 232 | |
Antonio Nino Diaz | 5eb8837 | 2018-11-08 10:20:19 +0000 | [diff] [blame] | 233 | #endif /* CCN_PRIVATE_H */ |