16f451b60SBhawanpreet Lakha /*
26f451b60SBhawanpreet Lakha * Copyright 2018 Advanced Micro Devices, Inc.
36f451b60SBhawanpreet Lakha  *
46f451b60SBhawanpreet Lakha  * Permission is hereby granted, free of charge, to any person obtaining a
56f451b60SBhawanpreet Lakha  * copy of this software and associated documentation files (the "Software"),
66f451b60SBhawanpreet Lakha  * to deal in the Software without restriction, including without limitation
76f451b60SBhawanpreet Lakha  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
86f451b60SBhawanpreet Lakha  * and/or sell copies of the Software, and to permit persons to whom the
96f451b60SBhawanpreet Lakha  * Software is furnished to do so, subject to the following conditions:
106f451b60SBhawanpreet Lakha  *
116f451b60SBhawanpreet Lakha  * The above copyright notice and this permission notice shall be included in
126f451b60SBhawanpreet Lakha  * all copies or substantial portions of the Software.
136f451b60SBhawanpreet Lakha  *
146f451b60SBhawanpreet Lakha  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
156f451b60SBhawanpreet Lakha  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
166f451b60SBhawanpreet Lakha  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
176f451b60SBhawanpreet Lakha  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
186f451b60SBhawanpreet Lakha  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
196f451b60SBhawanpreet Lakha  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
206f451b60SBhawanpreet Lakha  * OTHER DEALINGS IN THE SOFTWARE.
216f451b60SBhawanpreet Lakha  *
226f451b60SBhawanpreet Lakha  * Authors: AMD
236f451b60SBhawanpreet Lakha  *
246f451b60SBhawanpreet Lakha  */
2548d92e8eSDmytro Laktyushkin #include <linux/delay.h>
266f451b60SBhawanpreet Lakha #include "dm_services.h"
276f451b60SBhawanpreet Lakha #include "dcn20/dcn20_hubbub.h"
286f451b60SBhawanpreet Lakha #include "dcn21_hubbub.h"
296f451b60SBhawanpreet Lakha #include "reg_helper.h"
306f451b60SBhawanpreet Lakha 
316f451b60SBhawanpreet Lakha #define REG(reg)\
326f451b60SBhawanpreet Lakha 	hubbub1->regs->reg
336f451b60SBhawanpreet Lakha #define DC_LOGGER \
346f451b60SBhawanpreet Lakha 	hubbub1->base.ctx->logger
356f451b60SBhawanpreet Lakha #define CTX \
366f451b60SBhawanpreet Lakha 	hubbub1->base.ctx
376f451b60SBhawanpreet Lakha 
386f451b60SBhawanpreet Lakha #undef FN
396f451b60SBhawanpreet Lakha #define FN(reg_name, field_name) \
406f451b60SBhawanpreet Lakha 	hubbub1->shifts->field_name, hubbub1->masks->field_name
416f451b60SBhawanpreet Lakha 
426f451b60SBhawanpreet Lakha #define REG(reg)\
436f451b60SBhawanpreet Lakha 	hubbub1->regs->reg
446f451b60SBhawanpreet Lakha 
456f451b60SBhawanpreet Lakha #define CTX \
466f451b60SBhawanpreet Lakha 	hubbub1->base.ctx
476f451b60SBhawanpreet Lakha 
486f451b60SBhawanpreet Lakha #undef FN
496f451b60SBhawanpreet Lakha #define FN(reg_name, field_name) \
506f451b60SBhawanpreet Lakha 	hubbub1->shifts->field_name, hubbub1->masks->field_name
516f451b60SBhawanpreet Lakha 
526f451b60SBhawanpreet Lakha #ifdef NUM_VMID
536f451b60SBhawanpreet Lakha #undef NUM_VMID
546f451b60SBhawanpreet Lakha #endif
556f451b60SBhawanpreet Lakha #define NUM_VMID 1
566f451b60SBhawanpreet Lakha 
576f451b60SBhawanpreet Lakha static uint32_t convert_and_clamp(
586f451b60SBhawanpreet Lakha 	uint32_t wm_ns,
596f451b60SBhawanpreet Lakha 	uint32_t refclk_mhz,
606f451b60SBhawanpreet Lakha 	uint32_t clamp_value)
616f451b60SBhawanpreet Lakha {
626f451b60SBhawanpreet Lakha 	uint32_t ret_val = 0;
636f451b60SBhawanpreet Lakha 	ret_val = wm_ns * refclk_mhz;
646f451b60SBhawanpreet Lakha 	ret_val /= 1000;
656f451b60SBhawanpreet Lakha 
666f451b60SBhawanpreet Lakha 	if (ret_val > clamp_value)
676f451b60SBhawanpreet Lakha 		ret_val = clamp_value;
686f451b60SBhawanpreet Lakha 
696f451b60SBhawanpreet Lakha 	return ret_val;
706f451b60SBhawanpreet Lakha }
716f451b60SBhawanpreet Lakha 
726f451b60SBhawanpreet Lakha void dcn21_dchvm_init(struct hubbub *hubbub)
736f451b60SBhawanpreet Lakha {
746f451b60SBhawanpreet Lakha 	struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
7548d92e8eSDmytro Laktyushkin 	uint32_t riommu_active;
7648d92e8eSDmytro Laktyushkin 	int i;
776f451b60SBhawanpreet Lakha 
786f451b60SBhawanpreet Lakha 	//Init DCHVM block
796f451b60SBhawanpreet Lakha 	REG_UPDATE(DCHVM_CTRL0, HOSTVM_INIT_REQ, 1);
806f451b60SBhawanpreet Lakha 
816f451b60SBhawanpreet Lakha 	//Poll until RIOMMU_ACTIVE = 1
8248d92e8eSDmytro Laktyushkin 	for (i = 0; i < 100; i++) {
8348d92e8eSDmytro Laktyushkin 		REG_GET(DCHVM_RIOMMU_STAT0, RIOMMU_ACTIVE, &riommu_active);
846f451b60SBhawanpreet Lakha 
8548d92e8eSDmytro Laktyushkin 		if (riommu_active)
8648d92e8eSDmytro Laktyushkin 			break;
8748d92e8eSDmytro Laktyushkin 		else
8848d92e8eSDmytro Laktyushkin 			udelay(5);
8948d92e8eSDmytro Laktyushkin 	}
9048d92e8eSDmytro Laktyushkin 
9148d92e8eSDmytro Laktyushkin 	if (riommu_active) {
926f451b60SBhawanpreet Lakha 		//Reflect the power status of DCHUBBUB
936f451b60SBhawanpreet Lakha 		REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_POWERSTATUS, 1);
946f451b60SBhawanpreet Lakha 
956f451b60SBhawanpreet Lakha 		//Start rIOMMU prefetching
966f451b60SBhawanpreet Lakha 		REG_UPDATE(DCHVM_RIOMMU_CTRL0, HOSTVM_PREFETCH_REQ, 1);
976f451b60SBhawanpreet Lakha 
986f451b60SBhawanpreet Lakha 		// Enable dynamic clock gating
996f451b60SBhawanpreet Lakha 		REG_UPDATE_4(DCHVM_CLK_CTRL,
1006f451b60SBhawanpreet Lakha 						HVM_DISPCLK_R_GATE_DIS, 0,
1016f451b60SBhawanpreet Lakha 						HVM_DISPCLK_G_GATE_DIS, 0,
1026f451b60SBhawanpreet Lakha 						HVM_DCFCLK_R_GATE_DIS, 0,
1036f451b60SBhawanpreet Lakha 						HVM_DCFCLK_G_GATE_DIS, 0);
1046f451b60SBhawanpreet Lakha 
1056f451b60SBhawanpreet Lakha 		//Poll until HOSTVM_PREFETCH_DONE = 1
1066f451b60SBhawanpreet Lakha 		REG_WAIT(DCHVM_RIOMMU_STAT0, HOSTVM_PREFETCH_DONE, 1, 5, 100);
1076f451b60SBhawanpreet Lakha 	}
10848d92e8eSDmytro Laktyushkin }
1096f451b60SBhawanpreet Lakha 
1104de094eeSBhawanpreet Lakha int hubbub21_init_dchub(struct hubbub *hubbub,
1116f451b60SBhawanpreet Lakha 		struct dcn_hubbub_phys_addr_config *pa_config)
1126f451b60SBhawanpreet Lakha {
1136f451b60SBhawanpreet Lakha 	struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
1146f451b60SBhawanpreet Lakha 
1156f451b60SBhawanpreet Lakha 	REG_SET(DCN_VM_FB_LOCATION_BASE, 0,
1166f451b60SBhawanpreet Lakha 		FB_BASE, pa_config->system_aperture.fb_base);
1176f451b60SBhawanpreet Lakha 	REG_SET(DCN_VM_FB_LOCATION_TOP, 0,
1186f451b60SBhawanpreet Lakha 			FB_TOP, pa_config->system_aperture.fb_top);
1196f451b60SBhawanpreet Lakha 	REG_SET(DCN_VM_FB_OFFSET, 0,
1206f451b60SBhawanpreet Lakha 			FB_OFFSET, pa_config->system_aperture.fb_offset);
1216f451b60SBhawanpreet Lakha 	REG_SET(DCN_VM_AGP_BOT, 0,
1226f451b60SBhawanpreet Lakha 			AGP_BOT, pa_config->system_aperture.agp_bot);
1236f451b60SBhawanpreet Lakha 	REG_SET(DCN_VM_AGP_TOP, 0,
1246f451b60SBhawanpreet Lakha 			AGP_TOP, pa_config->system_aperture.agp_top);
1256f451b60SBhawanpreet Lakha 	REG_SET(DCN_VM_AGP_BASE, 0,
1266f451b60SBhawanpreet Lakha 			AGP_BASE, pa_config->system_aperture.agp_base);
1276f451b60SBhawanpreet Lakha 
1286f451b60SBhawanpreet Lakha 	dcn21_dchvm_init(hubbub);
1296f451b60SBhawanpreet Lakha 
1306f451b60SBhawanpreet Lakha 	return NUM_VMID;
1316f451b60SBhawanpreet Lakha }
1326f451b60SBhawanpreet Lakha 
1334de094eeSBhawanpreet Lakha void hubbub21_program_urgent_watermarks(
1346f451b60SBhawanpreet Lakha 		struct hubbub *hubbub,
1356f451b60SBhawanpreet Lakha 		struct dcn_watermark_set *watermarks,
1366f451b60SBhawanpreet Lakha 		unsigned int refclk_mhz,
1376f451b60SBhawanpreet Lakha 		bool safe_to_lower)
1386f451b60SBhawanpreet Lakha {
1396f451b60SBhawanpreet Lakha 	struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
1406f451b60SBhawanpreet Lakha 	uint32_t prog_wm_value;
1416f451b60SBhawanpreet Lakha 
1426f451b60SBhawanpreet Lakha 	/* Repeat for water mark set A, B, C and D. */
1436f451b60SBhawanpreet Lakha 	/* clock state A */
1446f451b60SBhawanpreet Lakha 	if (safe_to_lower || watermarks->a.urgent_ns > hubbub1->watermarks.a.urgent_ns) {
1456f451b60SBhawanpreet Lakha 		hubbub1->watermarks.a.urgent_ns = watermarks->a.urgent_ns;
1466f451b60SBhawanpreet Lakha 		prog_wm_value = convert_and_clamp(watermarks->a.urgent_ns,
1476f451b60SBhawanpreet Lakha 				refclk_mhz, 0x1fffff);
1486f451b60SBhawanpreet Lakha 		REG_SET_2(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, 0,
1496f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, prog_wm_value,
1506f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_A, prog_wm_value);
1516f451b60SBhawanpreet Lakha 
1526f451b60SBhawanpreet Lakha 		DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_A calculated =%d\n"
1536f451b60SBhawanpreet Lakha 			"HW register value = 0x%x\n",
1546f451b60SBhawanpreet Lakha 			watermarks->a.urgent_ns, prog_wm_value);
1556f451b60SBhawanpreet Lakha 	}
1566f451b60SBhawanpreet Lakha 
1576f451b60SBhawanpreet Lakha 	/* determine the transfer time for a quantity of data for a particular requestor.*/
1586f451b60SBhawanpreet Lakha 	if (safe_to_lower || watermarks->a.frac_urg_bw_flip
1596f451b60SBhawanpreet Lakha 			> hubbub1->watermarks.a.frac_urg_bw_flip) {
1606f451b60SBhawanpreet Lakha 		hubbub1->watermarks.a.frac_urg_bw_flip = watermarks->a.frac_urg_bw_flip;
1616f451b60SBhawanpreet Lakha 
1626f451b60SBhawanpreet Lakha 		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, 0,
1636f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_FRAC_URG_BW_FLIP_A, watermarks->a.frac_urg_bw_flip);
1646f451b60SBhawanpreet Lakha 	}
1656f451b60SBhawanpreet Lakha 
1666f451b60SBhawanpreet Lakha 	if (safe_to_lower || watermarks->a.frac_urg_bw_nom
1676f451b60SBhawanpreet Lakha 			> hubbub1->watermarks.a.frac_urg_bw_nom) {
1686f451b60SBhawanpreet Lakha 		hubbub1->watermarks.a.frac_urg_bw_nom = watermarks->a.frac_urg_bw_nom;
1696f451b60SBhawanpreet Lakha 
1706f451b60SBhawanpreet Lakha 		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, 0,
1716f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_FRAC_URG_BW_NOM_A, watermarks->a.frac_urg_bw_nom);
1726f451b60SBhawanpreet Lakha 	}
1734de094eeSBhawanpreet Lakha 	if (safe_to_lower || watermarks->a.urgent_latency_ns > hubbub1->watermarks.a.urgent_latency_ns) {
1744de094eeSBhawanpreet Lakha 		hubbub1->watermarks.a.urgent_latency_ns = watermarks->a.urgent_latency_ns;
1754de094eeSBhawanpreet Lakha 		prog_wm_value = convert_and_clamp(watermarks->a.urgent_latency_ns,
1764de094eeSBhawanpreet Lakha 				refclk_mhz, 0x1fffff);
1774de094eeSBhawanpreet Lakha 		REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, 0,
1784de094eeSBhawanpreet Lakha 				DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_A, prog_wm_value);
1794de094eeSBhawanpreet Lakha 	}
1806f451b60SBhawanpreet Lakha 
1816f451b60SBhawanpreet Lakha 	/* clock state B */
1826f451b60SBhawanpreet Lakha 	if (safe_to_lower || watermarks->b.urgent_ns > hubbub1->watermarks.b.urgent_ns) {
1836f451b60SBhawanpreet Lakha 		hubbub1->watermarks.b.urgent_ns = watermarks->b.urgent_ns;
1846f451b60SBhawanpreet Lakha 		prog_wm_value = convert_and_clamp(watermarks->b.urgent_ns,
1856f451b60SBhawanpreet Lakha 				refclk_mhz, 0x1fffff);
1866f451b60SBhawanpreet Lakha 		REG_SET_2(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, 0,
1876f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, prog_wm_value,
1886f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_B, prog_wm_value);
1896f451b60SBhawanpreet Lakha 
1906f451b60SBhawanpreet Lakha 		DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_B calculated =%d\n"
1916f451b60SBhawanpreet Lakha 			"HW register value = 0x%x\n",
1926f451b60SBhawanpreet Lakha 			watermarks->b.urgent_ns, prog_wm_value);
1936f451b60SBhawanpreet Lakha 	}
1946f451b60SBhawanpreet Lakha 
1956f451b60SBhawanpreet Lakha 	/* determine the transfer time for a quantity of data for a particular requestor.*/
1966f451b60SBhawanpreet Lakha 	if (safe_to_lower || watermarks->a.frac_urg_bw_flip
1976f451b60SBhawanpreet Lakha 			> hubbub1->watermarks.a.frac_urg_bw_flip) {
1986f451b60SBhawanpreet Lakha 		hubbub1->watermarks.a.frac_urg_bw_flip = watermarks->a.frac_urg_bw_flip;
1996f451b60SBhawanpreet Lakha 
2006f451b60SBhawanpreet Lakha 		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, 0,
2016f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_FRAC_URG_BW_FLIP_B, watermarks->a.frac_urg_bw_flip);
2026f451b60SBhawanpreet Lakha 	}
2036f451b60SBhawanpreet Lakha 
2046f451b60SBhawanpreet Lakha 	if (safe_to_lower || watermarks->a.frac_urg_bw_nom
2056f451b60SBhawanpreet Lakha 			> hubbub1->watermarks.a.frac_urg_bw_nom) {
2066f451b60SBhawanpreet Lakha 		hubbub1->watermarks.a.frac_urg_bw_nom = watermarks->a.frac_urg_bw_nom;
2076f451b60SBhawanpreet Lakha 
2086f451b60SBhawanpreet Lakha 		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, 0,
2096f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_FRAC_URG_BW_NOM_B, watermarks->a.frac_urg_bw_nom);
2106f451b60SBhawanpreet Lakha 	}
2116f451b60SBhawanpreet Lakha 
2124de094eeSBhawanpreet Lakha 	if (safe_to_lower || watermarks->b.urgent_latency_ns > hubbub1->watermarks.b.urgent_latency_ns) {
2134de094eeSBhawanpreet Lakha 		hubbub1->watermarks.b.urgent_latency_ns = watermarks->b.urgent_latency_ns;
2144de094eeSBhawanpreet Lakha 		prog_wm_value = convert_and_clamp(watermarks->b.urgent_latency_ns,
2154de094eeSBhawanpreet Lakha 				refclk_mhz, 0x1fffff);
2164de094eeSBhawanpreet Lakha 		REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, 0,
2174de094eeSBhawanpreet Lakha 				DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_B, prog_wm_value);
2184de094eeSBhawanpreet Lakha 	}
2194de094eeSBhawanpreet Lakha 
2206f451b60SBhawanpreet Lakha 	/* clock state C */
2216f451b60SBhawanpreet Lakha 	if (safe_to_lower || watermarks->c.urgent_ns > hubbub1->watermarks.c.urgent_ns) {
2226f451b60SBhawanpreet Lakha 		hubbub1->watermarks.c.urgent_ns = watermarks->c.urgent_ns;
2236f451b60SBhawanpreet Lakha 		prog_wm_value = convert_and_clamp(watermarks->c.urgent_ns,
2246f451b60SBhawanpreet Lakha 				refclk_mhz, 0x1fffff);
2256f451b60SBhawanpreet Lakha 		REG_SET_2(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, 0,
2266f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, prog_wm_value,
2276f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_C, prog_wm_value);
2286f451b60SBhawanpreet Lakha 
2296f451b60SBhawanpreet Lakha 		DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_C calculated =%d\n"
2306f451b60SBhawanpreet Lakha 			"HW register value = 0x%x\n",
2316f451b60SBhawanpreet Lakha 			watermarks->c.urgent_ns, prog_wm_value);
2326f451b60SBhawanpreet Lakha 	}
2336f451b60SBhawanpreet Lakha 
2346f451b60SBhawanpreet Lakha 	/* determine the transfer time for a quantity of data for a particular requestor.*/
2356f451b60SBhawanpreet Lakha 	if (safe_to_lower || watermarks->a.frac_urg_bw_flip
2366f451b60SBhawanpreet Lakha 			> hubbub1->watermarks.a.frac_urg_bw_flip) {
2376f451b60SBhawanpreet Lakha 		hubbub1->watermarks.a.frac_urg_bw_flip = watermarks->a.frac_urg_bw_flip;
2386f451b60SBhawanpreet Lakha 
2396f451b60SBhawanpreet Lakha 		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, 0,
2406f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_FRAC_URG_BW_FLIP_C, watermarks->a.frac_urg_bw_flip);
2416f451b60SBhawanpreet Lakha 	}
2426f451b60SBhawanpreet Lakha 
2436f451b60SBhawanpreet Lakha 	if (safe_to_lower || watermarks->a.frac_urg_bw_nom
2446f451b60SBhawanpreet Lakha 			> hubbub1->watermarks.a.frac_urg_bw_nom) {
2456f451b60SBhawanpreet Lakha 		hubbub1->watermarks.a.frac_urg_bw_nom = watermarks->a.frac_urg_bw_nom;
2466f451b60SBhawanpreet Lakha 
2476f451b60SBhawanpreet Lakha 		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, 0,
2486f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_FRAC_URG_BW_NOM_C, watermarks->a.frac_urg_bw_nom);
2496f451b60SBhawanpreet Lakha 	}
2506f451b60SBhawanpreet Lakha 
2514de094eeSBhawanpreet Lakha 	if (safe_to_lower || watermarks->c.urgent_latency_ns > hubbub1->watermarks.c.urgent_latency_ns) {
2524de094eeSBhawanpreet Lakha 		hubbub1->watermarks.c.urgent_latency_ns = watermarks->c.urgent_latency_ns;
2534de094eeSBhawanpreet Lakha 		prog_wm_value = convert_and_clamp(watermarks->c.urgent_latency_ns,
2544de094eeSBhawanpreet Lakha 				refclk_mhz, 0x1fffff);
2554de094eeSBhawanpreet Lakha 		REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, 0,
2564de094eeSBhawanpreet Lakha 				DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_C, prog_wm_value);
2574de094eeSBhawanpreet Lakha 	}
2584de094eeSBhawanpreet Lakha 
2596f451b60SBhawanpreet Lakha 	/* clock state D */
2606f451b60SBhawanpreet Lakha 	if (safe_to_lower || watermarks->d.urgent_ns > hubbub1->watermarks.d.urgent_ns) {
2616f451b60SBhawanpreet Lakha 		hubbub1->watermarks.d.urgent_ns = watermarks->d.urgent_ns;
2626f451b60SBhawanpreet Lakha 		prog_wm_value = convert_and_clamp(watermarks->d.urgent_ns,
2636f451b60SBhawanpreet Lakha 				refclk_mhz, 0x1fffff);
2646f451b60SBhawanpreet Lakha 		REG_SET_2(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, 0,
2656f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, prog_wm_value,
2666f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_VM_ROW_URGENCY_WATERMARK_D, prog_wm_value);
2676f451b60SBhawanpreet Lakha 
2686f451b60SBhawanpreet Lakha 		DC_LOG_BANDWIDTH_CALCS("URGENCY_WATERMARK_D calculated =%d\n"
2696f451b60SBhawanpreet Lakha 			"HW register value = 0x%x\n",
2706f451b60SBhawanpreet Lakha 			watermarks->d.urgent_ns, prog_wm_value);
2716f451b60SBhawanpreet Lakha 	}
2726f451b60SBhawanpreet Lakha 
2736f451b60SBhawanpreet Lakha 	/* determine the transfer time for a quantity of data for a particular requestor.*/
2746f451b60SBhawanpreet Lakha 	if (safe_to_lower || watermarks->a.frac_urg_bw_flip
2756f451b60SBhawanpreet Lakha 			> hubbub1->watermarks.a.frac_urg_bw_flip) {
2766f451b60SBhawanpreet Lakha 		hubbub1->watermarks.a.frac_urg_bw_flip = watermarks->a.frac_urg_bw_flip;
2776f451b60SBhawanpreet Lakha 
2786f451b60SBhawanpreet Lakha 		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, 0,
2796f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_FRAC_URG_BW_FLIP_D, watermarks->a.frac_urg_bw_flip);
2806f451b60SBhawanpreet Lakha 	}
2816f451b60SBhawanpreet Lakha 
2826f451b60SBhawanpreet Lakha 	if (safe_to_lower || watermarks->a.frac_urg_bw_nom
2836f451b60SBhawanpreet Lakha 			> hubbub1->watermarks.a.frac_urg_bw_nom) {
2846f451b60SBhawanpreet Lakha 		hubbub1->watermarks.a.frac_urg_bw_nom = watermarks->a.frac_urg_bw_nom;
2856f451b60SBhawanpreet Lakha 
2866f451b60SBhawanpreet Lakha 		REG_SET(DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, 0,
2876f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_FRAC_URG_BW_NOM_D, watermarks->a.frac_urg_bw_nom);
2886f451b60SBhawanpreet Lakha 	}
2894de094eeSBhawanpreet Lakha 
2904de094eeSBhawanpreet Lakha 	if (safe_to_lower || watermarks->d.urgent_latency_ns > hubbub1->watermarks.d.urgent_latency_ns) {
2914de094eeSBhawanpreet Lakha 		hubbub1->watermarks.d.urgent_latency_ns = watermarks->d.urgent_latency_ns;
2924de094eeSBhawanpreet Lakha 		prog_wm_value = convert_and_clamp(watermarks->d.urgent_latency_ns,
2934de094eeSBhawanpreet Lakha 				refclk_mhz, 0x1fffff);
2944de094eeSBhawanpreet Lakha 		REG_SET(DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, 0,
2954de094eeSBhawanpreet Lakha 				DCHUBBUB_ARB_REFCYC_PER_TRIP_TO_MEMORY_D, prog_wm_value);
2964de094eeSBhawanpreet Lakha 	}
2976f451b60SBhawanpreet Lakha }
2986f451b60SBhawanpreet Lakha 
2994de094eeSBhawanpreet Lakha void hubbub21_program_stutter_watermarks(
3006f451b60SBhawanpreet Lakha 		struct hubbub *hubbub,
3016f451b60SBhawanpreet Lakha 		struct dcn_watermark_set *watermarks,
3026f451b60SBhawanpreet Lakha 		unsigned int refclk_mhz,
3036f451b60SBhawanpreet Lakha 		bool safe_to_lower)
3046f451b60SBhawanpreet Lakha {
3056f451b60SBhawanpreet Lakha 	struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
3066f451b60SBhawanpreet Lakha 	uint32_t prog_wm_value;
3076f451b60SBhawanpreet Lakha 
3086f451b60SBhawanpreet Lakha 	/* clock state A */
3096f451b60SBhawanpreet Lakha 	if (safe_to_lower || watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns
3106f451b60SBhawanpreet Lakha 			> hubbub1->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns) {
3116f451b60SBhawanpreet Lakha 		hubbub1->watermarks.a.cstate_pstate.cstate_enter_plus_exit_ns =
3126f451b60SBhawanpreet Lakha 				watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns;
3136f451b60SBhawanpreet Lakha 		prog_wm_value = convert_and_clamp(
3146f451b60SBhawanpreet Lakha 				watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns,
3156f451b60SBhawanpreet Lakha 				refclk_mhz, 0x1fffff);
3166f451b60SBhawanpreet Lakha 		REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, 0,
3176f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value,
3186f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_A, prog_wm_value);
3196f451b60SBhawanpreet Lakha 		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_A calculated =%d\n"
3206f451b60SBhawanpreet Lakha 			"HW register value = 0x%x\n",
3216f451b60SBhawanpreet Lakha 			watermarks->a.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
3226f451b60SBhawanpreet Lakha 	}
3236f451b60SBhawanpreet Lakha 
3246f451b60SBhawanpreet Lakha 	if (safe_to_lower || watermarks->a.cstate_pstate.cstate_exit_ns
3256f451b60SBhawanpreet Lakha 			> hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns) {
3266f451b60SBhawanpreet Lakha 		hubbub1->watermarks.a.cstate_pstate.cstate_exit_ns =
3276f451b60SBhawanpreet Lakha 				watermarks->a.cstate_pstate.cstate_exit_ns;
3286f451b60SBhawanpreet Lakha 		prog_wm_value = convert_and_clamp(
3296f451b60SBhawanpreet Lakha 				watermarks->a.cstate_pstate.cstate_exit_ns,
3306f451b60SBhawanpreet Lakha 				refclk_mhz, 0x1fffff);
3316f451b60SBhawanpreet Lakha 		REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, 0,
3326f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value,
3336f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);
3346f451b60SBhawanpreet Lakha 		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_A calculated =%d\n"
3356f451b60SBhawanpreet Lakha 			"HW register value = 0x%x\n",
3366f451b60SBhawanpreet Lakha 			watermarks->a.cstate_pstate.cstate_exit_ns, prog_wm_value);
3376f451b60SBhawanpreet Lakha 	}
3386f451b60SBhawanpreet Lakha 
3396f451b60SBhawanpreet Lakha 	/* clock state B */
3406f451b60SBhawanpreet Lakha 	if (safe_to_lower || watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns
3416f451b60SBhawanpreet Lakha 			> hubbub1->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns) {
3426f451b60SBhawanpreet Lakha 		hubbub1->watermarks.b.cstate_pstate.cstate_enter_plus_exit_ns =
3436f451b60SBhawanpreet Lakha 				watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns;
3446f451b60SBhawanpreet Lakha 		prog_wm_value = convert_and_clamp(
3456f451b60SBhawanpreet Lakha 				watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns,
3466f451b60SBhawanpreet Lakha 				refclk_mhz, 0x1fffff);
3476f451b60SBhawanpreet Lakha 		REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, 0,
3486f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value,
3496f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_B, prog_wm_value);
3506f451b60SBhawanpreet Lakha 		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_B calculated =%d\n"
3516f451b60SBhawanpreet Lakha 			"HW register value = 0x%x\n",
3526f451b60SBhawanpreet Lakha 			watermarks->b.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
3536f451b60SBhawanpreet Lakha 	}
3546f451b60SBhawanpreet Lakha 
3556f451b60SBhawanpreet Lakha 	if (safe_to_lower || watermarks->b.cstate_pstate.cstate_exit_ns
3566f451b60SBhawanpreet Lakha 			> hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns) {
3576f451b60SBhawanpreet Lakha 		hubbub1->watermarks.b.cstate_pstate.cstate_exit_ns =
3586f451b60SBhawanpreet Lakha 				watermarks->b.cstate_pstate.cstate_exit_ns;
3596f451b60SBhawanpreet Lakha 		prog_wm_value = convert_and_clamp(
3606f451b60SBhawanpreet Lakha 				watermarks->b.cstate_pstate.cstate_exit_ns,
3616f451b60SBhawanpreet Lakha 				refclk_mhz, 0x1fffff);
3626f451b60SBhawanpreet Lakha 		REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, 0,
3636f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, prog_wm_value,
3646f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);
3656f451b60SBhawanpreet Lakha 		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_B calculated =%d\n"
3666f451b60SBhawanpreet Lakha 			"HW register value = 0x%x\n",
3676f451b60SBhawanpreet Lakha 			watermarks->b.cstate_pstate.cstate_exit_ns, prog_wm_value);
3686f451b60SBhawanpreet Lakha 	}
3696f451b60SBhawanpreet Lakha 
3706f451b60SBhawanpreet Lakha 	/* clock state C */
3716f451b60SBhawanpreet Lakha 	if (safe_to_lower || watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns
3726f451b60SBhawanpreet Lakha 			> hubbub1->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns) {
3736f451b60SBhawanpreet Lakha 		hubbub1->watermarks.c.cstate_pstate.cstate_enter_plus_exit_ns =
3746f451b60SBhawanpreet Lakha 				watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns;
3756f451b60SBhawanpreet Lakha 		prog_wm_value = convert_and_clamp(
3766f451b60SBhawanpreet Lakha 				watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns,
3776f451b60SBhawanpreet Lakha 				refclk_mhz, 0x1fffff);
3786f451b60SBhawanpreet Lakha 		REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, 0,
3796f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value,
3806f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_C, prog_wm_value);
3816f451b60SBhawanpreet Lakha 		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_C calculated =%d\n"
3826f451b60SBhawanpreet Lakha 			"HW register value = 0x%x\n",
3836f451b60SBhawanpreet Lakha 			watermarks->c.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
3846f451b60SBhawanpreet Lakha 	}
3856f451b60SBhawanpreet Lakha 
3866f451b60SBhawanpreet Lakha 	if (safe_to_lower || watermarks->c.cstate_pstate.cstate_exit_ns
3876f451b60SBhawanpreet Lakha 			> hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns) {
3886f451b60SBhawanpreet Lakha 		hubbub1->watermarks.c.cstate_pstate.cstate_exit_ns =
3896f451b60SBhawanpreet Lakha 				watermarks->c.cstate_pstate.cstate_exit_ns;
3906f451b60SBhawanpreet Lakha 		prog_wm_value = convert_and_clamp(
3916f451b60SBhawanpreet Lakha 				watermarks->c.cstate_pstate.cstate_exit_ns,
3926f451b60SBhawanpreet Lakha 				refclk_mhz, 0x1fffff);
3936f451b60SBhawanpreet Lakha 		REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, 0,
3946f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, prog_wm_value,
3956f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);
3966f451b60SBhawanpreet Lakha 		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_C calculated =%d\n"
3976f451b60SBhawanpreet Lakha 			"HW register value = 0x%x\n",
3986f451b60SBhawanpreet Lakha 			watermarks->c.cstate_pstate.cstate_exit_ns, prog_wm_value);
3996f451b60SBhawanpreet Lakha 	}
4006f451b60SBhawanpreet Lakha 
4016f451b60SBhawanpreet Lakha 	/* clock state D */
4026f451b60SBhawanpreet Lakha 	if (safe_to_lower || watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns
4036f451b60SBhawanpreet Lakha 			> hubbub1->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns) {
4046f451b60SBhawanpreet Lakha 		hubbub1->watermarks.d.cstate_pstate.cstate_enter_plus_exit_ns =
4056f451b60SBhawanpreet Lakha 				watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns;
4066f451b60SBhawanpreet Lakha 		prog_wm_value = convert_and_clamp(
4076f451b60SBhawanpreet Lakha 				watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns,
4086f451b60SBhawanpreet Lakha 				refclk_mhz, 0x1fffff);
4096f451b60SBhawanpreet Lakha 		REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, 0,
4106f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value,
4116f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_VM_ROW_ALLOW_SR_ENTER_WATERMARK_D, prog_wm_value);
4126f451b60SBhawanpreet Lakha 		DC_LOG_BANDWIDTH_CALCS("SR_ENTER_EXIT_WATERMARK_D calculated =%d\n"
4136f451b60SBhawanpreet Lakha 			"HW register value = 0x%x\n",
4146f451b60SBhawanpreet Lakha 			watermarks->d.cstate_pstate.cstate_enter_plus_exit_ns, prog_wm_value);
4156f451b60SBhawanpreet Lakha 	}
4166f451b60SBhawanpreet Lakha 
4176f451b60SBhawanpreet Lakha 	if (safe_to_lower || watermarks->d.cstate_pstate.cstate_exit_ns
4186f451b60SBhawanpreet Lakha 			> hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns) {
4196f451b60SBhawanpreet Lakha 		hubbub1->watermarks.d.cstate_pstate.cstate_exit_ns =
4206f451b60SBhawanpreet Lakha 				watermarks->d.cstate_pstate.cstate_exit_ns;
4216f451b60SBhawanpreet Lakha 		prog_wm_value = convert_and_clamp(
4226f451b60SBhawanpreet Lakha 				watermarks->d.cstate_pstate.cstate_exit_ns,
4236f451b60SBhawanpreet Lakha 				refclk_mhz, 0x1fffff);
4246f451b60SBhawanpreet Lakha 		REG_SET_2(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, 0,
4256f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, prog_wm_value,
4266f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_VM_ROW_ALLOW_SR_EXIT_WATERMARK_A, prog_wm_value);
4276f451b60SBhawanpreet Lakha 		DC_LOG_BANDWIDTH_CALCS("SR_EXIT_WATERMARK_D calculated =%d\n"
4286f451b60SBhawanpreet Lakha 			"HW register value = 0x%x\n",
4296f451b60SBhawanpreet Lakha 			watermarks->d.cstate_pstate.cstate_exit_ns, prog_wm_value);
4306f451b60SBhawanpreet Lakha 	}
4316f451b60SBhawanpreet Lakha }
4326f451b60SBhawanpreet Lakha 
4334de094eeSBhawanpreet Lakha void hubbub21_program_pstate_watermarks(
4346f451b60SBhawanpreet Lakha 		struct hubbub *hubbub,
4356f451b60SBhawanpreet Lakha 		struct dcn_watermark_set *watermarks,
4366f451b60SBhawanpreet Lakha 		unsigned int refclk_mhz,
4376f451b60SBhawanpreet Lakha 		bool safe_to_lower)
4386f451b60SBhawanpreet Lakha {
4396f451b60SBhawanpreet Lakha 	struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
4406f451b60SBhawanpreet Lakha 	uint32_t prog_wm_value;
4416f451b60SBhawanpreet Lakha 
4426f451b60SBhawanpreet Lakha 	/* clock state A */
4436f451b60SBhawanpreet Lakha 	if (safe_to_lower || watermarks->a.cstate_pstate.pstate_change_ns
4446f451b60SBhawanpreet Lakha 			> hubbub1->watermarks.a.cstate_pstate.pstate_change_ns) {
4456f451b60SBhawanpreet Lakha 		hubbub1->watermarks.a.cstate_pstate.pstate_change_ns =
4466f451b60SBhawanpreet Lakha 				watermarks->a.cstate_pstate.pstate_change_ns;
4476f451b60SBhawanpreet Lakha 		prog_wm_value = convert_and_clamp(
4486f451b60SBhawanpreet Lakha 				watermarks->a.cstate_pstate.pstate_change_ns,
4496f451b60SBhawanpreet Lakha 				refclk_mhz, 0x1fffff);
4506f451b60SBhawanpreet Lakha 		REG_SET_2(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, 0,
4516f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value,
4526f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, prog_wm_value);
4536f451b60SBhawanpreet Lakha 		DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_A calculated =%d\n"
4546f451b60SBhawanpreet Lakha 			"HW register value = 0x%x\n\n",
4556f451b60SBhawanpreet Lakha 			watermarks->a.cstate_pstate.pstate_change_ns, prog_wm_value);
4566f451b60SBhawanpreet Lakha 	}
4576f451b60SBhawanpreet Lakha 
4586f451b60SBhawanpreet Lakha 	/* clock state B */
4596f451b60SBhawanpreet Lakha 	if (safe_to_lower || watermarks->b.cstate_pstate.pstate_change_ns
4606f451b60SBhawanpreet Lakha 			> hubbub1->watermarks.b.cstate_pstate.pstate_change_ns) {
4616f451b60SBhawanpreet Lakha 		hubbub1->watermarks.b.cstate_pstate.pstate_change_ns =
4626f451b60SBhawanpreet Lakha 				watermarks->b.cstate_pstate.pstate_change_ns;
4636f451b60SBhawanpreet Lakha 		prog_wm_value = convert_and_clamp(
4646f451b60SBhawanpreet Lakha 				watermarks->b.cstate_pstate.pstate_change_ns,
4656f451b60SBhawanpreet Lakha 				refclk_mhz, 0x1fffff);
4666f451b60SBhawanpreet Lakha 		REG_SET_2(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, 0,
4676f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value,
4686f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, prog_wm_value);
4696f451b60SBhawanpreet Lakha 		DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_B calculated =%d\n"
4706f451b60SBhawanpreet Lakha 			"HW register value = 0x%x\n\n",
4716f451b60SBhawanpreet Lakha 			watermarks->b.cstate_pstate.pstate_change_ns, prog_wm_value);
4726f451b60SBhawanpreet Lakha 	}
4736f451b60SBhawanpreet Lakha 
4746f451b60SBhawanpreet Lakha 	/* clock state C */
4756f451b60SBhawanpreet Lakha 	if (safe_to_lower || watermarks->c.cstate_pstate.pstate_change_ns
4766f451b60SBhawanpreet Lakha 			> hubbub1->watermarks.c.cstate_pstate.pstate_change_ns) {
4776f451b60SBhawanpreet Lakha 		hubbub1->watermarks.c.cstate_pstate.pstate_change_ns =
4786f451b60SBhawanpreet Lakha 				watermarks->c.cstate_pstate.pstate_change_ns;
4796f451b60SBhawanpreet Lakha 		prog_wm_value = convert_and_clamp(
4806f451b60SBhawanpreet Lakha 				watermarks->c.cstate_pstate.pstate_change_ns,
4816f451b60SBhawanpreet Lakha 				refclk_mhz, 0x1fffff);
4826f451b60SBhawanpreet Lakha 		REG_SET_2(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, 0,
4836f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value,
4846f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, prog_wm_value);
4856f451b60SBhawanpreet Lakha 		DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_C calculated =%d\n"
4866f451b60SBhawanpreet Lakha 			"HW register value = 0x%x\n\n",
4876f451b60SBhawanpreet Lakha 			watermarks->c.cstate_pstate.pstate_change_ns, prog_wm_value);
4886f451b60SBhawanpreet Lakha 	}
4896f451b60SBhawanpreet Lakha 
4906f451b60SBhawanpreet Lakha 	/* clock state D */
4916f451b60SBhawanpreet Lakha 	if (safe_to_lower || watermarks->d.cstate_pstate.pstate_change_ns
4926f451b60SBhawanpreet Lakha 			> hubbub1->watermarks.d.cstate_pstate.pstate_change_ns) {
4936f451b60SBhawanpreet Lakha 		hubbub1->watermarks.d.cstate_pstate.pstate_change_ns =
4946f451b60SBhawanpreet Lakha 				watermarks->d.cstate_pstate.pstate_change_ns;
4956f451b60SBhawanpreet Lakha 		prog_wm_value = convert_and_clamp(
4966f451b60SBhawanpreet Lakha 				watermarks->d.cstate_pstate.pstate_change_ns,
4976f451b60SBhawanpreet Lakha 				refclk_mhz, 0x1fffff);
4986f451b60SBhawanpreet Lakha 		REG_SET_2(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, 0,
4996f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value,
5006f451b60SBhawanpreet Lakha 				DCHUBBUB_ARB_VM_ROW_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, prog_wm_value);
5016f451b60SBhawanpreet Lakha 		DC_LOG_BANDWIDTH_CALCS("DRAM_CLK_CHANGE_WATERMARK_D calculated =%d\n"
5026f451b60SBhawanpreet Lakha 			"HW register value = 0x%x\n\n",
5036f451b60SBhawanpreet Lakha 			watermarks->d.cstate_pstate.pstate_change_ns, prog_wm_value);
5046f451b60SBhawanpreet Lakha 	}
5056f451b60SBhawanpreet Lakha }
5066f451b60SBhawanpreet Lakha 
5076f451b60SBhawanpreet Lakha void hubbub21_program_watermarks(
5086f451b60SBhawanpreet Lakha 		struct hubbub *hubbub,
5096f451b60SBhawanpreet Lakha 		struct dcn_watermark_set *watermarks,
5106f451b60SBhawanpreet Lakha 		unsigned int refclk_mhz,
5116f451b60SBhawanpreet Lakha 		bool safe_to_lower)
5126f451b60SBhawanpreet Lakha {
5136f451b60SBhawanpreet Lakha 	struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
5146f451b60SBhawanpreet Lakha 
5156f451b60SBhawanpreet Lakha 	hubbub21_program_urgent_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower);
5166f451b60SBhawanpreet Lakha 	hubbub21_program_stutter_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower);
5176f451b60SBhawanpreet Lakha 	hubbub21_program_pstate_watermarks(hubbub, watermarks, refclk_mhz, safe_to_lower);
5186f451b60SBhawanpreet Lakha 
5196f451b60SBhawanpreet Lakha 	/*
5206f451b60SBhawanpreet Lakha 	 * The DCHub arbiter has a mechanism to dynamically rate limit the DCHub request stream to the fabric.
5216f451b60SBhawanpreet Lakha 	 * If the memory controller is fully utilized and the DCHub requestors are
5226f451b60SBhawanpreet Lakha 	 * well ahead of their amortized schedule, then it is safe to prevent the next winner
5236f451b60SBhawanpreet Lakha 	 * from being committed and sent to the fabric.
5246f451b60SBhawanpreet Lakha 	 * The utilization of the memory controller is approximated by ensuring that
5256f451b60SBhawanpreet Lakha 	 * the number of outstanding requests is greater than a threshold specified
5266f451b60SBhawanpreet Lakha 	 * by the ARB_MIN_REQ_OUTSTANDING. To determine that the DCHub requestors are well ahead of the amortized schedule,
5276f451b60SBhawanpreet Lakha 	 * the slack of the next winner is compared with the ARB_SAT_LEVEL in DLG RefClk cycles.
5286f451b60SBhawanpreet Lakha 	 *
5296f451b60SBhawanpreet Lakha 	 * TODO: Revisit request limit after figure out right number. request limit for Renoir isn't decided yet, set maximum value (0x1FF)
5306f451b60SBhawanpreet Lakha 	 * to turn off it for now.
5316f451b60SBhawanpreet Lakha 	 */
5326f451b60SBhawanpreet Lakha 	REG_SET(DCHUBBUB_ARB_SAT_LEVEL, 0,
5336f451b60SBhawanpreet Lakha 			DCHUBBUB_ARB_SAT_LEVEL, 60 * refclk_mhz);
5346f451b60SBhawanpreet Lakha 	REG_UPDATE_2(DCHUBBUB_ARB_DF_REQ_OUTSTAND,
5356f451b60SBhawanpreet Lakha 			DCHUBBUB_ARB_MIN_REQ_OUTSTAND, 0x1FF,
5366f451b60SBhawanpreet Lakha 			DCHUBBUB_ARB_MIN_REQ_OUTSTAND_COMMIT_THRESHOLD, 0xA);
5376f451b60SBhawanpreet Lakha 	REG_UPDATE(DCHUBBUB_ARB_HOSTVM_CNTL,
5386f451b60SBhawanpreet Lakha 			DCHUBBUB_ARB_MAX_QOS_COMMIT_THRESHOLD, 0xF);
5396f451b60SBhawanpreet Lakha 
5406f451b60SBhawanpreet Lakha 	hubbub1_allow_self_refresh_control(hubbub, !hubbub->ctx->dc->debug.disable_stutter);
5416f451b60SBhawanpreet Lakha }
5426f451b60SBhawanpreet Lakha 
5436f451b60SBhawanpreet Lakha void hubbub21_wm_read_state(struct hubbub *hubbub,
5446f451b60SBhawanpreet Lakha 		struct dcn_hubbub_wm *wm)
5456f451b60SBhawanpreet Lakha {
5466f451b60SBhawanpreet Lakha 	struct dcn20_hubbub *hubbub1 = TO_DCN20_HUBBUB(hubbub);
5476f451b60SBhawanpreet Lakha 	struct dcn_hubbub_wm_set *s;
5486f451b60SBhawanpreet Lakha 
5496f451b60SBhawanpreet Lakha 	memset(wm, 0, sizeof(struct dcn_hubbub_wm));
5506f451b60SBhawanpreet Lakha 
5516f451b60SBhawanpreet Lakha 	s = &wm->sets[0];
5526f451b60SBhawanpreet Lakha 	s->wm_set = 0;
5536f451b60SBhawanpreet Lakha 	REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A,
5546f451b60SBhawanpreet Lakha 			DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_A, &s->data_urgent);
5556f451b60SBhawanpreet Lakha 
5566f451b60SBhawanpreet Lakha 	REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A,
5576f451b60SBhawanpreet Lakha 			DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A, &s->sr_enter);
5586f451b60SBhawanpreet Lakha 
5596f451b60SBhawanpreet Lakha 	REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A,
5606f451b60SBhawanpreet Lakha 			DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_A, &s->sr_exit);
5616f451b60SBhawanpreet Lakha 
5626f451b60SBhawanpreet Lakha 	REG_GET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A,
5636f451b60SBhawanpreet Lakha 			 DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_A, &s->dram_clk_chanage);
5646f451b60SBhawanpreet Lakha 
5656f451b60SBhawanpreet Lakha 	s = &wm->sets[1];
5666f451b60SBhawanpreet Lakha 	s->wm_set = 1;
5676f451b60SBhawanpreet Lakha 	REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B,
5686f451b60SBhawanpreet Lakha 			DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_B, &s->data_urgent);
5696f451b60SBhawanpreet Lakha 
5706f451b60SBhawanpreet Lakha 	REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B,
5716f451b60SBhawanpreet Lakha 			DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_B, &s->sr_enter);
5726f451b60SBhawanpreet Lakha 
5736f451b60SBhawanpreet Lakha 	REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B,
5746f451b60SBhawanpreet Lakha 			DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_B, &s->sr_exit);
5756f451b60SBhawanpreet Lakha 
5766f451b60SBhawanpreet Lakha 	REG_GET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B,
5776f451b60SBhawanpreet Lakha 			DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_B, &s->dram_clk_chanage);
5786f451b60SBhawanpreet Lakha 
5796f451b60SBhawanpreet Lakha 	s = &wm->sets[2];
5806f451b60SBhawanpreet Lakha 	s->wm_set = 2;
5816f451b60SBhawanpreet Lakha 	REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C,
5826f451b60SBhawanpreet Lakha 			DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_C, &s->data_urgent);
5836f451b60SBhawanpreet Lakha 
5846f451b60SBhawanpreet Lakha 	REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C,
5856f451b60SBhawanpreet Lakha 			DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_C, &s->sr_enter);
5866f451b60SBhawanpreet Lakha 
5876f451b60SBhawanpreet Lakha 	REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C,
5886f451b60SBhawanpreet Lakha 			DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_C, &s->sr_exit);
5896f451b60SBhawanpreet Lakha 
5906f451b60SBhawanpreet Lakha 	REG_GET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C,
5916f451b60SBhawanpreet Lakha 			DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_C, &s->dram_clk_chanage);
5926f451b60SBhawanpreet Lakha 
5936f451b60SBhawanpreet Lakha 	s = &wm->sets[3];
5946f451b60SBhawanpreet Lakha 	s->wm_set = 3;
5956f451b60SBhawanpreet Lakha 	REG_GET(DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D,
5966f451b60SBhawanpreet Lakha 			DCHUBBUB_ARB_DATA_URGENCY_WATERMARK_D, &s->data_urgent);
5976f451b60SBhawanpreet Lakha 
5986f451b60SBhawanpreet Lakha 	REG_GET(DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D,
5996f451b60SBhawanpreet Lakha 			DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_D, &s->sr_enter);
6006f451b60SBhawanpreet Lakha 
6016f451b60SBhawanpreet Lakha 	REG_GET(DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D,
6026f451b60SBhawanpreet Lakha 			DCHUBBUB_ARB_ALLOW_SR_EXIT_WATERMARK_D, &s->sr_exit);
6036f451b60SBhawanpreet Lakha 
6046f451b60SBhawanpreet Lakha 	REG_GET(DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D,
6056f451b60SBhawanpreet Lakha 			DCHUBBUB_ARB_ALLOW_DRAM_CLK_CHANGE_WATERMARK_D, &s->dram_clk_chanage);
6066f451b60SBhawanpreet Lakha }
6076f451b60SBhawanpreet Lakha 
6086f451b60SBhawanpreet Lakha 
6096f451b60SBhawanpreet Lakha static const struct hubbub_funcs hubbub21_funcs = {
6106f451b60SBhawanpreet Lakha 	.update_dchub = hubbub2_update_dchub,
6116f451b60SBhawanpreet Lakha 	.init_dchub_sys_ctx = hubbub21_init_dchub,
6126f451b60SBhawanpreet Lakha 	.init_vm_ctx = NULL,
6136f451b60SBhawanpreet Lakha 	.dcc_support_swizzle = hubbub2_dcc_support_swizzle,
6146f451b60SBhawanpreet Lakha 	.dcc_support_pixel_format = hubbub2_dcc_support_pixel_format,
6156f451b60SBhawanpreet Lakha 	.get_dcc_compression_cap = hubbub2_get_dcc_compression_cap,
6166f451b60SBhawanpreet Lakha 	.wm_read_state = hubbub21_wm_read_state,
6176f451b60SBhawanpreet Lakha 	.get_dchub_ref_freq = hubbub2_get_dchub_ref_freq,
6186f451b60SBhawanpreet Lakha 	.program_watermarks = hubbub21_program_watermarks,
6196f451b60SBhawanpreet Lakha };
6206f451b60SBhawanpreet Lakha 
6216f451b60SBhawanpreet Lakha void hubbub21_construct(struct dcn20_hubbub *hubbub,
6226f451b60SBhawanpreet Lakha 	struct dc_context *ctx,
6236f451b60SBhawanpreet Lakha 	const struct dcn_hubbub_registers *hubbub_regs,
6246f451b60SBhawanpreet Lakha 	const struct dcn_hubbub_shift *hubbub_shift,
6256f451b60SBhawanpreet Lakha 	const struct dcn_hubbub_mask *hubbub_mask)
6266f451b60SBhawanpreet Lakha {
6276f451b60SBhawanpreet Lakha 	hubbub->base.ctx = ctx;
6286f451b60SBhawanpreet Lakha 
6296f451b60SBhawanpreet Lakha 	hubbub->base.funcs = &hubbub21_funcs;
6306f451b60SBhawanpreet Lakha 
6316f451b60SBhawanpreet Lakha 	hubbub->regs = hubbub_regs;
6326f451b60SBhawanpreet Lakha 	hubbub->shifts = hubbub_shift;
6336f451b60SBhawanpreet Lakha 	hubbub->masks = hubbub_mask;
6346f451b60SBhawanpreet Lakha 
6356f451b60SBhawanpreet Lakha 	hubbub->debug_test_index_pstate = 0xB;
6366f451b60SBhawanpreet Lakha }
637