Achin Gupta | a80720f | 2015-07-20 22:28:23 +0100 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. |
| 3 | * |
| 4 | * Redistribution and use in source and binary forms, with or without |
| 5 | * modification, are permitted provided that the following conditions are met: |
| 6 | * |
| 7 | * Redistributions of source code must retain the above copyright notice, this |
| 8 | * list of conditions and the following disclaimer. |
| 9 | * |
| 10 | * Redistributions in binary form must reproduce the above copyright notice, |
| 11 | * this list of conditions and the following disclaimer in the documentation |
| 12 | * and/or other materials provided with the distribution. |
| 13 | * |
| 14 | * Neither the name of ARM nor the names of its contributors may be used |
| 15 | * to endorse or promote products derived from this software without specific |
| 16 | * prior written permission. |
| 17 | * |
| 18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
| 19 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
| 20 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 21 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE |
| 22 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| 23 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| 24 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 25 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
| 26 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 27 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| 28 | * POSSIBILITY OF SUCH DAMAGE. |
| 29 | */ |
| 30 | |
| 31 | #ifndef __CCN_PRIVATE_H__ |
| 32 | #define __CCN_PRIVATE_H__ |
| 33 | |
| 34 | /* |
| 35 | * A CCN implementation can have a maximum of 64 Request nodes with node IDs |
| 36 | * from 0-63. These IDs are split across the three types of Request nodes |
| 37 | * i.e. RN-F, RN-D and RN-I. |
| 38 | */ |
| 39 | #define MAX_RN_NODES 64 |
| 40 | |
| 41 | /* Enum used to loop through the 3 types of Request nodes */ |
| 42 | typedef enum rn_types { |
| 43 | RN_TYPE_RNF = 0, |
| 44 | RN_TYPE_RNI, |
| 45 | RN_TYPE_RND, |
| 46 | NUM_RN_TYPES |
| 47 | } rn_types_t; |
| 48 | |
| 49 | /* Macro to convert a region id to its base address */ |
| 50 | #define region_id_to_base(id) ((id) << 16) |
| 51 | |
| 52 | /* |
| 53 | * Macro to calculate the number of master interfaces resident on a RN-I/RN-D. |
| 54 | * Value of first two bits of the RN-I/D node type + 1 == Maximum number of |
| 55 | * ACE-Lite or ACE-Lite+DVM interfaces supported on this node. E.g. |
| 56 | * |
| 57 | * 0x14 : RN-I with 1 ACE-Lite interface |
| 58 | * 0x15 : RN-I with 2 ACE-Lite interfaces |
| 59 | * 0x16 : RN-I with 3 ACE-Lite interfaces |
| 60 | */ |
| 61 | #define rn_type_id_to_master_cnt(id) (((id) & 0x3) + 1) |
| 62 | |
| 63 | /* |
| 64 | * Constants used to identify a region in the programmer's view. These are |
| 65 | * common for all regions. |
| 66 | */ |
| 67 | #define REGION_ID_LIMIT 256 |
| 68 | #define REGION_ID_OFFSET 0xFF00 |
| 69 | |
| 70 | #define REGION_NODE_ID_SHIFT 8 |
| 71 | #define REGION_NODE_ID_MASK 0x7f |
| 72 | #define get_node_id(id_reg) (((id_reg) >> REGION_NODE_ID_SHIFT) \ |
| 73 | & REGION_NODE_ID_MASK) |
| 74 | |
| 75 | #define REGION_NODE_TYPE_SHIFT 0 |
| 76 | #define REGION_NODE_TYPE_MASK 0x1f |
| 77 | #define get_node_type(id_reg) (((id_reg) >> REGION_NODE_TYPE_SHIFT) \ |
| 78 | & REGION_NODE_TYPE_MASK) |
| 79 | |
| 80 | /* Common offsets of registers to enter or exit a snoop/dvm domain */ |
| 81 | #define DOMAIN_CTRL_STAT_OFFSET 0x0200 |
| 82 | #define DOMAIN_CTRL_SET_OFFSET 0x0210 |
| 83 | #define DOMAIN_CTRL_CLR_OFFSET 0x0220 |
| 84 | |
| 85 | /* |
| 86 | * Thess macros are used to determine if an operation to add or remove a Request |
| 87 | * node from the snoop/dvm domain has completed. 'rn_id_map' is a bit map of |
| 88 | * nodes. It was used to program the SET or CLEAR control register. The type of |
| 89 | * register is specified by 'op_reg_offset'. 'status_reg' is the bit map of |
| 90 | * nodes currently present in the snoop/dvm domain. 'rn_id_map' and 'status_reg' |
| 91 | * are logically ANDed and the result it stored back in the 'status_reg'. There |
| 92 | * are two outcomes of this operation: |
| 93 | * |
| 94 | * 1. If the DOMAIN_CTRL_SET_OFFSET register was programmed, then the set bits in |
| 95 | * 'rn_id_map' should appear in 'status_reg' when the operation completes. So |
| 96 | * after the AND operation, at some point of time 'status_reg' should equal |
| 97 | * 'rn_id_map'. |
| 98 | * |
| 99 | * 2. If the DOMAIN_CTRL_CLR_OFFSET register was programmed, then the set bits in |
| 100 | * 'rn_id_map' should disappear in 'status_reg' when the operation |
| 101 | * completes. So after the AND operation, at some point of time 'status_reg' |
| 102 | * should equal 0. |
| 103 | */ |
| 104 | #define WAIT_FOR_DOMAIN_CTRL_OP_COMPLETION(region_id, stat_reg_offset, \ |
| 105 | op_reg_offset, rn_id_map) \ |
| 106 | { \ |
| 107 | uint64_t status_reg; \ |
| 108 | do { \ |
| 109 | status_reg = ccn_reg_read((ccn_plat_desc->periphbase), \ |
| 110 | (region_id), \ |
| 111 | (stat_reg_offset)); \ |
| 112 | status_reg &= (rn_id_map); \ |
| 113 | } while ((op_reg_offset) == DOMAIN_CTRL_SET_OFFSET ? \ |
| 114 | (rn_id_map) != status_reg : status_reg); \ |
| 115 | } |
| 116 | |
| 117 | /* |
| 118 | * Region ID of the Miscellaneous Node is always 0 as its located at the base of |
| 119 | * the programmer's view. |
| 120 | */ |
| 121 | #define MN_REGION_ID 0 |
| 122 | |
| 123 | #define MN_REGION_ID_START 0 |
| 124 | #define DEBUG_REGION_ID_START 1 |
| 125 | #define HNI_REGION_ID_START 8 |
| 126 | #define SBSX_REGION_ID_START 16 |
| 127 | #define HNF_REGION_ID_START 32 |
| 128 | #define XP_REGION_ID_START 64 |
| 129 | #define RNI_REGION_ID_START 128 |
| 130 | |
| 131 | /* Selected register offsets from the base of a HNF region */ |
| 132 | #define HNF_CFG_CTRL_OFFSET 0x0000 |
| 133 | #define HNF_SAM_CTRL_OFFSET 0x0008 |
| 134 | #define HNF_PSTATE_REQ_OFFSET 0x0010 |
| 135 | #define HNF_PSTATE_STAT_OFFSET 0x0018 |
| 136 | #define HNF_SDC_STAT_OFFSET DOMAIN_CTRL_STAT_OFFSET |
| 137 | #define HNF_SDC_SET_OFFSET DOMAIN_CTRL_SET_OFFSET |
| 138 | #define HNF_SDC_CLR_OFFSET DOMAIN_CTRL_CLR_OFFSET |
| 139 | #define HNF_AUX_CTRL_OFFSET 0x0500 |
| 140 | |
| 141 | /* Selected register offsets from the base of a MN region */ |
| 142 | #define MN_SAR_OFFSET 0x0000 |
| 143 | #define MN_RNF_NODEID_OFFSET 0x0180 |
| 144 | #define MN_RNI_NODEID_OFFSET 0x0190 |
| 145 | #define MN_RND_NODEID_OFFSET 0x01A0 |
| 146 | #define MN_HNF_NODEID_OFFSET 0x01B0 |
| 147 | #define MN_HNI_NODEID_OFFSET 0x01C0 |
| 148 | #define MN_SN_NODEID_OFFSET 0x01D0 |
| 149 | #define MN_DDC_STAT_OFFSET DOMAIN_CTRL_STAT_OFFSET |
Vikram Kanigiri | 4aceeb0 | 2016-01-04 16:23:22 +0000 | [diff] [blame] | 150 | #define MN_DDC_SET_OFFSET DOMAIN_CTRL_SET_OFFSET |
Achin Gupta | a80720f | 2015-07-20 22:28:23 +0100 | [diff] [blame] | 151 | #define MN_DDC_CLR_OFFSET DOMAIN_CTRL_CLR_OFFSET |
| 152 | #define MN_ID_OFFSET REGION_ID_OFFSET |
| 153 | |
| 154 | /* HNF System Address Map register bit masks and shifts */ |
| 155 | #define HNF_SAM_CTRL_SN_ID_MASK 0x7f |
| 156 | #define HNF_SAM_CTRL_SN0_ID_SHIFT 0 |
| 157 | #define HNF_SAM_CTRL_SN1_ID_SHIFT 8 |
| 158 | #define HNF_SAM_CTRL_SN2_ID_SHIFT 16 |
| 159 | |
| 160 | #define HNF_SAM_CTRL_TAB0_MASK 0x3fUL |
| 161 | #define HNF_SAM_CTRL_TAB0_SHIFT 48 |
| 162 | #define HNF_SAM_CTRL_TAB1_MASK 0x3fUL |
| 163 | #define HNF_SAM_CTRL_TAB1_SHIFT 56 |
| 164 | |
| 165 | #define HNF_SAM_CTRL_3SN_ENB_SHIFT 32 |
| 166 | #define HNF_SAM_CTRL_3SN_ENB_MASK 0x01UL |
| 167 | |
| 168 | /* |
| 169 | * Macro to create a value suitable for programming into a HNF SAM Control |
| 170 | * register for enabling 3SN striping. |
| 171 | */ |
| 172 | #define MAKE_HNF_SAM_CTRL_VALUE(sn0, sn1, sn2, tab0, tab1, three_sn_en) \ |
| 173 | ((((sn0) & HNF_SAM_CTRL_SN_ID_MASK) << HNF_SAM_CTRL_SN0_ID_SHIFT) | \ |
| 174 | (((sn1) & HNF_SAM_CTRL_SN_ID_MASK) << HNF_SAM_CTRL_SN1_ID_SHIFT) | \ |
| 175 | (((sn2) & HNF_SAM_CTRL_SN_ID_MASK) << HNF_SAM_CTRL_SN2_ID_SHIFT) | \ |
| 176 | (((tab0) & HNF_SAM_CTRL_TAB0_MASK) << HNF_SAM_CTRL_TAB0_SHIFT) | \ |
| 177 | (((tab1) & HNF_SAM_CTRL_TAB1_MASK) << HNF_SAM_CTRL_TAB1_SHIFT) | \ |
| 178 | (((three_sn_en) & HNF_SAM_CTRL_3SN_ENB_MASK) << HNF_SAM_CTRL_3SN_ENB_SHIFT)) |
| 179 | |
| 180 | /* Mask to read the power state value from an HN-F P-state register */ |
| 181 | #define HNF_PSTATE_MASK 0xf |
| 182 | |
| 183 | /* Macro to extract the run mode from a p-state value */ |
| 184 | #define PSTATE_TO_RUN_MODE(pstate) (((pstate) & HNF_PSTATE_MASK) >> 2) |
| 185 | |
| 186 | /* |
| 187 | * Helper macro that iterates through a given bit map. In each iteration, |
| 188 | * it returns the position of the set bit. |
| 189 | * It can be used by other utility macros to iterates through all nodes |
| 190 | * or masters given a bit map of them. |
| 191 | */ |
| 192 | #define FOR_EACH_BIT(bit_pos, bit_map) \ |
| 193 | for (bit_pos = __builtin_ctzll(bit_map); \ |
| 194 | bit_map; \ |
| 195 | bit_map &= ~(1UL << bit_pos), \ |
| 196 | bit_pos = __builtin_ctzll(bit_map)) |
| 197 | |
| 198 | /* |
| 199 | * Utility macro that iterates through a bit map of node IDs. In each |
| 200 | * iteration, it returns the ID of the next present node in the bit map. Node |
| 201 | * ID of a present node == Position of set bit == Number of zeroes trailing the |
| 202 | * bit. |
| 203 | */ |
| 204 | #define FOR_EACH_PRESENT_NODE_ID(node_id, bit_map) \ |
| 205 | FOR_EACH_BIT(node_id, bit_map) |
| 206 | |
| 207 | /* |
| 208 | * Helper function to return number of set bits in bitmap |
| 209 | */ |
| 210 | static inline unsigned int count_set_bits(uint64_t bitmap) |
| 211 | { |
| 212 | unsigned int count = 0; |
| 213 | |
| 214 | for (; bitmap; bitmap &= bitmap - 1) |
| 215 | ++count; |
| 216 | |
| 217 | return count; |
| 218 | } |
| 219 | |
| 220 | /* |
| 221 | * Utility macro that iterates through a bit map of node IDs. In each iteration, |
| 222 | * it returns the ID of the next present region corresponding to a node present |
| 223 | * in the bit map. Region ID of a present node is in between passed region id |
| 224 | * and region id + number of set bits in the bitmap i.e. the number of present |
| 225 | * nodes. |
| 226 | */ |
| 227 | #define FOR_EACH_PRESENT_REGION_ID(region_id, bit_map) \ |
| 228 | for (unsigned long long region_id_limit = count_set_bits(bit_map) \ |
| 229 | + region_id; \ |
| 230 | region_id < region_id_limit; \ |
| 231 | region_id++) |
| 232 | |
| 233 | /* |
| 234 | * Same macro as FOR_EACH_PRESENT_NODE, but renamed to indicate it traverses |
| 235 | * through a bit map of master interfaces. |
| 236 | */ |
| 237 | #define FOR_EACH_PRESENT_MASTER_INTERFACE(iface_id, bit_map) \ |
| 238 | FOR_EACH_BIT(iface_id, bit_map) |
Vikram Kanigiri | 4aceeb0 | 2016-01-04 16:23:22 +0000 | [diff] [blame] | 239 | |
| 240 | /* |
| 241 | * Macro that returns the node id bit map for the Miscellaneous Node |
| 242 | */ |
| 243 | #define CCN_GET_MN_NODEID_MAP(periphbase) \ |
| 244 | (1 << get_node_id(ccn_reg_read(periphbase, MN_REGION_ID, \ |
| 245 | REGION_ID_OFFSET))) |
| 246 | |
| 247 | /* |
| 248 | * This macro returns the bitmap of Home nodes on the basis of the |
| 249 | * 'mn_hn_id_reg_offset' parameter from the Miscellaneous node's (MN) |
| 250 | * programmer's view. The MN has a register which carries the bitmap of present |
| 251 | * Home nodes of each type i.e. HN-Fs, HN-Is & HN-Ds. |
| 252 | */ |
| 253 | #define CCN_GET_HN_NODEID_MAP(periphbase, mn_hn_id_reg_offset) \ |
| 254 | ccn_reg_read(periphbase, MN_REGION_ID, mn_hn_id_reg_offset) |
| 255 | |
Achin Gupta | a80720f | 2015-07-20 22:28:23 +0100 | [diff] [blame] | 256 | #endif /* __CCN_PRIVATE_H__ */ |