1 // SPDX-License-Identifier: MIT 2 // 3 // Copyright 2024 Advanced Micro Devices, Inc. 4 5 #include "dcn401_fpu.h" 6 #include "dcn401/dcn401_resource.h" 7 // We need this includes for WATERMARKS_* defines 8 #include "clk_mgr/dcn401/dcn401_smu14_driver_if.h" 9 #include "link.h" 10 11 #define DC_LOGGER_INIT(logger) 12 dcn401_build_wm_range_table_fpu(struct clk_mgr * clk_mgr)13void dcn401_build_wm_range_table_fpu(struct clk_mgr *clk_mgr) 14 { 15 /* defaults */ 16 double pstate_latency_us = clk_mgr->ctx->dc->dml.soc.dram_clock_change_latency_us; 17 double fclk_change_latency_us = clk_mgr->ctx->dc->dml.soc.fclk_change_latency_us; 18 double sr_exit_time_us = clk_mgr->ctx->dc->dml.soc.sr_exit_time_us; 19 double sr_enter_plus_exit_time_us = clk_mgr->ctx->dc->dml.soc.sr_enter_plus_exit_time_us; 20 /* For min clocks use as reported by PM FW and report those as min */ 21 uint16_t min_uclk_mhz = clk_mgr->bw_params->clk_table.entries[0].memclk_mhz; 22 uint16_t min_dcfclk_mhz = clk_mgr->bw_params->clk_table.entries[0].dcfclk_mhz; 23 uint16_t setb_min_uclk_mhz = min_uclk_mhz; 24 uint16_t dcfclk_mhz_for_the_second_state = clk_mgr->ctx->dc->dml.soc.clock_limits[2].dcfclk_mhz; 25 26 dc_assert_fp_enabled(); 27 28 /* For Set B ranges use min clocks state 2 when available, and report those to PM FW */ 29 if (dcfclk_mhz_for_the_second_state) 30 clk_mgr->bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.min_dcfclk = dcfclk_mhz_for_the_second_state; 31 else 32 clk_mgr->bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.min_dcfclk = clk_mgr->bw_params->clk_table.entries[0].dcfclk_mhz; 33 34 if (clk_mgr->bw_params->clk_table.entries[2].memclk_mhz) 35 setb_min_uclk_mhz = clk_mgr->bw_params->clk_table.entries[2].memclk_mhz; 36 37 /* Set A - Normal - default values */ 38 clk_mgr->bw_params->wm_table.nv_entries[WM_A].valid = true; 39 clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.pstate_latency_us = pstate_latency_us; 40 clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.fclk_change_latency_us = fclk_change_latency_us; 41 clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.sr_exit_time_us = sr_exit_time_us; 42 clk_mgr->bw_params->wm_table.nv_entries[WM_A].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us; 43 clk_mgr->bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.wm_type = WATERMARKS_CLOCK_RANGE; 44 clk_mgr->bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.min_dcfclk = min_dcfclk_mhz; 45 clk_mgr->bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.max_dcfclk = 0xFFFF; 46 clk_mgr->bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.min_uclk = min_uclk_mhz; 47 clk_mgr->bw_params->wm_table.nv_entries[WM_A].pmfw_breakdown.max_uclk = 0xFFFF; 48 49 /* Set B - Performance - higher clocks, using DPM[2] DCFCLK and UCLK */ 50 clk_mgr->bw_params->wm_table.nv_entries[WM_B].valid = true; 51 clk_mgr->bw_params->wm_table.nv_entries[WM_B].dml_input.pstate_latency_us = pstate_latency_us; 52 clk_mgr->bw_params->wm_table.nv_entries[WM_B].dml_input.fclk_change_latency_us = fclk_change_latency_us; 53 clk_mgr->bw_params->wm_table.nv_entries[WM_B].dml_input.sr_exit_time_us = sr_exit_time_us; 54 clk_mgr->bw_params->wm_table.nv_entries[WM_B].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us; 55 clk_mgr->bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.wm_type = WATERMARKS_CLOCK_RANGE; 56 clk_mgr->bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.max_dcfclk = 0xFFFF; 57 clk_mgr->bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.min_uclk = setb_min_uclk_mhz; 58 clk_mgr->bw_params->wm_table.nv_entries[WM_B].pmfw_breakdown.max_uclk = 0xFFFF; 59 60 /* Set C - Dummy P-State - P-State latency set to "dummy p-state" value */ 61 /* 'DalDummyClockChangeLatencyNs' registry key option set to 0x7FFFFFFF can be used to disable Set C for dummy p-state */ 62 if (clk_mgr->ctx->dc->bb_overrides.dummy_clock_change_latency_ns != 0x7FFFFFFF) { 63 clk_mgr->bw_params->wm_table.nv_entries[WM_C].valid = true; 64 clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.pstate_latency_us = 50; 65 clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.fclk_change_latency_us = fclk_change_latency_us; 66 clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.sr_exit_time_us = sr_exit_time_us; 67 clk_mgr->bw_params->wm_table.nv_entries[WM_C].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us; 68 clk_mgr->bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.wm_type = WATERMARKS_DUMMY_PSTATE; 69 clk_mgr->bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.min_dcfclk = min_dcfclk_mhz; 70 clk_mgr->bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.max_dcfclk = 0xFFFF; 71 clk_mgr->bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.min_uclk = min_uclk_mhz; 72 clk_mgr->bw_params->wm_table.nv_entries[WM_C].pmfw_breakdown.max_uclk = 0xFFFF; 73 clk_mgr->bw_params->dummy_pstate_table[0].dram_speed_mts = clk_mgr->bw_params->clk_table.entries[0].memclk_mhz * 16; 74 clk_mgr->bw_params->dummy_pstate_table[0].dummy_pstate_latency_us = 50; 75 clk_mgr->bw_params->dummy_pstate_table[1].dram_speed_mts = clk_mgr->bw_params->clk_table.entries[1].memclk_mhz * 16; 76 clk_mgr->bw_params->dummy_pstate_table[1].dummy_pstate_latency_us = 9; 77 clk_mgr->bw_params->dummy_pstate_table[2].dram_speed_mts = clk_mgr->bw_params->clk_table.entries[2].memclk_mhz * 16; 78 clk_mgr->bw_params->dummy_pstate_table[2].dummy_pstate_latency_us = 8; 79 clk_mgr->bw_params->dummy_pstate_table[3].dram_speed_mts = clk_mgr->bw_params->clk_table.entries[3].memclk_mhz * 16; 80 clk_mgr->bw_params->dummy_pstate_table[3].dummy_pstate_latency_us = 5; 81 } 82 /* Set D - MALL - SR enter and exit time specific to MALL, TBD after bringup or later phase for now use DRAM values / 2 */ 83 /* For MALL DRAM clock change latency is N/A, for watermak calculations use lowest value dummy P state latency */ 84 clk_mgr->bw_params->wm_table.nv_entries[WM_D].valid = true; 85 clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.pstate_latency_us = clk_mgr->bw_params->dummy_pstate_table[3].dummy_pstate_latency_us; 86 clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.fclk_change_latency_us = fclk_change_latency_us; 87 clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.sr_exit_time_us = sr_exit_time_us / 2; // TBD 88 clk_mgr->bw_params->wm_table.nv_entries[WM_D].dml_input.sr_enter_plus_exit_time_us = sr_enter_plus_exit_time_us / 2; // TBD 89 clk_mgr->bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.wm_type = WATERMARKS_MALL; 90 clk_mgr->bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.min_dcfclk = min_dcfclk_mhz; 91 clk_mgr->bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.max_dcfclk = 0xFFFF; 92 clk_mgr->bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.min_uclk = min_uclk_mhz; 93 clk_mgr->bw_params->wm_table.nv_entries[WM_D].pmfw_breakdown.max_uclk = 0xFFFF; 94 } 95 96 /* 97 * dcn401_update_bw_bounding_box 98 * 99 * This would override some dcn4_01 ip_or_soc initial parameters hardcoded from 100 * spreadsheet with actual values as per dGPU SKU: 101 * - with passed few options from dc->config 102 * - with dentist_vco_frequency from Clk Mgr (currently hardcoded, but might 103 * need to get it from PM FW) 104 * - with passed latency values (passed in ns units) in dc-> bb override for 105 * debugging purposes 106 * - with passed latencies from VBIOS (in 100_ns units) if available for 107 * certain dGPU SKU 108 * - with number of DRAM channels from VBIOS (which differ for certain dGPU SKU 109 * of the same ASIC) 110 * - clocks levels with passed clk_table entries from Clk Mgr as reported by PM 111 * FW for different clocks (which might differ for certain dGPU SKU of the 112 * same ASIC) 113 */ dcn401_update_bw_bounding_box_fpu(struct dc * dc,struct clk_bw_params * bw_params)114void dcn401_update_bw_bounding_box_fpu(struct dc *dc, struct clk_bw_params *bw_params) 115 { 116 dc_assert_fp_enabled(); 117 118 /* Override from passed dc->bb_overrides if available*/ 119 if (dc->bb_overrides.sr_exit_time_ns) 120 dc->dml2_options.bbox_overrides.sr_exit_latency_us = 121 dc->bb_overrides.sr_exit_time_ns / 1000.0; 122 123 if (dc->bb_overrides.sr_enter_plus_exit_time_ns) 124 dc->dml2_options.bbox_overrides.sr_enter_plus_exit_latency_us = 125 dc->bb_overrides.sr_enter_plus_exit_time_ns / 1000.0; 126 127 if (dc->bb_overrides.urgent_latency_ns) 128 dc->dml2_options.bbox_overrides.urgent_latency_us = 129 dc->bb_overrides.urgent_latency_ns / 1000.0; 130 131 if (dc->bb_overrides.dram_clock_change_latency_ns) 132 dc->dml2_options.bbox_overrides.dram_clock_change_latency_us = 133 dc->bb_overrides.dram_clock_change_latency_ns / 1000.0; 134 135 if (dc->bb_overrides.fclk_clock_change_latency_ns) 136 dc->dml2_options.bbox_overrides.fclk_change_latency_us = 137 dc->bb_overrides.fclk_clock_change_latency_ns / 1000; 138 139 /* Override from VBIOS if VBIOS bb_info available */ 140 if (dc->ctx->dc_bios->funcs->get_soc_bb_info) { 141 struct bp_soc_bb_info bb_info = {0}; 142 if (dc->ctx->dc_bios->funcs->get_soc_bb_info(dc->ctx->dc_bios, &bb_info) == BP_RESULT_OK) { 143 if (bb_info.dram_clock_change_latency_100ns > 0) 144 dc->dml2_options.bbox_overrides.dram_clock_change_latency_us = 145 bb_info.dram_clock_change_latency_100ns * 10; 146 147 if (bb_info.dram_sr_enter_exit_latency_100ns > 0) 148 dc->dml2_options.bbox_overrides.sr_enter_plus_exit_latency_us = 149 bb_info.dram_sr_enter_exit_latency_100ns * 10; 150 151 if (bb_info.dram_sr_exit_latency_100ns > 0) 152 dc->dml2_options.bbox_overrides.sr_exit_latency_us = 153 bb_info.dram_sr_exit_latency_100ns * 10; 154 } 155 } 156 157 /* Override from VBIOS for num_chan */ 158 if (dc->ctx->dc_bios->vram_info.num_chans) { 159 dc->dml2_options.bbox_overrides.dram_num_chan = 160 dc->ctx->dc_bios->vram_info.num_chans; 161 162 } 163 164 if (dc->ctx->dc_bios->vram_info.dram_channel_width_bytes) 165 dc->dml2_options.bbox_overrides.dram_chanel_width_bytes = 166 dc->ctx->dc_bios->vram_info.dram_channel_width_bytes; 167 168 dc->dml2_options.bbox_overrides.disp_pll_vco_speed_mhz = dc->clk_mgr->dentist_vco_freq_khz / 1000.0; 169 dc->dml2_options.bbox_overrides.xtalclk_mhz = dc->ctx->dc_bios->fw_info.pll_info.crystal_frequency / 1000.0; 170 dc->dml2_options.bbox_overrides.dchub_refclk_mhz = dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000.0; 171 dc->dml2_options.bbox_overrides.dprefclk_mhz = dc->clk_mgr->dprefclk_khz / 1000.0; 172 173 if (dc->clk_mgr->bw_params->clk_table.num_entries > 1) { 174 unsigned int i = 0; 175 176 dc->dml2_options.bbox_overrides.clks_table.num_states = dc->clk_mgr->bw_params->clk_table.num_entries; 177 178 dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dcfclk_levels = 179 dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dcfclk_levels; 180 181 dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_fclk_levels = 182 dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_fclk_levels; 183 184 dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_memclk_levels = 185 dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_memclk_levels; 186 187 dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_socclk_levels = 188 dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_socclk_levels; 189 190 dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dtbclk_levels = 191 dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dtbclk_levels; 192 193 dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dispclk_levels = 194 dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dispclk_levels; 195 196 dc->dml2_options.bbox_overrides.clks_table.num_entries_per_clk.num_dppclk_levels = 197 dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dppclk_levels; 198 199 for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dcfclk_levels; i++) { 200 if (dc->clk_mgr->bw_params->clk_table.entries[i].dcfclk_mhz) 201 dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dcfclk_mhz = 202 dc->clk_mgr->bw_params->clk_table.entries[i].dcfclk_mhz; 203 } 204 205 for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_fclk_levels; i++) { 206 if (dc->clk_mgr->bw_params->clk_table.entries[i].fclk_mhz) 207 dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].fclk_mhz = 208 dc->clk_mgr->bw_params->clk_table.entries[i].fclk_mhz; 209 } 210 211 for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_memclk_levels; i++) { 212 if (dc->clk_mgr->bw_params->clk_table.entries[i].memclk_mhz) 213 dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].memclk_mhz = 214 dc->clk_mgr->bw_params->clk_table.entries[i].memclk_mhz; 215 } 216 217 for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_socclk_levels; i++) { 218 if (dc->clk_mgr->bw_params->clk_table.entries[i].socclk_mhz) 219 dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].socclk_mhz = 220 dc->clk_mgr->bw_params->clk_table.entries[i].socclk_mhz; 221 } 222 223 for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dtbclk_levels; i++) { 224 if (dc->clk_mgr->bw_params->clk_table.entries[i].dtbclk_mhz) 225 dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dtbclk_mhz = 226 dc->clk_mgr->bw_params->clk_table.entries[i].dtbclk_mhz; 227 } 228 229 for (i = 0; i < dc->clk_mgr->bw_params->clk_table.num_entries_per_clk.num_dispclk_levels; i++) { 230 if (dc->clk_mgr->bw_params->clk_table.entries[i].dispclk_mhz) { 231 dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dispclk_mhz = 232 dc->clk_mgr->bw_params->clk_table.entries[i].dispclk_mhz; 233 dc->dml2_options.bbox_overrides.clks_table.clk_entries[i].dppclk_mhz = 234 dc->clk_mgr->bw_params->clk_table.entries[i].dispclk_mhz; 235 } 236 } 237 } 238 } 239 240