1 /* 2 * Copyright 2017 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 */ 23 /* 24 * dc_helper.c 25 * 26 * Created on: Aug 30, 2016 27 * Author: agrodzov 28 */ 29 30 #include <linux/delay.h> 31 32 #include "dm_services.h" 33 #include <stdarg.h> 34 35 struct dc_reg_value_masks { 36 uint32_t value; 37 uint32_t mask; 38 }; 39 40 struct dc_reg_sequence { 41 uint32_t addr; 42 struct dc_reg_value_masks value_masks; 43 }; 44 45 static inline void set_reg_field_value_masks( 46 struct dc_reg_value_masks *field_value_mask, 47 uint32_t value, 48 uint32_t mask, 49 uint8_t shift) 50 { 51 ASSERT(mask != 0); 52 53 field_value_mask->value = (field_value_mask->value & ~mask) | (mask & (value << shift)); 54 field_value_mask->mask = field_value_mask->mask | mask; 55 } 56 57 static void set_reg_field_values(struct dc_reg_value_masks *field_value_mask, 58 uint32_t addr, int n, 59 uint8_t shift1, uint32_t mask1, uint32_t field_value1, 60 va_list ap) 61 { 62 uint32_t shift, mask, field_value; 63 int i = 1; 64 65 /* gather all bits value/mask getting updated in this register */ 66 set_reg_field_value_masks(field_value_mask, 67 field_value1, mask1, shift1); 68 69 while (i < n) { 70 shift = va_arg(ap, uint32_t); 71 mask = va_arg(ap, uint32_t); 72 field_value = va_arg(ap, uint32_t); 73 74 set_reg_field_value_masks(field_value_mask, 75 field_value, mask, shift); 76 i++; 77 } 78 } 79 80 uint32_t generic_reg_update_ex(const struct dc_context *ctx, 81 uint32_t addr, int n, 82 uint8_t shift1, uint32_t mask1, uint32_t field_value1, 83 ...) 84 { 85 struct dc_reg_value_masks field_value_mask = {0}; 86 uint32_t reg_val; 87 va_list ap; 88 89 va_start(ap, field_value1); 90 91 set_reg_field_values(&field_value_mask, addr, n, shift1, mask1, 92 field_value1, ap); 93 94 va_end(ap); 95 96 /* mmio write directly */ 97 reg_val = dm_read_reg(ctx, addr); 98 reg_val = (reg_val & ~field_value_mask.mask) | field_value_mask.value; 99 dm_write_reg(ctx, addr, reg_val); 100 return reg_val; 101 } 102 103 uint32_t generic_reg_set_ex(const struct dc_context *ctx, 104 uint32_t addr, uint32_t reg_val, int n, 105 uint8_t shift1, uint32_t mask1, uint32_t field_value1, 106 ...) 107 { 108 struct dc_reg_value_masks field_value_mask = {0}; 109 va_list ap; 110 111 va_start(ap, field_value1); 112 113 set_reg_field_values(&field_value_mask, addr, n, shift1, mask1, 114 field_value1, ap); 115 116 va_end(ap); 117 118 119 /* mmio write directly */ 120 reg_val = (reg_val & ~field_value_mask.mask) | field_value_mask.value; 121 dm_write_reg(ctx, addr, reg_val); 122 return reg_val; 123 } 124 125 uint32_t dm_read_reg_func( 126 const struct dc_context *ctx, 127 uint32_t address, 128 const char *func_name) 129 { 130 uint32_t value; 131 #ifdef DM_CHECK_ADDR_0 132 if (address == 0) { 133 DC_ERR("invalid register read; address = 0\n"); 134 return 0; 135 } 136 #endif 137 value = cgs_read_register(ctx->cgs_device, address); 138 trace_amdgpu_dc_rreg(&ctx->perf_trace->read_count, address, value); 139 140 return value; 141 } 142 143 uint32_t generic_reg_get(const struct dc_context *ctx, uint32_t addr, 144 uint8_t shift, uint32_t mask, uint32_t *field_value) 145 { 146 uint32_t reg_val = dm_read_reg(ctx, addr); 147 *field_value = get_reg_field_value_ex(reg_val, mask, shift); 148 return reg_val; 149 } 150 151 uint32_t generic_reg_get2(const struct dc_context *ctx, uint32_t addr, 152 uint8_t shift1, uint32_t mask1, uint32_t *field_value1, 153 uint8_t shift2, uint32_t mask2, uint32_t *field_value2) 154 { 155 uint32_t reg_val = dm_read_reg(ctx, addr); 156 *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1); 157 *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2); 158 return reg_val; 159 } 160 161 uint32_t generic_reg_get3(const struct dc_context *ctx, uint32_t addr, 162 uint8_t shift1, uint32_t mask1, uint32_t *field_value1, 163 uint8_t shift2, uint32_t mask2, uint32_t *field_value2, 164 uint8_t shift3, uint32_t mask3, uint32_t *field_value3) 165 { 166 uint32_t reg_val = dm_read_reg(ctx, addr); 167 *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1); 168 *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2); 169 *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3); 170 return reg_val; 171 } 172 173 uint32_t generic_reg_get4(const struct dc_context *ctx, uint32_t addr, 174 uint8_t shift1, uint32_t mask1, uint32_t *field_value1, 175 uint8_t shift2, uint32_t mask2, uint32_t *field_value2, 176 uint8_t shift3, uint32_t mask3, uint32_t *field_value3, 177 uint8_t shift4, uint32_t mask4, uint32_t *field_value4) 178 { 179 uint32_t reg_val = dm_read_reg(ctx, addr); 180 *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1); 181 *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2); 182 *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3); 183 *field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4); 184 return reg_val; 185 } 186 187 uint32_t generic_reg_get5(const struct dc_context *ctx, uint32_t addr, 188 uint8_t shift1, uint32_t mask1, uint32_t *field_value1, 189 uint8_t shift2, uint32_t mask2, uint32_t *field_value2, 190 uint8_t shift3, uint32_t mask3, uint32_t *field_value3, 191 uint8_t shift4, uint32_t mask4, uint32_t *field_value4, 192 uint8_t shift5, uint32_t mask5, uint32_t *field_value5) 193 { 194 uint32_t reg_val = dm_read_reg(ctx, addr); 195 *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1); 196 *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2); 197 *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3); 198 *field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4); 199 *field_value5 = get_reg_field_value_ex(reg_val, mask5, shift5); 200 return reg_val; 201 } 202 203 uint32_t generic_reg_get6(const struct dc_context *ctx, uint32_t addr, 204 uint8_t shift1, uint32_t mask1, uint32_t *field_value1, 205 uint8_t shift2, uint32_t mask2, uint32_t *field_value2, 206 uint8_t shift3, uint32_t mask3, uint32_t *field_value3, 207 uint8_t shift4, uint32_t mask4, uint32_t *field_value4, 208 uint8_t shift5, uint32_t mask5, uint32_t *field_value5, 209 uint8_t shift6, uint32_t mask6, uint32_t *field_value6) 210 { 211 uint32_t reg_val = dm_read_reg(ctx, addr); 212 *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1); 213 *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2); 214 *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3); 215 *field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4); 216 *field_value5 = get_reg_field_value_ex(reg_val, mask5, shift5); 217 *field_value6 = get_reg_field_value_ex(reg_val, mask6, shift6); 218 return reg_val; 219 } 220 221 uint32_t generic_reg_get7(const struct dc_context *ctx, uint32_t addr, 222 uint8_t shift1, uint32_t mask1, uint32_t *field_value1, 223 uint8_t shift2, uint32_t mask2, uint32_t *field_value2, 224 uint8_t shift3, uint32_t mask3, uint32_t *field_value3, 225 uint8_t shift4, uint32_t mask4, uint32_t *field_value4, 226 uint8_t shift5, uint32_t mask5, uint32_t *field_value5, 227 uint8_t shift6, uint32_t mask6, uint32_t *field_value6, 228 uint8_t shift7, uint32_t mask7, uint32_t *field_value7) 229 { 230 uint32_t reg_val = dm_read_reg(ctx, addr); 231 *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1); 232 *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2); 233 *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3); 234 *field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4); 235 *field_value5 = get_reg_field_value_ex(reg_val, mask5, shift5); 236 *field_value6 = get_reg_field_value_ex(reg_val, mask6, shift6); 237 *field_value7 = get_reg_field_value_ex(reg_val, mask7, shift7); 238 return reg_val; 239 } 240 241 uint32_t generic_reg_get8(const struct dc_context *ctx, uint32_t addr, 242 uint8_t shift1, uint32_t mask1, uint32_t *field_value1, 243 uint8_t shift2, uint32_t mask2, uint32_t *field_value2, 244 uint8_t shift3, uint32_t mask3, uint32_t *field_value3, 245 uint8_t shift4, uint32_t mask4, uint32_t *field_value4, 246 uint8_t shift5, uint32_t mask5, uint32_t *field_value5, 247 uint8_t shift6, uint32_t mask6, uint32_t *field_value6, 248 uint8_t shift7, uint32_t mask7, uint32_t *field_value7, 249 uint8_t shift8, uint32_t mask8, uint32_t *field_value8) 250 { 251 uint32_t reg_val = dm_read_reg(ctx, addr); 252 *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1); 253 *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2); 254 *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3); 255 *field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4); 256 *field_value5 = get_reg_field_value_ex(reg_val, mask5, shift5); 257 *field_value6 = get_reg_field_value_ex(reg_val, mask6, shift6); 258 *field_value7 = get_reg_field_value_ex(reg_val, mask7, shift7); 259 *field_value8 = get_reg_field_value_ex(reg_val, mask8, shift8); 260 return reg_val; 261 } 262 /* note: va version of this is pretty bad idea, since there is a output parameter pass by pointer 263 * compiler won't be able to check for size match and is prone to stack corruption type of bugs 264 265 uint32_t generic_reg_get(const struct dc_context *ctx, 266 uint32_t addr, int n, ...) 267 { 268 uint32_t shift, mask; 269 uint32_t *field_value; 270 uint32_t reg_val; 271 int i = 0; 272 273 reg_val = dm_read_reg(ctx, addr); 274 275 va_list ap; 276 va_start(ap, n); 277 278 while (i < n) { 279 shift = va_arg(ap, uint32_t); 280 mask = va_arg(ap, uint32_t); 281 field_value = va_arg(ap, uint32_t *); 282 283 *field_value = get_reg_field_value_ex(reg_val, mask, shift); 284 i++; 285 } 286 287 va_end(ap); 288 289 return reg_val; 290 } 291 */ 292 293 void generic_reg_wait(const struct dc_context *ctx, 294 uint32_t addr, uint32_t shift, uint32_t mask, uint32_t condition_value, 295 unsigned int delay_between_poll_us, unsigned int time_out_num_tries, 296 const char *func_name, int line) 297 { 298 uint32_t field_value; 299 uint32_t reg_val; 300 int i; 301 302 /* something is terribly wrong if time out is > 200ms. (5Hz) */ 303 ASSERT(delay_between_poll_us * time_out_num_tries <= 3000000); 304 305 for (i = 0; i <= time_out_num_tries; i++) { 306 if (i) { 307 if (delay_between_poll_us >= 1000) 308 msleep(delay_between_poll_us/1000); 309 else if (delay_between_poll_us > 0) 310 udelay(delay_between_poll_us); 311 } 312 313 reg_val = dm_read_reg(ctx, addr); 314 315 field_value = get_reg_field_value_ex(reg_val, mask, shift); 316 317 if (field_value == condition_value) { 318 if (i * delay_between_poll_us > 1000 && 319 !IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) 320 DC_LOG_DC("REG_WAIT taking a while: %dms in %s line:%d\n", 321 delay_between_poll_us * i / 1000, 322 func_name, line); 323 return; 324 } 325 } 326 327 DC_LOG_WARNING("REG_WAIT timeout %dus * %d tries - %s line:%d\n", 328 delay_between_poll_us, time_out_num_tries, 329 func_name, line); 330 331 if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) 332 BREAK_TO_DEBUGGER(); 333 } 334 335 void generic_write_indirect_reg(const struct dc_context *ctx, 336 uint32_t addr_index, uint32_t addr_data, 337 uint32_t index, uint32_t data) 338 { 339 dm_write_reg(ctx, addr_index, index); 340 dm_write_reg(ctx, addr_data, data); 341 } 342 343 uint32_t generic_read_indirect_reg(const struct dc_context *ctx, 344 uint32_t addr_index, uint32_t addr_data, 345 uint32_t index) 346 { 347 uint32_t value = 0; 348 349 dm_write_reg(ctx, addr_index, index); 350 value = dm_read_reg(ctx, addr_data); 351 352 return value; 353 } 354 355 356 uint32_t generic_indirect_reg_update_ex(const struct dc_context *ctx, 357 uint32_t addr_index, uint32_t addr_data, 358 uint32_t index, uint32_t reg_val, int n, 359 uint8_t shift1, uint32_t mask1, uint32_t field_value1, 360 ...) 361 { 362 uint32_t shift, mask, field_value; 363 int i = 1; 364 365 va_list ap; 366 367 va_start(ap, field_value1); 368 369 reg_val = set_reg_field_value_ex(reg_val, field_value1, mask1, shift1); 370 371 while (i < n) { 372 shift = va_arg(ap, uint32_t); 373 mask = va_arg(ap, uint32_t); 374 field_value = va_arg(ap, uint32_t); 375 376 reg_val = set_reg_field_value_ex(reg_val, field_value, mask, shift); 377 i++; 378 } 379 380 generic_write_indirect_reg(ctx, addr_index, addr_data, index, reg_val); 381 va_end(ap); 382 383 return reg_val; 384 } 385