brintos

brintos / linux-shallow public Read only

0
0
Text · 28.5 KiB · 2546224 Raw
724 lines · c
1/*2* Copyright 2018 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * 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 OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: AMD23 *24 */25#include <linux/delay.h>26#include "dm_services.h"27#include "dcn20/dcn20_hubbub.h"28#include "dcn21_hubbub.h"29#include "reg_helper.h"30 31#define REG(reg)\32	hubbub1->regs->reg33#define DC_LOGGER \34	hubbub1->base.ctx->logger35#define CTX \36	hubbub1->base.ctx37 38#undef FN39#define FN(reg_name, field_name) \40	hubbub1->shifts->field_name, hubbub1->masks->field_name41 42#define REG(reg)\43	hubbub1->regs->reg44 45#define CTX \46	hubbub1->base.ctx47 48#undef FN49#define FN(reg_name, field_name) \50	hubbub1->shifts->field_name, hubbub1->masks->field_name51 52static uint32_t convert_and_clamp(53	uint32_t wm_ns,54	uint32_t refclk_mhz,55	uint32_t clamp_value)56{57	uint32_t ret_val = 0;58	ret_val = wm_ns * refclk_mhz;59	ret_val /= 1000;60 61	if (ret_val > clamp_value)62		ret_val = clamp_value;63 64	return ret_val;65}66 67void dcn21_dchvm_init(struct hubbub *hubbub)68{69	struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);70	uint32_t riommu_active;71	int i;72 73	//Init DCHVM block74	REG_UPDATE(DCHVM_CTRL0, HOSTVM_INIT_REQ, 1);75 76	//Poll until RIOMMU_ACTIVE = 177	for (i = 0; i < 100; i++) {78		REG_GET(DCHVM_RIOMMU_STAT0, RIOMMU_ACTIVE, &riommu_active);79 80		if (riommu_active)81			break;82		else83			udelay(5);84	}85 86	if (riommu_active) {87		//Reflect the power status of DCHUBBUB88		REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_POWERSTATUS, 1);89 90		//Start rIOMMU prefetching91		REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_PREFETCH_REQ, 1);92 93		// Enable dynamic clock gating94		REG_UPDATE_4(DCHVM_CLK_CTRL,95						HVM_DISPCLK_R_GATE_DIS, 0,96						HVM_DISPCLK_G_GATE_DIS, 0,97						HVM_DCFCLK_R_GATE_DIS, 0,98						HVM_DCFCLK_G_GATE_DIS, 0);99 100		//Poll until HOSTVM_PREFETCH_DONE = 1101		REG_WAIT(DCHVM_RIOMMU_STAT0, HOSTVM_PREFETCH_DONE, 1, 5, 100);102 103		hubbub->riommu_active = true;104	}105}106 107int hubbub21_init_dchub(struct hubbub *hubbub,108		struct dcn_hubbub_phys_addr_config *pa_config)109{110	struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);111	struct dcn_vmid_page_table_config phys_config;112 113	REG_SET(DCN_VM_FB_LOCATION_BASE, 0,114			FB_BASE, pa_config->system_aperture.fb_base >> 24);115	REG_SET(DCN_VM_FB_LOCATION_TOP, 0,116			FB_TOP, pa_config->system_aperture.fb_top >> 24);117	REG_SET(DCN_VM_FB_OFFSET, 0,118			FB_OFFSET, pa_config->system_aperture.fb_offset >> 24);119	REG_SET(DCN_VM_AGP_BOT, 0,120			AGP_BOT, pa_config->system_aperture.agp_bot >> 24);121	REG_SET(DCN_VM_AGP_TOP, 0,122			AGP_TOP, pa_config->system_aperture.agp_top >> 24);123	REG_SET(DCN_VM_AGP_BASE, 0,124			AGP_BASE, pa_config->system_aperture.agp_base >> 24);125 126	if (pa_config->gart_config.page_table_start_addr != pa_config->gart_config.page_table_end_addr) {127		phys_config.page_table_start_addr = pa_config->gart_config.page_table_start_addr >> 12;128		phys_config.page_table_end_addr = pa_config->gart_config.page_table_end_addr >> 12;129		phys_config.page_table_base_addr = pa_config->gart_config.page_table_base_addr | 1; //Note: hack130		phys_config.depth = 0;131		phys_config.block_size = 0;132		// Init VMID 0 based on PA config133		dcn20_vmid_setup(&hubbub1->vmid[0], &phys_config);134	}135 136	dcn21_dchvm_init(hubbub);137 138	return hubbub1->num_vmid;139}140 141bool hubbub21_program_urgent_watermarks(142		struct hubbub *hubbub,143		union dcn_watermark_set *watermarks,144		unsigned int refclk_mhz,145		bool safe_to_lower)146{147	struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);148	uint32_t prog_wm_value;149	bool wm_pending = false;150 151	/* Repeat for water mark set A, B, C and D. */152	/* clock state A */153	if (safe_to_lower || watermarks->a.urgent_ns > hubbub1->watermarks.a.urgent_ns) {154		hubbub1->watermarks.a.urgent_ns = watermarks->a.urgent_ns;155		prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns,156				refclk_mhz, 0x1fffff);157		REG_SET_2(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 0,158				DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value,159				DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_A, prog_wm_value);160 161		DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_A calculated =%d\n"162			"HW register value = 0x%x\n",163			watermarks->a.urgent_ns, prog_wm_value);164	} else if (watermarks->a.urgent_ns < hubbub1->watermarks.a.urgent_ns)165		wm_pending = true;166 167	/* determine the transfer time for a quantity of data for a particular requestor.*/168	if (safe_to_lower || watermarks->a.frac_urg_bw_flip169			> hubbub1->watermarks.a.frac_urg_bw_flip) {170		hubbub1->watermarks.a.frac_urg_bw_flip = watermarks->a.frac_urg_bw_flip;171 172		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, 0,173				DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, watermarks->a.frac_urg_bw_flip);174	} else if (watermarks->a.frac_urg_bw_flip175			< hubbub1->watermarks.a.frac_urg_bw_flip)176		wm_pending = true;177 178	if (safe_to_lower || watermarks->a.frac_urg_bw_nom179			> hubbub1->watermarks.a.frac_urg_bw_nom) {180		hubbub1->watermarks.a.frac_urg_bw_nom = watermarks->a.frac_urg_bw_nom;181 182		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, 0,183				DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, watermarks->a.frac_urg_bw_nom);184	} else if (watermarks->a.frac_urg_bw_nom185			< hubbub1->watermarks.a.frac_urg_bw_nom)186		wm_pending = true;187 188	if (safe_to_lower || watermarks->a.urgent_latency_ns > hubbub1->watermarks.a.urgent_latency_ns) {189		hubbub1->watermarks.a.urgent_latency_ns = watermarks->a.urgent_latency_ns;190		prog_wm_value = convert_and_clamp(watermarks->a.urgent_latency_ns,191				refclk_mhz, 0x1fffff);192		REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, 0,193				DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, prog_wm_value);194	} else if (watermarks->a.urgent_latency_ns < hubbub1->watermarks.a.urgent_latency_ns)195		wm_pending = true;196 197	/* clock state B */198	if (safe_to_lower || watermarks->b.urgent_ns > hubbub1->watermarks.b.urgent_ns) {199		hubbub1->watermarks.b.urgent_ns = watermarks->b.urgent_ns;200		prog_wm_value = convert_and_clamp(watermarks->b.urgent_ns,201				refclk_mhz, 0x1fffff);202		REG_SET_2(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, 0,203				DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value,204				DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_B, prog_wm_value);205 206		DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_B calculated =%d\n"207			"HW register value = 0x%x\n",208			watermarks->b.urgent_ns, prog_wm_value);209	} else if (watermarks->b.urgent_ns < hubbub1->watermarks.b.urgent_ns)210		wm_pending = true;211 212	/* determine the transfer time for a quantity of data for a particular requestor.*/213	if (safe_to_lower || watermarks->a.frac_urg_bw_flip214			> hubbub1->watermarks.a.frac_urg_bw_flip) {215		hubbub1->watermarks.a.frac_urg_bw_flip = watermarks->a.frac_urg_bw_flip;216 217		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, 0,218				DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, watermarks->a.frac_urg_bw_flip);219	} else if (watermarks->a.frac_urg_bw_flip220			< hubbub1->watermarks.a.frac_urg_bw_flip)221		wm_pending = true;222 223	if (safe_to_lower || watermarks->a.frac_urg_bw_nom224			> hubbub1->watermarks.a.frac_urg_bw_nom) {225		hubbub1->watermarks.a.frac_urg_bw_nom = watermarks->a.frac_urg_bw_nom;226 227		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, 0,228				DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, watermarks->a.frac_urg_bw_nom);229	} else if (watermarks->a.frac_urg_bw_nom230			< hubbub1->watermarks.a.frac_urg_bw_nom)231		wm_pending = true;232 233	if (safe_to_lower || watermarks->b.urgent_latency_ns > hubbub1->watermarks.b.urgent_latency_ns) {234		hubbub1->watermarks.b.urgent_latency_ns = watermarks->b.urgent_latency_ns;235		prog_wm_value = convert_and_clamp(watermarks->b.urgent_latency_ns,236				refclk_mhz, 0x1fffff);237		REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, 0,238				DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, prog_wm_value);239	} else if (watermarks->b.urgent_latency_ns < hubbub1->watermarks.b.urgent_latency_ns)240		wm_pending = true;241 242	/* clock state C */243	if (safe_to_lower || watermarks->c.urgent_ns > hubbub1->watermarks.c.urgent_ns) {244		hubbub1->watermarks.c.urgent_ns = watermarks->c.urgent_ns;245		prog_wm_value = convert_and_clamp(watermarks->c.urgent_ns,246				refclk_mhz, 0x1fffff);247		REG_SET_2(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, 0,248				DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value,249				DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_C, prog_wm_value);250 251		DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_C calculated =%d\n"252			"HW register value = 0x%x\n",253			watermarks->c.urgent_ns, prog_wm_value);254	} else if (watermarks->c.urgent_ns < hubbub1->watermarks.c.urgent_ns)255		wm_pending = true;256 257	/* determine the transfer time for a quantity of data for a particular requestor.*/258	if (safe_to_lower || watermarks->a.frac_urg_bw_flip259			> hubbub1->watermarks.a.frac_urg_bw_flip) {260		hubbub1->watermarks.a.frac_urg_bw_flip = watermarks->a.frac_urg_bw_flip;261 262		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, 0,263				DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, watermarks->a.frac_urg_bw_flip);264	} else if (watermarks->a.frac_urg_bw_flip265			< hubbub1->watermarks.a.frac_urg_bw_flip)266		wm_pending = true;267 268	if (safe_to_lower || watermarks->a.frac_urg_bw_nom269			> hubbub1->watermarks.a.frac_urg_bw_nom) {270		hubbub1->watermarks.a.frac_urg_bw_nom = watermarks->a.frac_urg_bw_nom;271 272		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, 0,273				DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, watermarks->a.frac_urg_bw_nom);274	} else if (watermarks->a.frac_urg_bw_nom275			< hubbub1->watermarks.a.frac_urg_bw_nom)276		wm_pending = true;277 278	if (safe_to_lower || watermarks->c.urgent_latency_ns > hubbub1->watermarks.c.urgent_latency_ns) {279		hubbub1->watermarks.c.urgent_latency_ns = watermarks->c.urgent_latency_ns;280		prog_wm_value = convert_and_clamp(watermarks->c.urgent_latency_ns,281				refclk_mhz, 0x1fffff);282		REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, 0,283				DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, prog_wm_value);284	} else if (watermarks->c.urgent_latency_ns < hubbub1->watermarks.c.urgent_latency_ns)285		wm_pending = true;286 287	/* clock state D */288	if (safe_to_lower || watermarks->d.urgent_ns > hubbub1->watermarks.d.urgent_ns) {289		hubbub1->watermarks.d.urgent_ns = watermarks->d.urgent_ns;290		prog_wm_value = convert_and_clamp(watermarks->d.urgent_ns,291				refclk_mhz, 0x1fffff);292		REG_SET_2(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, 0,293				DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value,294				DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_D, prog_wm_value);295 296		DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_D calculated =%d\n"297			"HW register value = 0x%x\n",298			watermarks->d.urgent_ns, prog_wm_value);299	} else if (watermarks->d.urgent_ns < hubbub1->watermarks.d.urgent_ns)300		wm_pending = true;301 302	/* determine the transfer time for a quantity of data for a particular requestor.*/303	if (safe_to_lower || watermarks->a.frac_urg_bw_flip304			> hubbub1->watermarks.a.frac_urg_bw_flip) {305		hubbub1->watermarks.a.frac_urg_bw_flip = watermarks->a.frac_urg_bw_flip;306 307		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, 0,308				DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, watermarks->a.frac_urg_bw_flip);309	} else if (watermarks->a.frac_urg_bw_flip310			< hubbub1->watermarks.a.frac_urg_bw_flip)311		wm_pending = true;312 313	if (safe_to_lower || watermarks->a.frac_urg_bw_nom314			> hubbub1->watermarks.a.frac_urg_bw_nom) {315		hubbub1->watermarks.a.frac_urg_bw_nom = watermarks->a.frac_urg_bw_nom;316 317		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, 0,318				DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, watermarks->a.frac_urg_bw_nom);319	} else if (watermarks->a.frac_urg_bw_nom320			< hubbub1->watermarks.a.frac_urg_bw_nom)321		wm_pending = true;322 323	if (safe_to_lower || watermarks->d.urgent_latency_ns > hubbub1->watermarks.d.urgent_latency_ns) {324		hubbub1->watermarks.d.urgent_latency_ns = watermarks->d.urgent_latency_ns;325		prog_wm_value = convert_and_clamp(watermarks->d.urgent_latency_ns,326				refclk_mhz, 0x1fffff);327		REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, 0,328				DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, prog_wm_value);329	} else if (watermarks->d.urgent_latency_ns < hubbub1->watermarks.d.urgent_latency_ns)330		wm_pending = true;331 332	return wm_pending;333}334 335bool hubbub21_program_stutter_watermarks(336		struct hubbub *hubbub,337		union dcn_watermark_set *watermarks,338		unsigned int refclk_mhz,339		bool safe_to_lower)340{341	struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);342	uint32_t prog_wm_value;343	bool wm_pending = false;344 345	/* clock state A */346	if (safe_to_lower || watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns347			> hubbub1->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns) {348		hubbub1->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns =349				watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns;350		prog_wm_value = convert_and_clamp(351				watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns,352				refclk_mhz, 0x1fffff);353		REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, 0,354				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value,355				DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value);356		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_A calculated =%d\n"357			"HW register value = 0x%x\n",358			watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);359	} else if (watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns360			< hubbub1->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns)361		wm_pending = true;362 363	if (safe_to_lower || watermarks->a.cstate_pstate.cstate_exit_ns364			> hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns) {365		hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns =366				watermarks->a.cstate_pstate.cstate_exit_ns;367		prog_wm_value = convert_and_clamp(368				watermarks->a.cstate_pstate.cstate_exit_ns,369				refclk_mhz, 0x1fffff);370		REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, 0,371				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value,372				DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);373		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_A calculated =%d\n"374			"HW register value = 0x%x\n",375			watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value);376	} else if (watermarks->a.cstate_pstate.cstate_exit_ns377			< hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns)378		wm_pending = true;379 380	/* clock state B */381	if (safe_to_lower || watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns382			> hubbub1->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns) {383		hubbub1->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns =384				watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns;385		prog_wm_value = convert_and_clamp(386				watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns,387				refclk_mhz, 0x1fffff);388		REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, 0,389				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value,390				DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value);391		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_B calculated =%d\n"392			"HW register value = 0x%x\n",393			watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);394	} else if (watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns395			< hubbub1->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns)396		wm_pending = true;397 398	if (safe_to_lower || watermarks->b.cstate_pstate.cstate_exit_ns399			> hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns) {400		hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns =401				watermarks->b.cstate_pstate.cstate_exit_ns;402		prog_wm_value = convert_and_clamp(403				watermarks->b.cstate_pstate.cstate_exit_ns,404				refclk_mhz, 0x1fffff);405		REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, 0,406				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value,407				DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);408		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_B calculated =%d\n"409			"HW register value = 0x%x\n",410			watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value);411	} else if (watermarks->b.cstate_pstate.cstate_exit_ns412			< hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns)413		wm_pending = true;414 415	/* clock state C */416	if (safe_to_lower || watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns417			> hubbub1->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns) {418		hubbub1->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns =419				watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns;420		prog_wm_value = convert_and_clamp(421				watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns,422				refclk_mhz, 0x1fffff);423		REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, 0,424				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value,425				DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value);426		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_C calculated =%d\n"427			"HW register value = 0x%x\n",428			watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);429	} else if (watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns430			< hubbub1->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns)431		wm_pending = true;432 433	if (safe_to_lower || watermarks->c.cstate_pstate.cstate_exit_ns434			> hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns) {435		hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns =436				watermarks->c.cstate_pstate.cstate_exit_ns;437		prog_wm_value = convert_and_clamp(438				watermarks->c.cstate_pstate.cstate_exit_ns,439				refclk_mhz, 0x1fffff);440		REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, 0,441				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value,442				DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);443		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_C calculated =%d\n"444			"HW register value = 0x%x\n",445			watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value);446	} else if (watermarks->c.cstate_pstate.cstate_exit_ns447			< hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns)448		wm_pending = true;449 450	/* clock state D */451	if (safe_to_lower || watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns452			> hubbub1->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns) {453		hubbub1->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns =454				watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns;455		prog_wm_value = convert_and_clamp(456				watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns,457				refclk_mhz, 0x1fffff);458		REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, 0,459				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value,460				DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value);461		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_D calculated =%d\n"462			"HW register value = 0x%x\n",463			watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);464	} else if (watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns465			< hubbub1->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns)466		wm_pending = true;467 468	if (safe_to_lower || watermarks->d.cstate_pstate.cstate_exit_ns469			> hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns) {470		hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns =471				watermarks->d.cstate_pstate.cstate_exit_ns;472		prog_wm_value = convert_and_clamp(473				watermarks->d.cstate_pstate.cstate_exit_ns,474				refclk_mhz, 0x1fffff);475		REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, 0,476				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value,477				DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);478		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_D calculated =%d\n"479			"HW register value = 0x%x\n",480			watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value);481	} else if (watermarks->d.cstate_pstate.cstate_exit_ns482			< hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns)483		wm_pending = true;484 485	return wm_pending;486}487 488bool hubbub21_program_pstate_watermarks(489		struct hubbub *hubbub,490		union dcn_watermark_set *watermarks,491		unsigned int refclk_mhz,492		bool safe_to_lower)493{494	struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);495	uint32_t prog_wm_value;496 497	bool wm_pending = false;498 499	/* clock state A */500	if (safe_to_lower || watermarks->a.cstate_pstate.pstate_change_ns501			> hubbub1->watermarks.a.cstate_pstate.pstate_change_ns) {502		hubbub1->watermarks.a.cstate_pstate.pstate_change_ns =503				watermarks->a.cstate_pstate.pstate_change_ns;504		prog_wm_value = convert_and_clamp(505				watermarks->a.cstate_pstate.pstate_change_ns,506				refclk_mhz, 0x1fffff);507		REG_SET_2(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, 0,508				DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value,509				DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value);510		DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n"511			"HW register value = 0x%x\n\n",512			watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value);513	} else if (watermarks->a.cstate_pstate.pstate_change_ns514			< hubbub1->watermarks.a.cstate_pstate.pstate_change_ns)515		wm_pending = true;516 517	/* clock state B */518	if (safe_to_lower || watermarks->b.cstate_pstate.pstate_change_ns519			> hubbub1->watermarks.b.cstate_pstate.pstate_change_ns) {520		hubbub1->watermarks.b.cstate_pstate.pstate_change_ns =521				watermarks->b.cstate_pstate.pstate_change_ns;522		prog_wm_value = convert_and_clamp(523				watermarks->b.cstate_pstate.pstate_change_ns,524				refclk_mhz, 0x1fffff);525		REG_SET_2(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, 0,526				DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value,527				DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value);528		DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n"529			"HW register value = 0x%x\n\n",530			watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value);531	} else if (watermarks->b.cstate_pstate.pstate_change_ns532			< hubbub1->watermarks.b.cstate_pstate.pstate_change_ns)533		wm_pending = false;534 535	/* clock state C */536	if (safe_to_lower || watermarks->c.cstate_pstate.pstate_change_ns537			> hubbub1->watermarks.c.cstate_pstate.pstate_change_ns) {538		hubbub1->watermarks.c.cstate_pstate.pstate_change_ns =539				watermarks->c.cstate_pstate.pstate_change_ns;540		prog_wm_value = convert_and_clamp(541				watermarks->c.cstate_pstate.pstate_change_ns,542				refclk_mhz, 0x1fffff);543		REG_SET_2(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, 0,544				DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value,545				DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value);546		DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n"547			"HW register value = 0x%x\n\n",548			watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value);549	} else if (watermarks->c.cstate_pstate.pstate_change_ns550			< hubbub1->watermarks.c.cstate_pstate.pstate_change_ns)551		wm_pending = true;552 553	/* clock state D */554	if (safe_to_lower || watermarks->d.cstate_pstate.pstate_change_ns555			> hubbub1->watermarks.d.cstate_pstate.pstate_change_ns) {556		hubbub1->watermarks.d.cstate_pstate.pstate_change_ns =557				watermarks->d.cstate_pstate.pstate_change_ns;558		prog_wm_value = convert_and_clamp(559				watermarks->d.cstate_pstate.pstate_change_ns,560				refclk_mhz, 0x1fffff);561		REG_SET_2(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, 0,562				DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value,563				DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value);564		DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n"565			"HW register value = 0x%x\n\n",566			watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value);567	} else if (watermarks->d.cstate_pstate.pstate_change_ns568			< hubbub1->watermarks.d.cstate_pstate.pstate_change_ns)569		wm_pending = true;570 571	return wm_pending;572}573 574bool hubbub21_program_watermarks(575		struct hubbub *hubbub,576		union dcn_watermark_set *watermarks,577		unsigned int refclk_mhz,578		bool safe_to_lower)579{580	struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);581	bool wm_pending = false;582 583	if (hubbub21_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))584		wm_pending = true;585 586	if (hubbub21_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))587		wm_pending = true;588 589	if (hubbub21_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))590		wm_pending = true;591 592	/*593	 * The DCHub arbiter has a mechanism to dynamically rate limit the DCHub request stream to the fabric.594	 * If the memory controller is fully utilized and the DCHub requestors are595	 * well ahead of their amortized schedule, then it is safe to prevent the next winner596	 * from being committed and sent to the fabric.597	 * The utilization of the memory controller is approximated by ensuring that598	 * the number of outstanding requests is greater than a threshold specified599	 * by the ARB_MIN_REQ_OUTSTANDING. To determine that the DCHub requestors are well ahead of the amortized schedule,600	 * the slack of the next winner is compared with the ARB_SAT_LEVEL in DLG RefClk cycles.601	 *602	 * TODO: Revisit request limit after figure out right number. request limit for Renoir isn't decided yet, set maximum value (0x1FF)603	 * to turn off it for now.604	 */605	REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0,606			DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);607	REG_UPDATE_2(DCHUBBUB_ARB_DF_REQ_OUTSTAND,608			DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0x1FF,609			DCHUBBUB_ARB_MIN_REQ_OUTSTAND_COMMIT_THRESHOLD, 0xA);610	REG_UPDATE(DCHUBBUB_ARB_HOSTVM_CNTL,611			DCHUBBUB_ARB_MAX_QOS_COMMIT_THRESHOLD, 0xF);612 613	hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter);614 615	return wm_pending;616}617 618void hubbub21_wm_read_state(struct hubbub *hubbub,619		struct dcn_hubbub_wm *wm)620{621	struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);622	struct dcn_hubbub_wm_set *s;623 624	memset(wm, 0, sizeof(struct dcn_hubbub_wm));625 626	s = &wm->sets[0];627	s->wm_set = 0;628	REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A,629			DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, &s->data_urgent);630 631	REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A,632			DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, &s->sr_enter);633 634	REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A,635			DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, &s->sr_exit);636 637	REG_GET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A,638			 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, &s->dram_clk_change);639 640	s = &wm->sets[1];641	s->wm_set = 1;642	REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B,643			DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, &s->data_urgent);644 645	REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B,646			DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, &s->sr_enter);647 648	REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B,649			DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, &s->sr_exit);650 651	REG_GET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B,652			DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, &s->dram_clk_change);653 654	s = &wm->sets[2];655	s->wm_set = 2;656	REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C,657			DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, &s->data_urgent);658 659	REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C,660			DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, &s->sr_enter);661 662	REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C,663			DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, &s->sr_exit);664 665	REG_GET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C,666			DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, &s->dram_clk_change);667 668	s = &wm->sets[3];669	s->wm_set = 3;670	REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D,671			DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, &s->data_urgent);672 673	REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D,674			DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, &s->sr_enter);675 676	REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D,677			DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, &s->sr_exit);678 679	REG_GET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D,680			DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, &s->dram_clk_change);681}682 683static void hubbub21_apply_DEDCN21_147_wa(struct hubbub *hubbub)684{685	struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);686	uint32_t prog_wm_value;687 688	prog_wm_value = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A);689	REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value);690}691 692static const struct hubbub_funcs hubbub21_funcs = {693	.update_dchub = hubbub2_update_dchub,694	.init_dchub_sys_ctx = hubbub21_init_dchub,695	.init_vm_ctx = hubbub2_init_vm_ctx,696	.dcc_support_swizzle = hubbub2_dcc_support_swizzle,697	.dcc_support_pixel_format = hubbub2_dcc_support_pixel_format,698	.get_dcc_compression_cap = hubbub2_get_dcc_compression_cap,699	.wm_read_state = hubbub21_wm_read_state,700	.get_dchub_ref_freq = hubbub2_get_dchub_ref_freq,701	.program_watermarks = hubbub21_program_watermarks,702	.allow_self_refresh_control = hubbub1_allow_self_refresh_control,703	.apply_DEDCN21_147_wa = hubbub21_apply_DEDCN21_147_wa,704	.hubbub_read_state = hubbub2_read_state,705};706 707void hubbub21_construct(struct dcn20_hubbub *hubbub,708	struct dc_context *ctx,709	const struct dcn_hubbub_registers *hubbub_regs,710	const struct dcn_hubbub_shift *hubbub_shift,711	const struct dcn_hubbub_mask *hubbub_mask)712{713	hubbub->base.ctx = ctx;714 715	hubbub->base.funcs = &hubbub21_funcs;716 717	hubbub->regs = hubbub_regs;718	hubbub->shifts = hubbub_shift;719	hubbub->masks = hubbub_mask;720 721	hubbub->debug_test_index_pstate = 0xB;722	hubbub->detile_buf_size = 164 * 1024; /* 164KB for DCN2.0 */723}724