1 /***********************license start*********************************** 2 * Copyright (C) 2021-2026 Marvell. 3 * SPDX-License-Identifier: BSD-3-Clause 4 * https://spdx.org/licenses 5 ***********************license end**************************************/ 6 #ifndef __ODY_CSR_H__ 7 #define __ODY_CSR_H__ 8 9 /** 10 * @file 11 * 12 * Functions and macros for accessing Cavium CSRs. 13 * 14 * <hr>$Revision: 49448 $<hr> 15 * 16 * @defgroup csr CSR support 17 * @{ 18 */ 19 20 /** 21 * Possible CSR bus types 22 */ 23 typedef enum { 24 CSR_TYPE_DAB, /**< External debug 64bit CSR */ 25 CSR_TYPE_DAB32b, /**< External debug 32bit CSR */ 26 CSR_TYPE_MDSB, /**< CN96XX: Memory Diagnostic Serial Bus?, not memory mapped */ 27 CSR_TYPE_NCB, /**< Fast 64bit CSR */ 28 CSR_TYPE_NCB32b, /**< Fast 32bit CSR */ 29 CSR_TYPE_PCCBR, 30 CSR_TYPE_PCCPF, 31 CSR_TYPE_PCCVF, 32 CSR_TYPE_PCICONFIGRC, /**< PCIe config address (RC mode) */ 33 CSR_TYPE_PCICONFIGEP, /**< PCIe config address (EP mode) */ 34 CSR_TYPE_PCICONFIGEP_SHADOW, /**< CN96XX: PCIEP register invisible to host, not memory mapped */ 35 CSR_TYPE_PCICONFIGEPVF, /**< CN96XX: PCIEP registers only on vertain PEMs, not memory mapped */ 36 CSR_TYPE_PEXP, /**< PCIe BAR 0 address only */ 37 CSR_TYPE_PEXP_NCB, /**< NCB-direct and PCIe BAR0 address */ 38 CSR_TYPE_RSL, /**< Slow 64bit CSR */ 39 CSR_TYPE_RSL32b, /**< Slow 32bit CSR */ 40 CSR_TYPE_RVU_PF_BAR0, /**< Index into RVU PF BAR0 */ 41 CSR_TYPE_RVU_PF_BAR2, /**< Index into RVU PF BAR2 */ 42 CSR_TYPE_RVU_PFVF_BAR2, /**< Index into RVU PF or VF BAR2 */ 43 CSR_TYPE_RVU_VF_BAR2, /**< Index into RVU VF BAR2 */ 44 CSR_TYPE_SYSREG, /**< Core system register */ 45 } ody_csr_type_t; 46 47 #define CSR_DB_MAX_PARAM 6 48 typedef struct __attribute__ ((packed)) { 49 uint32_t name_index : 20;/**< Index into __ody_csr_db_string where the name is */ 50 uint32_t width : 4; /**< CSR width in bytes */ 51 ody_csr_type_t type : 8; /**< Enum type from above */ 52 uint16_t base_index; /**< Index into __ody_csr_db_number where the base address is */ 53 uint16_t field_index; /**< Index into __ody_csr_db_fieldList where the fields start */ 54 uint16_t range_index; /**< Index into __ody_csr_db_range where the range is */ 55 uint16_t param_inc_index; /**< Index into __ody_csr_db_number where the param multiplier is */ 56 } __ody_csr_db_type_t; 57 58 typedef struct __attribute__ ((packed)) { 59 uint32_t name_index : 20;/**< Index into __ody_csr_db_string where the name is */ 60 uint32_t start_bit : 6; /**< LSB of the field */ 61 uint32_t stop_bit : 6; /**< MSB of the field */ 62 } __ody_csr_db_field_t; 63 64 typedef struct { 65 uint32_t model; 66 uint32_t offset; 67 } __ody_csr_db_map_t; 68 69 struct ody_readline_tab; 70 extern uint64_t ody_sysreg_read(int core, uint64_t regnum); 71 extern void ody_sysreg_write(int core, uint64_t regnum, uint64_t value); 72 73 #ifndef ODY_BUILD_HOST 74 75 /** 76 * Read a value from a CSR. Normally this function should not be 77 * used directly. Instead use the macro CSR_READ that fills 78 * in the parameters to this function for you. 79 * 80 * @param type Bus type the CSR is on 81 * @param busnum Bus number the CSR is on 82 * @param size Width of the CSR in bytes 83 * @param address The address of the CSR 84 * 85 * @return The value of the CSR 86 */ 87 static inline uint64_t ody_csr_read(ody_csr_type_t type, int busnum, int size, uint64_t address) __attribute__ ((always_inline)); 88 static inline uint64_t ody_csr_read(ody_csr_type_t type, int busnum, int size, uint64_t address) 89 { 90 extern uint64_t __ody_csr_read_slow(ody_csr_type_t type, int busnum, int size, uint64_t address); 91 92 switch (type) { 93 case CSR_TYPE_DAB: 94 case CSR_TYPE_DAB32b: 95 case CSR_TYPE_NCB: 96 case CSR_TYPE_NCB32b: 97 case CSR_TYPE_PEXP_NCB: 98 case CSR_TYPE_RSL: 99 case CSR_TYPE_RSL32b: 100 case CSR_TYPE_RVU_PF_BAR0: 101 case CSR_TYPE_RVU_PF_BAR2: 102 case CSR_TYPE_RVU_PFVF_BAR2: 103 case CSR_TYPE_RVU_VF_BAR2: 104 /* Note: This code assume a 1:1 mapping of all of address space 105 * It is designed to run with the MMU disabled 106 */ 107 switch (size) { 108 case 1: 109 return *(volatile uint8_t *)address; 110 case 2: 111 return ody_le16_to_cpu(*(volatile uint16_t *)address); 112 case 4: 113 return ody_le32_to_cpu(*(volatile uint32_t *)address); 114 default: 115 return ody_le64_to_cpu(*(volatile uint64_t *)address); 116 } 117 default: 118 return __ody_csr_read_slow(type, busnum, size, address); 119 } 120 } 121 122 123 /** 124 * Wrate a value to a CSR. Normally this function should not be 125 * used directly. Instead use the macro CSR_WRITE that fills 126 * in the parameters to this function for you. 127 * 128 * @param type Bus type the CSR is on 129 * @param busnum Bus number the CSR is on 130 * @param size Width of the CSR in bytes 131 * @param address The address of the CSR 132 * @param value Value to write to the CSR 133 */ 134 static inline void ody_csr_write(ody_csr_type_t type, int busnum, int size, uint64_t address, uint64_t value) __attribute__ ((always_inline)); 135 static inline void ody_csr_write(ody_csr_type_t type, int busnum, int size, uint64_t address, uint64_t value) 136 { 137 extern void __ody_csr_write_slow(ody_csr_type_t type, int busnum, int size, uint64_t address, uint64_t value); 138 139 switch (type) { 140 case CSR_TYPE_DAB: 141 case CSR_TYPE_DAB32b: 142 case CSR_TYPE_NCB: 143 case CSR_TYPE_NCB32b: 144 case CSR_TYPE_PEXP_NCB: 145 case CSR_TYPE_RSL: 146 case CSR_TYPE_RSL32b: 147 case CSR_TYPE_RVU_PF_BAR0: 148 case CSR_TYPE_RVU_PF_BAR2: 149 case CSR_TYPE_RVU_PFVF_BAR2: 150 case CSR_TYPE_RVU_VF_BAR2: 151 /* Note: This code assume a 1:1 mapping of all of address space. 152 * It is designed to run with the MMU disabled 153 */ 154 switch (size) { 155 case 1: 156 *(volatile uint8_t *)address = value; 157 break; 158 case 2: 159 *(volatile uint16_t *)address = ody_cpu_to_le16(value); 160 break; 161 case 4: 162 *(volatile uint32_t *)address = ody_cpu_to_le32(value); 163 break; 164 default: 165 *(volatile uint64_t *)address = ody_cpu_to_le64(value); 166 break; 167 } 168 break; 169 default: 170 __ody_csr_write_slow(type, busnum, size, address, value); 171 } 172 } 173 174 #else 175 #define ody_csr_read thunder_remote_read_csr 176 #define ody_csr_write thunder_remote_write_csr 177 #endif 178 179 /** 180 * This macro makes it easy to define a variable of the correct 181 * type for a CSR. 182 */ 183 #define CSR_DEFINE(name, csr) typedef_##csr name 184 185 /** 186 * This macro makes it easy to define a variable and initialize it 187 * with a CSR. 188 */ 189 #define CSR_INIT(name, csr) typedef_##csr name = {.u = ody_csr_read(bustype_##csr, busnum_##csr, sizeof(typedef_##csr), csr)} 190 191 /** 192 * Macro to read a CSR 193 */ 194 #define CSR_READ(csr) ody_csr_read(bustype_##csr, busnum_##csr, sizeof(typedef_##csr), csr) 195 196 /** 197 * Macro to write a CSR 198 */ 199 #define CSR_WRITE(csr, value) ody_csr_write(bustype_##csr, busnum_##csr, sizeof(typedef_##csr), csr, value) 200 201 /** 202 * Macro to make a read, modify, and write sequence easy. The "code_block" 203 * should be replaced with a C code block or a comma separated list of 204 * "name.s.field = value", without the quotes. 205 */ 206 #define CSR_MODIFY(name, csr, code_block) do { \ 207 uint64_t _tmp_address = csr; \ 208 typedef_##csr name = {.u = ody_csr_read(bustype_##csr, busnum_##csr, sizeof(typedef_##csr), _tmp_address)}; \ 209 code_block; \ 210 ody_csr_write(bustype_##csr, busnum_##csr, sizeof(typedef_##csr), _tmp_address, name.u); \ 211 } while (0) 212 213 /** 214 * This macro spins on a field waiting for it to reach a value. It 215 * is common in code to need to wait for a specific field in a CSR 216 * to match a specific value. Conceptually this macro expands to: 217 * 218 * 1) read csr at "address" with a csr typedef of "type" 219 * 2) Check if ("type".s."field" "op" "value") 220 * 3) If #2 isn't true loop to #1 unless too much time has passed. 221 */ 222 #define CSR_WAIT_FOR_FIELD(csr, field, op, value, timeout_usec) \ 223 ({int result; \ 224 do { \ 225 uint64_t done = ody_clock_get_count(CLOCK_TIME) + (uint64_t)timeout_usec * \ 226 ody_clock_get_rate(CLOCK_TIME) / 1000000; \ 227 typedef_##csr c; \ 228 uint64_t _tmp_address = csr; \ 229 while (1) { \ 230 c.u = ody_csr_read(bustype_##csr, busnum_##csr, sizeof(typedef_##csr), _tmp_address); \ 231 if ((c.s.field) op(value)) { \ 232 result = 0; \ 233 break; \ 234 } else if (ody_clock_get_count(CLOCK_TIME) > done) { \ 235 result = -1; \ 236 break; \ 237 } else \ 238 ody_wait_usec(1); \ 239 } \ 240 } while (0); \ 241 result; }) 242 243 /** 244 * This macro spins on a field waiting for it to reach a value. It 245 * is common in code to need to wait for a specific field in a CSR 246 * to match a specific value. Conceptually this macro expands to: 247 * 248 * 1) read csr at "address" with a csr typedef of "type" 249 * 2) Check if ("type".s."field" "op" "value") 250 * 3) If #2 isn't true loop to #1 unless too much time has passed. 251 */ 252 #define CSR_WAIT_FOR_FIELD_ACTUAL(csr, field, op, value, timeout_usec) \ 253 ({int result; \ 254 do { \ 255 uint64_t _start_time = ody_clock_get_count(CLOCK_TIME); \ 256 uint64_t done = _start_time + (uint64_t)timeout_usec * \ 257 ody_clock_get_rate(CLOCK_TIME) / 1000000; \ 258 typedef_##csr c; \ 259 uint64_t _tmp_address = csr; \ 260 uint64_t _current_time; \ 261 while (1) { \ 262 c.u = ody_csr_read(bustype_##csr, busnum_##csr, sizeof(typedef_##csr), _tmp_address); \ 263 _current_time = ody_clock_get_count(CLOCK_TIME); \ 264 if ((c.s.field) op(value)) { \ 265 result = _current_time - _start_time; \ 266 break; \ 267 } else if (_current_time > done) { \ 268 result = -1; \ 269 break; \ 270 } else \ 271 ody_thread_yield(); \ 272 } \ 273 } while (0); \ 274 result; }) 275 276 /** 277 * This macro spins on a field waiting for it to reach a value. It 278 * is common in code to need to wait for a specific field in a CSR 279 * to match a specific value. Conceptually this macro expands to: 280 * 281 * 1) read csr at "address" with a csr typedef of "type" 282 * 2) Check if ("type"."chip"."field" "op" "value") 283 * 3) If #2 isn't true loop to #1 unless too much time has passed. 284 * 285 * Note that usage of this macro should be avoided. When future chips 286 * change bit locations, the compiler will not catch those changes 287 * with this macro. Changes silently do the wrong thing at runtime. 288 */ 289 #define CSR_WAIT_FOR_CHIP_FIELD(csr, chip, field, op, value, timeout_usec) \ 290 ({int result; \ 291 do { \ 292 uint64_t done = ody_clock_get_count(CLOCK_TIME) + (uint64_t)timeout_usec * \ 293 ody_clock_get_rate(CLOCK_TIME) / 1000000; \ 294 typedef_##csr c; \ 295 uint64_t _tmp_address = csr; \ 296 while (1) { \ 297 c.u = ody_csr_read(bustype_##csr, busnum_##csr, sizeof(typedef_##csr), _tmp_address); \ 298 if ((c.chip.field) op(value)) { \ 299 result = 0; \ 300 break; \ 301 } else if (ody_clock_get_count(CLOCK_TIME) > done) { \ 302 result = -1; \ 303 break; \ 304 } else \ 305 ody_wait_usec(1); \ 306 } \ 307 } while (0); \ 308 result; }) 309 310 /** @} */ 311 #endif 312