1 /* 2 * Copyright 2018 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 * Authors: AMD 23 * 24 */ 25 #include "dm_services.h" 26 #include "dcn20/dcn20_hubbub.h" 27 #include "dcn21_hubbub.h" 28 #include "reg_helper.h" 29 30 #define REG(reg)\ 31 hubbub1->regs->reg 32 #define DC_LOGGER \ 33 hubbub1->base.ctx->logger 34 #define CTX \ 35 hubbub1->base.ctx 36 37 #undef FN 38 #define FN(reg_name, field_name) \ 39 hubbub1->shifts->field_name, hubbub1->masks->field_name 40 41 #define REG(reg)\ 42 hubbub1->regs->reg 43 44 #define CTX \ 45 hubbub1->base.ctx 46 47 #undef FN 48 #define FN(reg_name, field_name) \ 49 hubbub1->shifts->field_name, hubbub1->masks->field_name 50 51 #ifdef NUM_VMID 52 #undef NUM_VMID 53 #endif 54 #define NUM_VMID 1 55 56 static uint32_t convert_and_clamp( 57 uint32_t wm_ns, 58 uint32_t refclk_mhz, 59 uint32_t clamp_value) 60 { 61 uint32_t ret_val = 0; 62 ret_val = wm_ns * refclk_mhz; 63 ret_val /= 1000; 64 65 if (ret_val > clamp_value) 66 ret_val = clamp_value; 67 68 return ret_val; 69 } 70 71 void dcn21_dchvm_init(struct hubbub *hubbub) 72 { 73 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub); 74 75 //Init DCHVM block 76 REG_UPDATE(DCHVM_CTRL0, HOSTVM_INIT_REQ, 1); 77 78 //Poll until RIOMMU_ACTIVE = 1 79 //TODO: Figure out interval us and retry count 80 REG_WAIT(DCHVM_RIOMMU_STAT0, RIOMMU_ACTIVE, 1, 5, 100); 81 82 //Reflect the power status of DCHUBBUB 83 REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_POWERSTATUS, 1); 84 85 //Start rIOMMU prefetching 86 REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_PREFETCH_REQ, 1); 87 88 // Enable dynamic clock gating 89 REG_UPDATE_4(DCHVM_CLK_CTRL, 90 HVM_DISPCLK_R_GATE_DIS, 0, 91 HVM_DISPCLK_G_GATE_DIS, 0, 92 HVM_DCFCLK_R_GATE_DIS, 0, 93 HVM_DCFCLK_G_GATE_DIS, 0); 94 95 //Poll until HOSTVM_PREFETCH_DONE = 1 96 //TODO: Figure out interval us and retry count 97 REG_WAIT(DCHVM_RIOMMU_STAT0, HOSTVM_PREFETCH_DONE, 1, 5, 100); 98 } 99 100 static int hubbub21_init_dchub(struct hubbub *hubbub, 101 struct dcn_hubbub_phys_addr_config *pa_config) 102 { 103 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub); 104 105 REG_SET(DCN_VM_FB_LOCATION_BASE, 0, 106 FB_BASE, pa_config->system_aperture.fb_base); 107 REG_SET(DCN_VM_FB_LOCATION_TOP, 0, 108 FB_TOP, pa_config->system_aperture.fb_top); 109 REG_SET(DCN_VM_FB_OFFSET, 0, 110 FB_OFFSET, pa_config->system_aperture.fb_offset); 111 REG_SET(DCN_VM_AGP_BOT, 0, 112 AGP_BOT, pa_config->system_aperture.agp_bot); 113 REG_SET(DCN_VM_AGP_TOP, 0, 114 AGP_TOP, pa_config->system_aperture.agp_top); 115 REG_SET(DCN_VM_AGP_BASE, 0, 116 AGP_BASE, pa_config->system_aperture.agp_base); 117 118 dcn21_dchvm_init(hubbub); 119 120 return NUM_VMID; 121 } 122 123 static void hubbub21_program_urgent_watermarks( 124 struct hubbub *hubbub, 125 struct dcn_watermark_set *watermarks, 126 unsigned int refclk_mhz, 127 bool safe_to_lower) 128 { 129 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub); 130 uint32_t prog_wm_value; 131 132 /* Repeat for water mark set A, B, C and D. */ 133 /* clock state A */ 134 if (safe_to_lower || watermarks->a.urgent_ns > hubbub1->watermarks.a.urgent_ns) { 135 hubbub1->watermarks.a.urgent_ns = watermarks->a.urgent_ns; 136 prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns, 137 refclk_mhz, 0x1fffff); 138 REG_SET_2(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 0, 139 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value, 140 DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_A, prog_wm_value); 141 142 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_A calculated =%d\n" 143 "HW register value = 0x%x\n", 144 watermarks->a.urgent_ns, prog_wm_value); 145 } 146 147 /* determine the transfer time for a quantity of data for a particular requestor.*/ 148 if (safe_to_lower || watermarks->a.frac_urg_bw_flip 149 > hubbub1->watermarks.a.frac_urg_bw_flip) { 150 hubbub1->watermarks.a.frac_urg_bw_flip = watermarks->a.frac_urg_bw_flip; 151 152 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, 0, 153 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, watermarks->a.frac_urg_bw_flip); 154 } 155 156 if (safe_to_lower || watermarks->a.frac_urg_bw_nom 157 > hubbub1->watermarks.a.frac_urg_bw_nom) { 158 hubbub1->watermarks.a.frac_urg_bw_nom = watermarks->a.frac_urg_bw_nom; 159 160 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, 0, 161 DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, watermarks->a.frac_urg_bw_nom); 162 } 163 164 /* clock state B */ 165 if (safe_to_lower || watermarks->b.urgent_ns > hubbub1->watermarks.b.urgent_ns) { 166 hubbub1->watermarks.b.urgent_ns = watermarks->b.urgent_ns; 167 prog_wm_value = convert_and_clamp(watermarks->b.urgent_ns, 168 refclk_mhz, 0x1fffff); 169 REG_SET_2(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, 0, 170 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value, 171 DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_B, prog_wm_value); 172 173 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_B calculated =%d\n" 174 "HW register value = 0x%x\n", 175 watermarks->b.urgent_ns, prog_wm_value); 176 } 177 178 /* determine the transfer time for a quantity of data for a particular requestor.*/ 179 if (safe_to_lower || watermarks->a.frac_urg_bw_flip 180 > hubbub1->watermarks.a.frac_urg_bw_flip) { 181 hubbub1->watermarks.a.frac_urg_bw_flip = watermarks->a.frac_urg_bw_flip; 182 183 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, 0, 184 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, watermarks->a.frac_urg_bw_flip); 185 } 186 187 if (safe_to_lower || watermarks->a.frac_urg_bw_nom 188 > hubbub1->watermarks.a.frac_urg_bw_nom) { 189 hubbub1->watermarks.a.frac_urg_bw_nom = watermarks->a.frac_urg_bw_nom; 190 191 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, 0, 192 DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, watermarks->a.frac_urg_bw_nom); 193 } 194 195 /* clock state C */ 196 if (safe_to_lower || watermarks->c.urgent_ns > hubbub1->watermarks.c.urgent_ns) { 197 hubbub1->watermarks.c.urgent_ns = watermarks->c.urgent_ns; 198 prog_wm_value = convert_and_clamp(watermarks->c.urgent_ns, 199 refclk_mhz, 0x1fffff); 200 REG_SET_2(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, 0, 201 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value, 202 DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_C, prog_wm_value); 203 204 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_C calculated =%d\n" 205 "HW register value = 0x%x\n", 206 watermarks->c.urgent_ns, prog_wm_value); 207 } 208 209 /* determine the transfer time for a quantity of data for a particular requestor.*/ 210 if (safe_to_lower || watermarks->a.frac_urg_bw_flip 211 > hubbub1->watermarks.a.frac_urg_bw_flip) { 212 hubbub1->watermarks.a.frac_urg_bw_flip = watermarks->a.frac_urg_bw_flip; 213 214 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, 0, 215 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, watermarks->a.frac_urg_bw_flip); 216 } 217 218 if (safe_to_lower || watermarks->a.frac_urg_bw_nom 219 > hubbub1->watermarks.a.frac_urg_bw_nom) { 220 hubbub1->watermarks.a.frac_urg_bw_nom = watermarks->a.frac_urg_bw_nom; 221 222 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, 0, 223 DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, watermarks->a.frac_urg_bw_nom); 224 } 225 226 /* clock state D */ 227 if (safe_to_lower || watermarks->d.urgent_ns > hubbub1->watermarks.d.urgent_ns) { 228 hubbub1->watermarks.d.urgent_ns = watermarks->d.urgent_ns; 229 prog_wm_value = convert_and_clamp(watermarks->d.urgent_ns, 230 refclk_mhz, 0x1fffff); 231 REG_SET_2(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, 0, 232 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value, 233 DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_D, prog_wm_value); 234 235 DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_D calculated =%d\n" 236 "HW register value = 0x%x\n", 237 watermarks->d.urgent_ns, prog_wm_value); 238 } 239 240 /* determine the transfer time for a quantity of data for a particular requestor.*/ 241 if (safe_to_lower || watermarks->a.frac_urg_bw_flip 242 > hubbub1->watermarks.a.frac_urg_bw_flip) { 243 hubbub1->watermarks.a.frac_urg_bw_flip = watermarks->a.frac_urg_bw_flip; 244 245 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, 0, 246 DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, watermarks->a.frac_urg_bw_flip); 247 } 248 249 if (safe_to_lower || watermarks->a.frac_urg_bw_nom 250 > hubbub1->watermarks.a.frac_urg_bw_nom) { 251 hubbub1->watermarks.a.frac_urg_bw_nom = watermarks->a.frac_urg_bw_nom; 252 253 REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, 0, 254 DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, watermarks->a.frac_urg_bw_nom); 255 } 256 } 257 258 static void hubbub21_program_stutter_watermarks( 259 struct hubbub *hubbub, 260 struct dcn_watermark_set *watermarks, 261 unsigned int refclk_mhz, 262 bool safe_to_lower) 263 { 264 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub); 265 uint32_t prog_wm_value; 266 267 /* clock state A */ 268 if (safe_to_lower || watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns 269 > hubbub1->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns) { 270 hubbub1->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns = 271 watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns; 272 prog_wm_value = convert_and_clamp( 273 watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, 274 refclk_mhz, 0x1fffff); 275 REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, 0, 276 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value, 277 DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value); 278 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_A calculated =%d\n" 279 "HW register value = 0x%x\n", 280 watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); 281 } 282 283 if (safe_to_lower || watermarks->a.cstate_pstate.cstate_exit_ns 284 > hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns) { 285 hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns = 286 watermarks->a.cstate_pstate.cstate_exit_ns; 287 prog_wm_value = convert_and_clamp( 288 watermarks->a.cstate_pstate.cstate_exit_ns, 289 refclk_mhz, 0x1fffff); 290 REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, 0, 291 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value, 292 DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value); 293 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_A calculated =%d\n" 294 "HW register value = 0x%x\n", 295 watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value); 296 } 297 298 /* clock state B */ 299 if (safe_to_lower || watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns 300 > hubbub1->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns) { 301 hubbub1->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns = 302 watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns; 303 prog_wm_value = convert_and_clamp( 304 watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, 305 refclk_mhz, 0x1fffff); 306 REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, 0, 307 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value, 308 DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value); 309 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_B calculated =%d\n" 310 "HW register value = 0x%x\n", 311 watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); 312 } 313 314 if (safe_to_lower || watermarks->b.cstate_pstate.cstate_exit_ns 315 > hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns) { 316 hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns = 317 watermarks->b.cstate_pstate.cstate_exit_ns; 318 prog_wm_value = convert_and_clamp( 319 watermarks->b.cstate_pstate.cstate_exit_ns, 320 refclk_mhz, 0x1fffff); 321 REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, 0, 322 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value, 323 DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value); 324 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_B calculated =%d\n" 325 "HW register value = 0x%x\n", 326 watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value); 327 } 328 329 /* clock state C */ 330 if (safe_to_lower || watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns 331 > hubbub1->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns) { 332 hubbub1->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns = 333 watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns; 334 prog_wm_value = convert_and_clamp( 335 watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, 336 refclk_mhz, 0x1fffff); 337 REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, 0, 338 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value, 339 DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value); 340 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_C calculated =%d\n" 341 "HW register value = 0x%x\n", 342 watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); 343 } 344 345 if (safe_to_lower || watermarks->c.cstate_pstate.cstate_exit_ns 346 > hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns) { 347 hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns = 348 watermarks->c.cstate_pstate.cstate_exit_ns; 349 prog_wm_value = convert_and_clamp( 350 watermarks->c.cstate_pstate.cstate_exit_ns, 351 refclk_mhz, 0x1fffff); 352 REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, 0, 353 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value, 354 DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value); 355 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_C calculated =%d\n" 356 "HW register value = 0x%x\n", 357 watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value); 358 } 359 360 /* clock state D */ 361 if (safe_to_lower || watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns 362 > hubbub1->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns) { 363 hubbub1->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns = 364 watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns; 365 prog_wm_value = convert_and_clamp( 366 watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, 367 refclk_mhz, 0x1fffff); 368 REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, 0, 369 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value, 370 DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value); 371 DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_D calculated =%d\n" 372 "HW register value = 0x%x\n", 373 watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value); 374 } 375 376 if (safe_to_lower || watermarks->d.cstate_pstate.cstate_exit_ns 377 > hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns) { 378 hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns = 379 watermarks->d.cstate_pstate.cstate_exit_ns; 380 prog_wm_value = convert_and_clamp( 381 watermarks->d.cstate_pstate.cstate_exit_ns, 382 refclk_mhz, 0x1fffff); 383 REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, 0, 384 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value, 385 DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value); 386 DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_D calculated =%d\n" 387 "HW register value = 0x%x\n", 388 watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value); 389 } 390 } 391 392 static void hubbub21_program_pstate_watermarks( 393 struct hubbub *hubbub, 394 struct dcn_watermark_set *watermarks, 395 unsigned int refclk_mhz, 396 bool safe_to_lower) 397 { 398 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub); 399 uint32_t prog_wm_value; 400 401 /* clock state A */ 402 if (safe_to_lower || watermarks->a.cstate_pstate.pstate_change_ns 403 > hubbub1->watermarks.a.cstate_pstate.pstate_change_ns) { 404 hubbub1->watermarks.a.cstate_pstate.pstate_change_ns = 405 watermarks->a.cstate_pstate.pstate_change_ns; 406 prog_wm_value = convert_and_clamp( 407 watermarks->a.cstate_pstate.pstate_change_ns, 408 refclk_mhz, 0x1fffff); 409 REG_SET_2(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, 0, 410 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value, 411 DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value); 412 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n" 413 "HW register value = 0x%x\n\n", 414 watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value); 415 } 416 417 /* clock state B */ 418 if (safe_to_lower || watermarks->b.cstate_pstate.pstate_change_ns 419 > hubbub1->watermarks.b.cstate_pstate.pstate_change_ns) { 420 hubbub1->watermarks.b.cstate_pstate.pstate_change_ns = 421 watermarks->b.cstate_pstate.pstate_change_ns; 422 prog_wm_value = convert_and_clamp( 423 watermarks->b.cstate_pstate.pstate_change_ns, 424 refclk_mhz, 0x1fffff); 425 REG_SET_2(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, 0, 426 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value, 427 DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value); 428 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n" 429 "HW register value = 0x%x\n\n", 430 watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value); 431 } 432 433 /* clock state C */ 434 if (safe_to_lower || watermarks->c.cstate_pstate.pstate_change_ns 435 > hubbub1->watermarks.c.cstate_pstate.pstate_change_ns) { 436 hubbub1->watermarks.c.cstate_pstate.pstate_change_ns = 437 watermarks->c.cstate_pstate.pstate_change_ns; 438 prog_wm_value = convert_and_clamp( 439 watermarks->c.cstate_pstate.pstate_change_ns, 440 refclk_mhz, 0x1fffff); 441 REG_SET_2(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, 0, 442 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value, 443 DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value); 444 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n" 445 "HW register value = 0x%x\n\n", 446 watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value); 447 } 448 449 /* clock state D */ 450 if (safe_to_lower || watermarks->d.cstate_pstate.pstate_change_ns 451 > hubbub1->watermarks.d.cstate_pstate.pstate_change_ns) { 452 hubbub1->watermarks.d.cstate_pstate.pstate_change_ns = 453 watermarks->d.cstate_pstate.pstate_change_ns; 454 prog_wm_value = convert_and_clamp( 455 watermarks->d.cstate_pstate.pstate_change_ns, 456 refclk_mhz, 0x1fffff); 457 REG_SET_2(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, 0, 458 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value, 459 DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value); 460 DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n" 461 "HW register value = 0x%x\n\n", 462 watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value); 463 } 464 } 465 466 void hubbub21_program_watermarks( 467 struct hubbub *hubbub, 468 struct dcn_watermark_set *watermarks, 469 unsigned int refclk_mhz, 470 bool safe_to_lower) 471 { 472 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub); 473 474 hubbub21_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower); 475 hubbub21_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower); 476 hubbub21_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower); 477 478 /* 479 * The DCHub arbiter has a mechanism to dynamically rate limit the DCHub request stream to the fabric. 480 * If the memory controller is fully utilized and the DCHub requestors are 481 * well ahead of their amortized schedule, then it is safe to prevent the next winner 482 * from being committed and sent to the fabric. 483 * The utilization of the memory controller is approximated by ensuring that 484 * the number of outstanding requests is greater than a threshold specified 485 * by the ARB_MIN_REQ_OUTSTANDING. To determine that the DCHub requestors are well ahead of the amortized schedule, 486 * the slack of the next winner is compared with the ARB_SAT_LEVEL in DLG RefClk cycles. 487 * 488 * TODO: Revisit request limit after figure out right number. request limit for Renoir isn't decided yet, set maximum value (0x1FF) 489 * to turn off it for now. 490 */ 491 REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0, 492 DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz); 493 REG_UPDATE_2(DCHUBBUB_ARB_DF_REQ_OUTSTAND, 494 DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0x1FF, 495 DCHUBBUB_ARB_MIN_REQ_OUTSTAND_COMMIT_THRESHOLD, 0xA); 496 REG_UPDATE(DCHUBBUB_ARB_HOSTVM_CNTL, 497 DCHUBBUB_ARB_MAX_QOS_COMMIT_THRESHOLD, 0xF); 498 499 hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter); 500 } 501 502 void hubbub21_wm_read_state(struct hubbub *hubbub, 503 struct dcn_hubbub_wm *wm) 504 { 505 struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub); 506 struct dcn_hubbub_wm_set *s; 507 508 memset(wm, 0, sizeof(struct dcn_hubbub_wm)); 509 510 s = &wm->sets[0]; 511 s->wm_set = 0; 512 REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 513 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, &s->data_urgent); 514 515 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, 516 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, &s->sr_enter); 517 518 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, 519 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, &s->sr_exit); 520 521 REG_GET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, 522 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, &s->dram_clk_chanage); 523 524 s = &wm->sets[1]; 525 s->wm_set = 1; 526 REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, 527 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, &s->data_urgent); 528 529 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, 530 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, &s->sr_enter); 531 532 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, 533 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, &s->sr_exit); 534 535 REG_GET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, 536 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, &s->dram_clk_chanage); 537 538 s = &wm->sets[2]; 539 s->wm_set = 2; 540 REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, 541 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, &s->data_urgent); 542 543 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, 544 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, &s->sr_enter); 545 546 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, 547 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, &s->sr_exit); 548 549 REG_GET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, 550 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, &s->dram_clk_chanage); 551 552 s = &wm->sets[3]; 553 s->wm_set = 3; 554 REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, 555 DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, &s->data_urgent); 556 557 REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, 558 DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, &s->sr_enter); 559 560 REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, 561 DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, &s->sr_exit); 562 563 REG_GET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, 564 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, &s->dram_clk_chanage); 565 } 566 567 568 static const struct hubbub_funcs hubbub21_funcs = { 569 .update_dchub = hubbub2_update_dchub, 570 .init_dchub_sys_ctx = hubbub21_init_dchub, 571 .init_vm_ctx = NULL, 572 .dcc_support_swizzle = hubbub2_dcc_support_swizzle, 573 .dcc_support_pixel_format = hubbub2_dcc_support_pixel_format, 574 .get_dcc_compression_cap = hubbub2_get_dcc_compression_cap, 575 .wm_read_state = hubbub21_wm_read_state, 576 .get_dchub_ref_freq = hubbub2_get_dchub_ref_freq, 577 .program_watermarks = hubbub21_program_watermarks, 578 }; 579 580 void hubbub21_construct(struct dcn20_hubbub *hubbub, 581 struct dc_context *ctx, 582 const struct dcn_hubbub_registers *hubbub_regs, 583 const struct dcn_hubbub_shift *hubbub_shift, 584 const struct dcn_hubbub_mask *hubbub_mask) 585 { 586 hubbub->base.ctx = ctx; 587 588 hubbub->base.funcs = &hubbub21_funcs; 589 590 hubbub->regs = hubbub_regs; 591 hubbub->shifts = hubbub_shift; 592 hubbub->masks = hubbub_mask; 593 594 hubbub->debug_test_index_pstate = 0xB; 595 } 596