brintos

brintos / linux-shallow public Read only

0
0
Text · 40.9 KiB · 5264dc2 Raw
1033 lines · c
1/*2 * Copyright 2021 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 26 27#include "dcn30/dcn30_hubbub.h"28#include "dcn32_hubbub.h"29#include "dm_services.h"30#include "reg_helper.h"31 32 33#define CTX \34	hubbub2->base.ctx35#define DC_LOGGER \36	hubbub2->base.ctx->logger37#define REG(reg)\38	hubbub2->regs->reg39 40#undef FN41#define FN(reg_name, field_name) \42	hubbub2->shifts->field_name, hubbub2->masks->field_name43 44/**45 * DCN32_CRB_SEGMENT_SIZE_KB: Maximum Configurable Return Buffer size for46 *                            DCN3247 */48#define DCN32_CRB_SEGMENT_SIZE_KB 6449 50static void dcn32_init_crb(struct hubbub *hubbub)51{52	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);53 54	REG_GET(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT,55		&hubbub2->det0_size);56 57	REG_GET(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT,58		&hubbub2->det1_size);59 60	REG_GET(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT,61		&hubbub2->det2_size);62 63	REG_GET(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT,64		&hubbub2->det3_size);65 66	REG_GET(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE_CURRENT,67		&hubbub2->compbuf_size_segments);68 69	REG_SET_2(COMPBUF_RESERVED_SPACE, 0,70			COMPBUF_RESERVED_SPACE_64B, hubbub2->pixel_chunk_size / 32,71			COMPBUF_RESERVED_SPACE_ZS, hubbub2->pixel_chunk_size / 128);72	REG_UPDATE(DCHUBBUB_DEBUG_CTRL_0, DET_DEPTH, 0x47F);73}74 75void hubbub32_set_request_limit(struct hubbub *hubbub, int memory_channel_count, int words_per_channel)76{77	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);78 79	uint32_t request_limit = 3 * memory_channel_count * words_per_channel / 4;80 81	ASSERT((request_limit & (~0xFFF)) == 0); //field is only 24 bits long82	ASSERT(request_limit > 0); //field is only 24 bits long83 84	if (request_limit > 0xFFF)85		request_limit = 0xFFF;86 87	if (request_limit > 0)88		REG_UPDATE(SDPIF_REQUEST_RATE_LIMIT, SDPIF_REQUEST_RATE_LIMIT, request_limit);89}90 91 92void dcn32_program_det_size(struct hubbub *hubbub, int hubp_inst, unsigned int det_buffer_size_in_kbyte)93{94	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);95 96	unsigned int det_size_segments = (det_buffer_size_in_kbyte + DCN32_CRB_SEGMENT_SIZE_KB - 1) / DCN32_CRB_SEGMENT_SIZE_KB;97 98	switch (hubp_inst) {99	case 0:100		REG_UPDATE(DCHUBBUB_DET0_CTRL,101					DET0_SIZE, det_size_segments);102		hubbub2->det0_size = det_size_segments;103		break;104	case 1:105		REG_UPDATE(DCHUBBUB_DET1_CTRL,106					DET1_SIZE, det_size_segments);107		hubbub2->det1_size = det_size_segments;108		break;109	case 2:110		REG_UPDATE(DCHUBBUB_DET2_CTRL,111					DET2_SIZE, det_size_segments);112		hubbub2->det2_size = det_size_segments;113		break;114	case 3:115		REG_UPDATE(DCHUBBUB_DET3_CTRL,116					DET3_SIZE, det_size_segments);117		hubbub2->det3_size = det_size_segments;118		break;119	default:120		break;121	}122	if (hubbub2->det0_size + hubbub2->det1_size + hubbub2->det2_size123			+ hubbub2->det3_size + hubbub2->compbuf_size_segments > hubbub2->crb_size_segs) {124		/* This may happen during seamless transition from ODM 2:1 to ODM4:1 */125		DC_LOG_WARNING("CRB Config Warning: DET size (%d,%d,%d,%d) + Compbuf size (%d) >  CRB segments (%d)\n",126						hubbub2->det0_size, hubbub2->det1_size, hubbub2->det2_size, hubbub2->det3_size,127						hubbub2->compbuf_size_segments, hubbub2->crb_size_segs);128	}129}130 131void dcn32_program_compbuf_size(struct hubbub *hubbub, unsigned int compbuf_size_kb, bool safe_to_increase)132{133	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);134	unsigned int compbuf_size_segments = (compbuf_size_kb + DCN32_CRB_SEGMENT_SIZE_KB - 1) / DCN32_CRB_SEGMENT_SIZE_KB;135 136	if (safe_to_increase || compbuf_size_segments <= hubbub2->compbuf_size_segments) {137		if (compbuf_size_segments > hubbub2->compbuf_size_segments) {138			REG_WAIT(DCHUBBUB_DET0_CTRL, DET0_SIZE_CURRENT, hubbub2->det0_size, 1, 100);139			REG_WAIT(DCHUBBUB_DET1_CTRL, DET1_SIZE_CURRENT, hubbub2->det1_size, 1, 100);140			REG_WAIT(DCHUBBUB_DET2_CTRL, DET2_SIZE_CURRENT, hubbub2->det2_size, 1, 100);141			REG_WAIT(DCHUBBUB_DET3_CTRL, DET3_SIZE_CURRENT, hubbub2->det3_size, 1, 100);142		}143		/* Should never be hit, if it is we have an erroneous hw config*/144		ASSERT(hubbub2->det0_size + hubbub2->det1_size + hubbub2->det2_size145				+ hubbub2->det3_size + compbuf_size_segments <= hubbub2->crb_size_segs);146		REG_UPDATE(DCHUBBUB_COMPBUF_CTRL, COMPBUF_SIZE, compbuf_size_segments);147		hubbub2->compbuf_size_segments = compbuf_size_segments;148		ASSERT(REG_GET(DCHUBBUB_COMPBUF_CTRL, CONFIG_ERROR, &compbuf_size_segments) && !compbuf_size_segments);149	}150}151 152static uint32_t convert_and_clamp(153	uint32_t wm_ns,154	uint32_t refclk_mhz,155	uint32_t clamp_value)156{157	uint32_t ret_val = 0;158	ret_val = wm_ns * refclk_mhz;159 160	ret_val /= 1000;161 162	if (ret_val > clamp_value)163		ret_val = clamp_value;164 165	return ret_val;166}167 168bool hubbub32_program_urgent_watermarks(169		struct hubbub *hubbub,170		union dcn_watermark_set *watermarks,171		unsigned int refclk_mhz,172		bool safe_to_lower)173{174	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);175	uint32_t prog_wm_value;176	bool wm_pending = false;177 178	/* Repeat for water mark set A, B, C and D. */179	/* clock state A */180	if (safe_to_lower || watermarks->a.urgent_ns > hubbub2->watermarks.a.urgent_ns) {181		hubbub2->watermarks.a.urgent_ns = watermarks->a.urgent_ns;182		prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns,183				refclk_mhz, 0x3fff);184		REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 0,185				DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value);186 187		DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_A calculated =%d\n"188			"HW register value = 0x%x\n",189			watermarks->a.urgent_ns, prog_wm_value);190	} else if (watermarks->a.urgent_ns < hubbub2->watermarks.a.urgent_ns)191		wm_pending = true;192 193	/* determine the transfer time for a quantity of data for a particular requestor.*/194	if (safe_to_lower || watermarks->a.frac_urg_bw_flip195			> hubbub2->watermarks.a.frac_urg_bw_flip) {196		hubbub2->watermarks.a.frac_urg_bw_flip = watermarks->a.frac_urg_bw_flip;197 198		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, 0,199				DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, watermarks->a.frac_urg_bw_flip);200	} else if (watermarks->a.frac_urg_bw_flip201			< hubbub2->watermarks.a.frac_urg_bw_flip)202		wm_pending = true;203 204	if (safe_to_lower || watermarks->a.frac_urg_bw_nom205			> hubbub2->watermarks.a.frac_urg_bw_nom) {206		hubbub2->watermarks.a.frac_urg_bw_nom = watermarks->a.frac_urg_bw_nom;207 208		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, 0,209				DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, watermarks->a.frac_urg_bw_nom);210	} else if (watermarks->a.frac_urg_bw_nom211			< hubbub2->watermarks.a.frac_urg_bw_nom)212		wm_pending = true;213 214	if (safe_to_lower || watermarks->a.urgent_latency_ns > hubbub2->watermarks.a.urgent_latency_ns) {215		hubbub2->watermarks.a.urgent_latency_ns = watermarks->a.urgent_latency_ns;216		prog_wm_value = convert_and_clamp(watermarks->a.urgent_latency_ns,217				refclk_mhz, 0x3fff);218		REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, 0,219				DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, prog_wm_value);220	} else if (watermarks->a.urgent_latency_ns < hubbub2->watermarks.a.urgent_latency_ns)221		wm_pending = true;222 223	/* clock state B */224	if (safe_to_lower || watermarks->b.urgent_ns > hubbub2->watermarks.b.urgent_ns) {225		hubbub2->watermarks.b.urgent_ns = watermarks->b.urgent_ns;226		prog_wm_value = convert_and_clamp(watermarks->b.urgent_ns,227				refclk_mhz, 0x3fff);228		REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, 0,229				DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value);230 231		DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_B calculated =%d\n"232			"HW register value = 0x%x\n",233			watermarks->b.urgent_ns, prog_wm_value);234	} else if (watermarks->b.urgent_ns < hubbub2->watermarks.b.urgent_ns)235		wm_pending = true;236 237	/* determine the transfer time for a quantity of data for a particular requestor.*/238	if (safe_to_lower || watermarks->b.frac_urg_bw_flip239			> hubbub2->watermarks.b.frac_urg_bw_flip) {240		hubbub2->watermarks.b.frac_urg_bw_flip = watermarks->b.frac_urg_bw_flip;241 242		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, 0,243				DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, watermarks->b.frac_urg_bw_flip);244	} else if (watermarks->b.frac_urg_bw_flip245			< hubbub2->watermarks.b.frac_urg_bw_flip)246		wm_pending = true;247 248	if (safe_to_lower || watermarks->b.frac_urg_bw_nom249			> hubbub2->watermarks.b.frac_urg_bw_nom) {250		hubbub2->watermarks.b.frac_urg_bw_nom = watermarks->b.frac_urg_bw_nom;251 252		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, 0,253				DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, watermarks->b.frac_urg_bw_nom);254	} else if (watermarks->b.frac_urg_bw_nom255			< hubbub2->watermarks.b.frac_urg_bw_nom)256		wm_pending = true;257 258	if (safe_to_lower || watermarks->b.urgent_latency_ns > hubbub2->watermarks.b.urgent_latency_ns) {259		hubbub2->watermarks.b.urgent_latency_ns = watermarks->b.urgent_latency_ns;260		prog_wm_value = convert_and_clamp(watermarks->b.urgent_latency_ns,261				refclk_mhz, 0x3fff);262		REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, 0,263				DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, prog_wm_value);264	} else if (watermarks->b.urgent_latency_ns < hubbub2->watermarks.b.urgent_latency_ns)265		wm_pending = true;266 267	/* clock state C */268	if (safe_to_lower || watermarks->c.urgent_ns > hubbub2->watermarks.c.urgent_ns) {269		hubbub2->watermarks.c.urgent_ns = watermarks->c.urgent_ns;270		prog_wm_value = convert_and_clamp(watermarks->c.urgent_ns,271				refclk_mhz, 0x3fff);272		REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, 0,273				DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value);274 275		DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_C calculated =%d\n"276			"HW register value = 0x%x\n",277			watermarks->c.urgent_ns, prog_wm_value);278	} else if (watermarks->c.urgent_ns < hubbub2->watermarks.c.urgent_ns)279		wm_pending = true;280 281	/* determine the transfer time for a quantity of data for a particular requestor.*/282	if (safe_to_lower || watermarks->c.frac_urg_bw_flip283			> hubbub2->watermarks.c.frac_urg_bw_flip) {284		hubbub2->watermarks.c.frac_urg_bw_flip = watermarks->c.frac_urg_bw_flip;285 286		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, 0,287				DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, watermarks->c.frac_urg_bw_flip);288	} else if (watermarks->c.frac_urg_bw_flip289			< hubbub2->watermarks.c.frac_urg_bw_flip)290		wm_pending = true;291 292	if (safe_to_lower || watermarks->c.frac_urg_bw_nom293			> hubbub2->watermarks.c.frac_urg_bw_nom) {294		hubbub2->watermarks.c.frac_urg_bw_nom = watermarks->c.frac_urg_bw_nom;295 296		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, 0,297				DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, watermarks->c.frac_urg_bw_nom);298	} else if (watermarks->c.frac_urg_bw_nom299			< hubbub2->watermarks.c.frac_urg_bw_nom)300		wm_pending = true;301 302	if (safe_to_lower || watermarks->c.urgent_latency_ns > hubbub2->watermarks.c.urgent_latency_ns) {303		hubbub2->watermarks.c.urgent_latency_ns = watermarks->c.urgent_latency_ns;304		prog_wm_value = convert_and_clamp(watermarks->c.urgent_latency_ns,305				refclk_mhz, 0x3fff);306		REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, 0,307				DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, prog_wm_value);308	} else if (watermarks->c.urgent_latency_ns < hubbub2->watermarks.c.urgent_latency_ns)309		wm_pending = true;310 311	/* clock state D */312	if (safe_to_lower || watermarks->d.urgent_ns > hubbub2->watermarks.d.urgent_ns) {313		hubbub2->watermarks.d.urgent_ns = watermarks->d.urgent_ns;314		prog_wm_value = convert_and_clamp(watermarks->d.urgent_ns,315				refclk_mhz, 0x3fff);316		REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, 0,317				DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value);318 319		DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_D calculated =%d\n"320			"HW register value = 0x%x\n",321			watermarks->d.urgent_ns, prog_wm_value);322	} else if (watermarks->d.urgent_ns < hubbub2->watermarks.d.urgent_ns)323		wm_pending = true;324 325	/* determine the transfer time for a quantity of data for a particular requestor.*/326	if (safe_to_lower || watermarks->d.frac_urg_bw_flip327			> hubbub2->watermarks.d.frac_urg_bw_flip) {328		hubbub2->watermarks.d.frac_urg_bw_flip = watermarks->d.frac_urg_bw_flip;329 330		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, 0,331				DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, watermarks->d.frac_urg_bw_flip);332	} else if (watermarks->d.frac_urg_bw_flip333			< hubbub2->watermarks.d.frac_urg_bw_flip)334		wm_pending = true;335 336	if (safe_to_lower || watermarks->d.frac_urg_bw_nom337			> hubbub2->watermarks.d.frac_urg_bw_nom) {338		hubbub2->watermarks.d.frac_urg_bw_nom = watermarks->d.frac_urg_bw_nom;339 340		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, 0,341				DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, watermarks->d.frac_urg_bw_nom);342	} else if (watermarks->d.frac_urg_bw_nom343			< hubbub2->watermarks.d.frac_urg_bw_nom)344		wm_pending = true;345 346	if (safe_to_lower || watermarks->d.urgent_latency_ns > hubbub2->watermarks.d.urgent_latency_ns) {347		hubbub2->watermarks.d.urgent_latency_ns = watermarks->d.urgent_latency_ns;348		prog_wm_value = convert_and_clamp(watermarks->d.urgent_latency_ns,349				refclk_mhz, 0x3fff);350		REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, 0,351				DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, prog_wm_value);352	} else if (watermarks->d.urgent_latency_ns < hubbub2->watermarks.d.urgent_latency_ns)353		wm_pending = true;354 355	return wm_pending;356}357 358bool hubbub32_program_stutter_watermarks(359		struct hubbub *hubbub,360		union dcn_watermark_set *watermarks,361		unsigned int refclk_mhz,362		bool safe_to_lower)363{364	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);365	uint32_t prog_wm_value;366	bool wm_pending = false;367 368	/* clock state A */369	if (safe_to_lower || watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns370			> hubbub2->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns) {371		hubbub2->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns =372				watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns;373		prog_wm_value = convert_and_clamp(374				watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns,375				refclk_mhz, 0xffff);376		REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, 0,377				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value);378		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_A calculated =%d\n"379			"HW register value = 0x%x\n",380			watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);381	} else if (watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns382			< hubbub2->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns)383		wm_pending = true;384 385	if (safe_to_lower || watermarks->a.cstate_pstate.cstate_exit_ns386			> hubbub2->watermarks.a.cstate_pstate.cstate_exit_ns) {387		hubbub2->watermarks.a.cstate_pstate.cstate_exit_ns =388				watermarks->a.cstate_pstate.cstate_exit_ns;389		prog_wm_value = convert_and_clamp(390				watermarks->a.cstate_pstate.cstate_exit_ns,391				refclk_mhz, 0xffff);392		REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, 0,393				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);394		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_A calculated =%d\n"395			"HW register value = 0x%x\n",396			watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value);397	} else if (watermarks->a.cstate_pstate.cstate_exit_ns398			< hubbub2->watermarks.a.cstate_pstate.cstate_exit_ns)399		wm_pending = true;400 401	/* clock state B */402	if (safe_to_lower || watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns403			> hubbub2->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns) {404		hubbub2->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns =405				watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns;406		prog_wm_value = convert_and_clamp(407				watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns,408				refclk_mhz, 0xffff);409		REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, 0,410				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value);411		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_B calculated =%d\n"412			"HW register value = 0x%x\n",413			watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);414	} else if (watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns415			< hubbub2->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns)416		wm_pending = true;417 418	if (safe_to_lower || watermarks->b.cstate_pstate.cstate_exit_ns419			> hubbub2->watermarks.b.cstate_pstate.cstate_exit_ns) {420		hubbub2->watermarks.b.cstate_pstate.cstate_exit_ns =421				watermarks->b.cstate_pstate.cstate_exit_ns;422		prog_wm_value = convert_and_clamp(423				watermarks->b.cstate_pstate.cstate_exit_ns,424				refclk_mhz, 0xffff);425		REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, 0,426				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value);427		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_B calculated =%d\n"428			"HW register value = 0x%x\n",429			watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value);430	} else if (watermarks->b.cstate_pstate.cstate_exit_ns431			< hubbub2->watermarks.b.cstate_pstate.cstate_exit_ns)432		wm_pending = true;433 434	/* clock state C */435	if (safe_to_lower || watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns436			> hubbub2->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns) {437		hubbub2->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns =438				watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns;439		prog_wm_value = convert_and_clamp(440				watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns,441				refclk_mhz, 0xffff);442		REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, 0,443				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value);444		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_C calculated =%d\n"445			"HW register value = 0x%x\n",446			watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);447	} else if (watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns448			< hubbub2->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns)449		wm_pending = true;450 451	if (safe_to_lower || watermarks->c.cstate_pstate.cstate_exit_ns452			> hubbub2->watermarks.c.cstate_pstate.cstate_exit_ns) {453		hubbub2->watermarks.c.cstate_pstate.cstate_exit_ns =454				watermarks->c.cstate_pstate.cstate_exit_ns;455		prog_wm_value = convert_and_clamp(456				watermarks->c.cstate_pstate.cstate_exit_ns,457				refclk_mhz, 0xffff);458		REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, 0,459				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value);460		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_C calculated =%d\n"461			"HW register value = 0x%x\n",462			watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value);463	} else if (watermarks->c.cstate_pstate.cstate_exit_ns464			< hubbub2->watermarks.c.cstate_pstate.cstate_exit_ns)465		wm_pending = true;466 467	/* clock state D */468	if (safe_to_lower || watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns469			> hubbub2->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns) {470		hubbub2->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns =471				watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns;472		prog_wm_value = convert_and_clamp(473				watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns,474				refclk_mhz, 0xffff);475		REG_SET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, 0,476				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value);477		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_D calculated =%d\n"478			"HW register value = 0x%x\n",479			watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);480	} else if (watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns481			< hubbub2->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns)482		wm_pending = true;483 484	if (safe_to_lower || watermarks->d.cstate_pstate.cstate_exit_ns485			> hubbub2->watermarks.d.cstate_pstate.cstate_exit_ns) {486		hubbub2->watermarks.d.cstate_pstate.cstate_exit_ns =487				watermarks->d.cstate_pstate.cstate_exit_ns;488		prog_wm_value = convert_and_clamp(489				watermarks->d.cstate_pstate.cstate_exit_ns,490				refclk_mhz, 0xffff);491		REG_SET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, 0,492				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value);493		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_D calculated =%d\n"494			"HW register value = 0x%x\n",495			watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value);496	} else if (watermarks->d.cstate_pstate.cstate_exit_ns497			< hubbub2->watermarks.d.cstate_pstate.cstate_exit_ns)498		wm_pending = true;499 500	return wm_pending;501}502 503 504bool hubbub32_program_pstate_watermarks(505		struct hubbub *hubbub,506		union dcn_watermark_set *watermarks,507		unsigned int refclk_mhz,508		bool safe_to_lower)509{510	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);511	uint32_t prog_wm_value;512 513	bool wm_pending = false;514 515	/* Section for UCLK_PSTATE_CHANGE_WATERMARKS */516	/* clock state A */517	if (safe_to_lower || watermarks->a.cstate_pstate.pstate_change_ns518			> hubbub2->watermarks.a.cstate_pstate.pstate_change_ns) {519		hubbub2->watermarks.a.cstate_pstate.pstate_change_ns =520				watermarks->a.cstate_pstate.pstate_change_ns;521		prog_wm_value = convert_and_clamp(522				watermarks->a.cstate_pstate.pstate_change_ns,523				refclk_mhz, 0xffff);524		REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, 0,525				DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, prog_wm_value);526		DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n"527			"HW register value = 0x%x\n\n",528			watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value);529	} else if (watermarks->a.cstate_pstate.pstate_change_ns530			< hubbub2->watermarks.a.cstate_pstate.pstate_change_ns)531		wm_pending = true;532 533	/* clock state B */534	if (safe_to_lower || watermarks->b.cstate_pstate.pstate_change_ns535			> hubbub2->watermarks.b.cstate_pstate.pstate_change_ns) {536		hubbub2->watermarks.b.cstate_pstate.pstate_change_ns =537				watermarks->b.cstate_pstate.pstate_change_ns;538		prog_wm_value = convert_and_clamp(539				watermarks->b.cstate_pstate.pstate_change_ns,540				refclk_mhz, 0xffff);541		REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, 0,542				DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, prog_wm_value);543		DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n"544			"HW register value = 0x%x\n\n",545			watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value);546	} else if (watermarks->b.cstate_pstate.pstate_change_ns547			< hubbub2->watermarks.b.cstate_pstate.pstate_change_ns)548		wm_pending = true;549 550	/* clock state C */551	if (safe_to_lower || watermarks->c.cstate_pstate.pstate_change_ns552			> hubbub2->watermarks.c.cstate_pstate.pstate_change_ns) {553		hubbub2->watermarks.c.cstate_pstate.pstate_change_ns =554				watermarks->c.cstate_pstate.pstate_change_ns;555		prog_wm_value = convert_and_clamp(556				watermarks->c.cstate_pstate.pstate_change_ns,557				refclk_mhz, 0xffff);558		REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, 0,559				DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, prog_wm_value);560		DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n"561			"HW register value = 0x%x\n\n",562			watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value);563	} else if (watermarks->c.cstate_pstate.pstate_change_ns564			< hubbub2->watermarks.c.cstate_pstate.pstate_change_ns)565		wm_pending = true;566 567	/* clock state D */568	if (safe_to_lower || watermarks->d.cstate_pstate.pstate_change_ns569			> hubbub2->watermarks.d.cstate_pstate.pstate_change_ns) {570		hubbub2->watermarks.d.cstate_pstate.pstate_change_ns =571				watermarks->d.cstate_pstate.pstate_change_ns;572		prog_wm_value = convert_and_clamp(573				watermarks->d.cstate_pstate.pstate_change_ns,574				refclk_mhz, 0xffff);575		REG_SET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, 0,576				DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, prog_wm_value);577		DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n"578			"HW register value = 0x%x\n\n",579			watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value);580	} else if (watermarks->d.cstate_pstate.pstate_change_ns581			< hubbub2->watermarks.d.cstate_pstate.pstate_change_ns)582		wm_pending = true;583 584	/* Section for FCLK_PSTATE_CHANGE_WATERMARKS */585	/* clock state A */586	if (safe_to_lower || watermarks->a.cstate_pstate.fclk_pstate_change_ns587			> hubbub2->watermarks.a.cstate_pstate.fclk_pstate_change_ns) {588		hubbub2->watermarks.a.cstate_pstate.fclk_pstate_change_ns =589				watermarks->a.cstate_pstate.fclk_pstate_change_ns;590		prog_wm_value = convert_and_clamp(591				watermarks->a.cstate_pstate.fclk_pstate_change_ns,592				refclk_mhz, 0xffff);593		REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, 0,594				DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, prog_wm_value);595		DC_LOG_BANDWIDTH_CALCS("FCLK_CHANGE_WATERMARK_A calculated =%d\n"596			"HW register value = 0x%x\n\n",597			watermarks->a.cstate_pstate.fclk_pstate_change_ns, prog_wm_value);598	} else if (watermarks->a.cstate_pstate.fclk_pstate_change_ns599			< hubbub2->watermarks.a.cstate_pstate.fclk_pstate_change_ns)600		wm_pending = true;601 602	/* clock state B */603	if (safe_to_lower || watermarks->b.cstate_pstate.fclk_pstate_change_ns604			> hubbub2->watermarks.b.cstate_pstate.fclk_pstate_change_ns) {605		hubbub2->watermarks.b.cstate_pstate.fclk_pstate_change_ns =606				watermarks->b.cstate_pstate.fclk_pstate_change_ns;607		prog_wm_value = convert_and_clamp(608				watermarks->b.cstate_pstate.fclk_pstate_change_ns,609				refclk_mhz, 0xffff);610		REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, 0,611				DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, prog_wm_value);612		DC_LOG_BANDWIDTH_CALCS("FCLK_CHANGE_WATERMARK_B calculated =%d\n"613			"HW register value = 0x%x\n\n",614			watermarks->b.cstate_pstate.fclk_pstate_change_ns, prog_wm_value);615	} else if (watermarks->b.cstate_pstate.fclk_pstate_change_ns616			< hubbub2->watermarks.b.cstate_pstate.fclk_pstate_change_ns)617		wm_pending = true;618 619	/* clock state C */620	if (safe_to_lower || watermarks->c.cstate_pstate.fclk_pstate_change_ns621			> hubbub2->watermarks.c.cstate_pstate.fclk_pstate_change_ns) {622		hubbub2->watermarks.c.cstate_pstate.fclk_pstate_change_ns =623				watermarks->c.cstate_pstate.fclk_pstate_change_ns;624		prog_wm_value = convert_and_clamp(625				watermarks->c.cstate_pstate.fclk_pstate_change_ns,626				refclk_mhz, 0xffff);627		REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, 0,628				DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, prog_wm_value);629		DC_LOG_BANDWIDTH_CALCS("FCLK_CHANGE_WATERMARK_C calculated =%d\n"630			"HW register value = 0x%x\n\n",631			watermarks->c.cstate_pstate.fclk_pstate_change_ns, prog_wm_value);632	} else if (watermarks->c.cstate_pstate.fclk_pstate_change_ns633			< hubbub2->watermarks.c.cstate_pstate.fclk_pstate_change_ns)634		wm_pending = true;635 636	/* clock state D */637	if (safe_to_lower || watermarks->d.cstate_pstate.fclk_pstate_change_ns638			> hubbub2->watermarks.d.cstate_pstate.fclk_pstate_change_ns) {639		hubbub2->watermarks.d.cstate_pstate.fclk_pstate_change_ns =640				watermarks->d.cstate_pstate.fclk_pstate_change_ns;641		prog_wm_value = convert_and_clamp(642				watermarks->d.cstate_pstate.fclk_pstate_change_ns,643				refclk_mhz, 0xffff);644		REG_SET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, 0,645				DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, prog_wm_value);646		DC_LOG_BANDWIDTH_CALCS("FCLK_CHANGE_WATERMARK_D calculated =%d\n"647			"HW register value = 0x%x\n\n",648			watermarks->d.cstate_pstate.fclk_pstate_change_ns, prog_wm_value);649	} else if (watermarks->d.cstate_pstate.fclk_pstate_change_ns650			< hubbub2->watermarks.d.cstate_pstate.fclk_pstate_change_ns)651		wm_pending = true;652 653	return wm_pending;654}655 656 657bool hubbub32_program_usr_watermarks(658		struct hubbub *hubbub,659		union dcn_watermark_set *watermarks,660		unsigned int refclk_mhz,661		bool safe_to_lower)662{663	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);664	uint32_t prog_wm_value;665 666	bool wm_pending = false;667 668	/* clock state A */669	if (safe_to_lower || watermarks->a.usr_retraining_ns670			> hubbub2->watermarks.a.usr_retraining_ns) {671		hubbub2->watermarks.a.usr_retraining_ns = watermarks->a.usr_retraining_ns;672		prog_wm_value = convert_and_clamp(673				watermarks->a.usr_retraining_ns,674				refclk_mhz, 0x3fff);675		REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, 0,676				DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, prog_wm_value);677		DC_LOG_BANDWIDTH_CALCS("USR_RETRAINING_WATERMARK_A calculated =%d\n"678			"HW register value = 0x%x\n\n",679			watermarks->a.usr_retraining_ns, prog_wm_value);680	} else if (watermarks->a.usr_retraining_ns681			< hubbub2->watermarks.a.usr_retraining_ns)682		wm_pending = true;683 684	/* clock state B */685	if (safe_to_lower || watermarks->b.usr_retraining_ns686			> hubbub2->watermarks.b.usr_retraining_ns) {687		hubbub2->watermarks.b.usr_retraining_ns = watermarks->b.usr_retraining_ns;688		prog_wm_value = convert_and_clamp(689				watermarks->b.usr_retraining_ns,690				refclk_mhz, 0x3fff);691		REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, 0,692				DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, prog_wm_value);693		DC_LOG_BANDWIDTH_CALCS("USR_RETRAINING_WATERMARK_B calculated =%d\n"694			"HW register value = 0x%x\n\n",695			watermarks->b.usr_retraining_ns, prog_wm_value);696	} else if (watermarks->b.usr_retraining_ns697			< hubbub2->watermarks.b.usr_retraining_ns)698		wm_pending = true;699 700	/* clock state C */701	if (safe_to_lower || watermarks->c.usr_retraining_ns702			> hubbub2->watermarks.c.usr_retraining_ns) {703		hubbub2->watermarks.c.usr_retraining_ns =704				watermarks->c.usr_retraining_ns;705		prog_wm_value = convert_and_clamp(706				watermarks->c.usr_retraining_ns,707				refclk_mhz, 0x3fff);708		REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, 0,709				DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, prog_wm_value);710		DC_LOG_BANDWIDTH_CALCS("USR_RETRAINING_WATERMARK_C calculated =%d\n"711			"HW register value = 0x%x\n\n",712			watermarks->c.usr_retraining_ns, prog_wm_value);713	} else if (watermarks->c.usr_retraining_ns714			< hubbub2->watermarks.c.usr_retraining_ns)715		wm_pending = true;716 717	/* clock state D */718	if (safe_to_lower || watermarks->d.usr_retraining_ns719			> hubbub2->watermarks.d.usr_retraining_ns) {720		hubbub2->watermarks.d.usr_retraining_ns =721				watermarks->d.usr_retraining_ns;722		prog_wm_value = convert_and_clamp(723				watermarks->d.usr_retraining_ns,724				refclk_mhz, 0x3fff);725		REG_SET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, 0,726				DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, prog_wm_value);727		DC_LOG_BANDWIDTH_CALCS("USR_RETRAINING_WATERMARK_D calculated =%d\n"728			"HW register value = 0x%x\n\n",729			watermarks->d.usr_retraining_ns, prog_wm_value);730	} else if (watermarks->d.usr_retraining_ns731			< hubbub2->watermarks.d.usr_retraining_ns)732		wm_pending = true;733 734	return wm_pending;735}736 737void hubbub32_force_usr_retraining_allow(struct hubbub *hubbub, bool allow)738{739	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);740 741	/*742	 * DCHUBBUB_ARB_ALLOW_USR_RETRAINING_FORCE_ENABLE = 1 means enabling forcing value743	 * DCHUBBUB_ARB_ALLOW_USR_RETRAINING_FORCE_VALUE = 1 or 0,  means value to be forced when force enable744	 */745 746	REG_UPDATE_2(DCHUBBUB_ARB_USR_RETRAINING_CNTL,747			DCHUBBUB_ARB_ALLOW_USR_RETRAINING_FORCE_VALUE, allow,748			DCHUBBUB_ARB_ALLOW_USR_RETRAINING_FORCE_ENABLE, allow);749}750 751static bool hubbub32_program_watermarks(752		struct hubbub *hubbub,753		union dcn_watermark_set *watermarks,754		unsigned int refclk_mhz,755		bool safe_to_lower)756{757	bool wm_pending = false;758 759	if (hubbub32_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))760		wm_pending = true;761 762	if (hubbub32_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))763		wm_pending = true;764 765	if (hubbub32_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))766		wm_pending = true;767 768	if (hubbub32_program_usr_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower))769		wm_pending = true;770 771	/*772	 * The DCHub arbiter has a mechanism to dynamically rate limit the DCHub request stream to the fabric.773	 * If the memory controller is fully utilized and the DCHub requestors are774	 * well ahead of their amortized schedule, then it is safe to prevent the next winner775	 * from being committed and sent to the fabric.776	 * The utilization of the memory controller is approximated by ensuring that777	 * the number of outstanding requests is greater than a threshold specified778	 * by the ARB_MIN_REQ_OUTSTANDING. To determine that the DCHub requestors are well ahead of the amortized schedule,779	 * the slack of the next winner is compared with the ARB_SAT_LEVEL in DLG RefClk cycles.780	 *781	 * TODO: Revisit request limit after figure out right number. request limit for RM isn't decided yet, set maximum value (0x1FF)782	 * to turn off it for now.783	 */784	/*REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0,785			DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);786	REG_UPDATE(DCHUBBUB_ARB_DF_REQ_OUTSTAND,787			DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0x1FF);*/788 789	hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter);790 791	hubbub32_force_usr_retraining_allow(hubbub, hubbub->ctx->dc->debug.force_usr_allow);792 793	return wm_pending;794}795 796/* Copy values from WM set A to all other sets */797static void hubbub32_init_watermarks(struct hubbub *hubbub)798{799	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);800	uint32_t reg;801 802	reg = REG_READ(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A);803	REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, reg);804	REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, reg);805	REG_WRITE(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, reg);806 807	reg = REG_READ(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A);808	REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, reg);809	REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, reg);810	REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, reg);811 812	reg = REG_READ(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A);813	REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, reg);814	REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, reg);815	REG_WRITE(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, reg);816 817	reg = REG_READ(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A);818	REG_WRITE(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, reg);819	REG_WRITE(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, reg);820	REG_WRITE(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, reg);821 822	reg = REG_READ(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A);823	REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, reg);824	REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, reg);825	REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, reg);826 827	reg = REG_READ(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A);828	REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, reg);829	REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, reg);830	REG_WRITE(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, reg);831 832	reg = REG_READ(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A);833	REG_WRITE(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, reg);834	REG_WRITE(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, reg);835	REG_WRITE(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, reg);836 837	reg = REG_READ(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A);838	REG_WRITE(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, reg);839	REG_WRITE(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, reg);840	REG_WRITE(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, reg);841 842	reg = REG_READ(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A);843	REG_WRITE(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, reg);844	REG_WRITE(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, reg);845	REG_WRITE(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, reg);846}847 848static void hubbub32_wm_read_state(struct hubbub *hubbub,849		struct dcn_hubbub_wm *wm)850{851	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);852	struct dcn_hubbub_wm_set *s;853 854	memset(wm, 0, sizeof(struct dcn_hubbub_wm));855 856	s = &wm->sets[0];857	s->wm_set = 0;858	REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A,859			DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, &s->data_urgent);860 861	REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A,862			DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, &s->sr_enter);863 864	REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A,865			DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, &s->sr_exit);866 867	REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A,868			 DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_A, &s->dram_clk_change);869 870	REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A,871			 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_A, &s->usr_retrain);872 873	REG_GET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A,874			 DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_A, &s->fclk_pstate_change);875 876	s = &wm->sets[1];877	s->wm_set = 1;878	REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B,879			DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, &s->data_urgent);880 881	REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B,882			DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, &s->sr_enter);883 884	REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B,885			DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, &s->sr_exit);886 887	REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B,888			DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_B, &s->dram_clk_change);889 890	REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B,891			 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_B, &s->usr_retrain);892 893	REG_GET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B,894			DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_B, &s->fclk_pstate_change);895 896	s = &wm->sets[2];897	s->wm_set = 2;898	REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C,899			DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, &s->data_urgent);900 901	REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C,902			DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, &s->sr_enter);903 904	REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C,905			DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, &s->sr_exit);906 907	REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C,908			DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_C, &s->dram_clk_change);909 910	REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C,911			 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_C, &s->usr_retrain);912 913	REG_GET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C,914			DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_C, &s->fclk_pstate_change);915 916	s = &wm->sets[3];917	s->wm_set = 3;918	REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D,919			DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, &s->data_urgent);920 921	REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D,922			DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, &s->sr_enter);923 924	REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D,925			DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, &s->sr_exit);926 927	REG_GET(DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D,928			DCHUBBUB_ARB_UCLK_PSTATE_CHANGE_WATERMARK_D, &s->dram_clk_change);929 930	REG_GET(DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D,931			 DCHUBBUB_ARB_USR_RETRAINING_WATERMARK_D, &s->usr_retrain);932 933	REG_GET(DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D,934			DCHUBBUB_ARB_FCLK_PSTATE_CHANGE_WATERMARK_D, &s->fclk_pstate_change);935}936 937void hubbub32_force_wm_propagate_to_pipes(struct hubbub *hubbub)938{939	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);940	uint32_t refclk_mhz = hubbub->ctx->dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000;941	uint32_t prog_wm_value = convert_and_clamp(hubbub2->watermarks.a.urgent_ns,942			refclk_mhz, 0x3fff);943 944	REG_SET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 0,945			DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value);946}947 948void hubbub32_get_mall_en(struct hubbub *hubbub, unsigned int *mall_in_use)949{950	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);951	uint32_t prefetch_complete, mall_en;952 953	REG_GET_2(DCHUBBUB_ARB_MALL_CNTL, MALL_IN_USE, &mall_en,954			  MALL_PREFETCH_COMPLETE, &prefetch_complete);955 956	*mall_in_use = prefetch_complete && mall_en;957}958 959void hubbub32_init(struct hubbub *hubbub)960{961	struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);962 963	/* Enable clock gate*/964	if (hubbub->ctx->dc->debug.disable_clock_gate) {965		/*done in hwseq*/966		/*REG_UPDATE(DCFCLK_CNTL, DCFCLK_GATE_DIS, 0);*/967 968		REG_UPDATE_2(DCHUBBUB_CLOCK_CNTL,969			DISPCLK_R_DCHUBBUB_GATE_DIS, 1,970			DCFCLK_R_DCHUBBUB_GATE_DIS, 1);971	}972	/*973	ignore the "df_pre_cstate_req" from the SDP port control.974	only the DCN will determine when to connect the SDP port975	*/976	REG_UPDATE(DCHUBBUB_SDPIF_CFG0,977			SDPIF_PORT_CONTROL, 1);978	/*Set SDP's max outstanding request to 512979	must set the register back to 0 (max outstanding = 256) in zero frame buffer mode*/980	REG_UPDATE(DCHUBBUB_SDPIF_CFG1,981			SDPIF_MAX_NUM_OUTSTANDING, 1);982	/*must set the registers back to 256 in zero frame buffer mode*/983	REG_UPDATE_2(DCHUBBUB_ARB_DF_REQ_OUTSTAND,984			DCHUBBUB_ARB_MAX_REQ_OUTSTAND, 512,985			DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 512);986}987 988static const struct hubbub_funcs hubbub32_funcs = {989	.update_dchub = hubbub2_update_dchub,990	.init_dchub_sys_ctx = hubbub3_init_dchub_sys_ctx,991	.init_vm_ctx = hubbub2_init_vm_ctx,992	.dcc_support_swizzle = hubbub3_dcc_support_swizzle,993	.dcc_support_pixel_format = hubbub2_dcc_support_pixel_format,994	.get_dcc_compression_cap = hubbub3_get_dcc_compression_cap,995	.wm_read_state = hubbub32_wm_read_state,996	.get_dchub_ref_freq = hubbub2_get_dchub_ref_freq,997	.program_watermarks = hubbub32_program_watermarks,998	.allow_self_refresh_control = hubbub1_allow_self_refresh_control,999	.is_allow_self_refresh_enabled = hubbub1_is_allow_self_refresh_enabled,1000	.verify_allow_pstate_change_high = hubbub1_verify_allow_pstate_change_high,1001	.force_wm_propagate_to_pipes = hubbub32_force_wm_propagate_to_pipes,1002	.force_pstate_change_control = hubbub3_force_pstate_change_control,1003	.init_watermarks = hubbub32_init_watermarks,1004	.program_det_size = dcn32_program_det_size,1005	.program_compbuf_size = dcn32_program_compbuf_size,1006	.init_crb = dcn32_init_crb,1007	.hubbub_read_state = hubbub2_read_state,1008	.force_usr_retraining_allow = hubbub32_force_usr_retraining_allow,1009	.set_request_limit = hubbub32_set_request_limit,1010	.get_mall_en = hubbub32_get_mall_en,1011};1012 1013void hubbub32_construct(struct dcn20_hubbub *hubbub2,1014	struct dc_context *ctx,1015	const struct dcn_hubbub_registers *hubbub_regs,1016	const struct dcn_hubbub_shift *hubbub_shift,1017	const struct dcn_hubbub_mask *hubbub_mask,1018	int det_size_kb,1019	int pixel_chunk_size_kb,1020	int config_return_buffer_size_kb)1021{1022	hubbub2->base.ctx = ctx;1023	hubbub2->base.funcs = &hubbub32_funcs;1024	hubbub2->regs = hubbub_regs;1025	hubbub2->shifts = hubbub_shift;1026	hubbub2->masks = hubbub_mask;1027 1028	hubbub2->debug_test_index_pstate = 0xB;1029	hubbub2->detile_buf_size = det_size_kb * 1024;1030	hubbub2->pixel_chunk_size = pixel_chunk_size_kb * 1024;1031	hubbub2->crb_size_segs = config_return_buffer_size_kb / DCN32_CRB_SEGMENT_SIZE_KB;1032}1033