return 1;
 }
 
+static inline uint32_t calc_dram_speed_mts(const MemPstateTable_t *entry)
+{
+       return entry->UClk * convert_wck_ratio(entry->WckRatio) * 2;
+}
+
 static void dcn35_clk_mgr_helper_populate_bw_params(struct clk_mgr_internal *clk_mgr,
                                                    struct integrated_info *bios_info,
                                                    DpmClocks_t_dcn35 *clock_table)
 {
        struct clk_bw_params *bw_params = clk_mgr->base.bw_params;
        struct clk_limit_table_entry def_max = bw_params->clk_table.entries[bw_params->clk_table.num_entries - 1];
-       uint32_t max_pstate = 0,  max_uclk = 0, max_fclk = 0;
-       uint32_t min_pstate = 0, max_dispclk = 0, max_dppclk = 0;
+       uint32_t max_fclk = 0, min_pstate = 0, max_dispclk = 0, max_dppclk = 0;
+       uint32_t max_pstate = 0, max_dram_speed_mts = 0, min_dram_speed_mts = 0;
        int i;
 
+       /* Determine min/max p-state values. */
        for (i = 0; i < clock_table->NumMemPstatesEnabled; i++) {
-               if (is_valid_clock_value(clock_table->MemPstateTable[i].UClk) &&
-                   clock_table->MemPstateTable[i].UClk > max_uclk) {
-                       max_uclk = clock_table->MemPstateTable[i].UClk;
+               uint32_t dram_speed_mts = calc_dram_speed_mts(&clock_table->MemPstateTable[i]);
+
+               if (is_valid_clock_value(dram_speed_mts) && dram_speed_mts > max_dram_speed_mts) {
+                       max_dram_speed_mts = dram_speed_mts;
                        max_pstate = i;
                }
        }
 
-       /* We expect the table to contain at least one valid Uclk entry. */
-       ASSERT(is_valid_clock_value(max_uclk));
+       min_dram_speed_mts = max_dram_speed_mts;
+       min_pstate = max_pstate;
 
+       for (i = 0; i < clock_table->NumMemPstatesEnabled; i++) {
+               uint32_t dram_speed_mts = calc_dram_speed_mts(&clock_table->MemPstateTable[i]);
+
+               if (is_valid_clock_value(dram_speed_mts) && dram_speed_mts < min_dram_speed_mts) {
+                       min_dram_speed_mts = dram_speed_mts;
+                       min_pstate = i;
+               }
+       }
+
+       /* We expect the table to contain at least one valid P-state entry. */
+       ASSERT(clock_table->NumMemPstatesEnabled &&
+              is_valid_clock_value(max_dram_speed_mts) &&
+              is_valid_clock_value(min_dram_speed_mts));
 
        /* dispclk and dppclk can be max at any voltage, same number of levels for both */
        if (clock_table->NumDispClkLevelsEnabled <= NUM_DISPCLK_DPM_LEVELS &&
                max_dppclk = find_max_clk_value(clock_table->DppClocks,
                        clock_table->NumDispClkLevelsEnabled);
        } else {
+               /* Invalid number of entries in the table from PMFW. */
                ASSERT(0);
        }
-       if (clock_table->NumFclkLevelsEnabled <= NUM_FCLK_DPM_LEVELS)
-               max_fclk = find_max_clk_value(clock_table->FclkClocks_Freq,
-                       clock_table->NumFclkLevelsEnabled);
 
-       for (i = 0; i < clock_table->NumMemPstatesEnabled; i++) {
-               uint32_t min_uclk = clock_table->MemPstateTable[0].UClk;
-               int j;
+       /* Base the clock table on dcfclk, need at least one entry regardless of pmfw table */
+       ASSERT(clock_table->NumDcfClkLevelsEnabled > 0);
 
-               for (j = 1; j < clock_table->NumMemPstatesEnabled; j++) {
-                       if (is_valid_clock_value(clock_table->MemPstateTable[j].UClk) &&
-                           clock_table->MemPstateTable[j].UClk < min_uclk &&
-                           clock_table->MemPstateTable[j].Voltage <= clock_table->SocVoltage[i]) {
-                               min_uclk = clock_table->MemPstateTable[j].UClk;
-                               min_pstate = j;
-                       }
-               }
+       max_fclk = find_max_clk_value(clock_table->FclkClocks_Freq, clock_table->NumFclkLevelsEnabled);
 
+       for (i = 0; i < clock_table->NumDcfClkLevelsEnabled; i++) {
+               int j;
+
+               /* First search defaults for the clocks we don't read using closest lower or equal default dcfclk */
                for (j = bw_params->clk_table.num_entries - 1; j > 0; j--)
                        if (bw_params->clk_table.entries[j].dcfclk_mhz <= clock_table->DcfClocks[i])
-                       break;
+                               break;
 
                bw_params->clk_table.entries[i].phyclk_mhz = bw_params->clk_table.entries[j].phyclk_mhz;
                bw_params->clk_table.entries[i].phyclk_d18_mhz = bw_params->clk_table.entries[j].phyclk_d18_mhz;
                bw_params->clk_table.entries[i].dtbclk_mhz = bw_params->clk_table.entries[j].dtbclk_mhz;
-               bw_params->clk_table.entries[i].fclk_mhz = max_fclk;
+
+               /* Now update clocks we do read */
                bw_params->clk_table.entries[i].memclk_mhz = clock_table->MemPstateTable[min_pstate].MemClk;
                bw_params->clk_table.entries[i].voltage = clock_table->MemPstateTable[min_pstate].Voltage;
                bw_params->clk_table.entries[i].dcfclk_mhz = clock_table->DcfClocks[i];
                bw_params->clk_table.entries[i].socclk_mhz = clock_table->SocClocks[i];
                bw_params->clk_table.entries[i].dispclk_mhz = max_dispclk;
                bw_params->clk_table.entries[i].dppclk_mhz = max_dppclk;
-               bw_params->clk_table.entries[i].wck_ratio = convert_wck_ratio(
-                       clock_table->MemPstateTable[min_pstate].WckRatio);
-               }
+               bw_params->clk_table.entries[i].wck_ratio =
+                       convert_wck_ratio(clock_table->MemPstateTable[min_pstate].WckRatio);
+
+               /* Dcfclk and Fclk are tied, but at a different ratio */
+               bw_params->clk_table.entries[i].fclk_mhz = min(max_fclk, 2 * clock_table->DcfClocks[i]);
+       }
 
        /* Make sure to include at least one entry at highest pstate */
        if (max_pstate != min_pstate || i == 0) {
                if (i > MAX_NUM_DPM_LVL - 1)
                        i = MAX_NUM_DPM_LVL - 1;
+
                bw_params->clk_table.entries[i].fclk_mhz = max_fclk;
                bw_params->clk_table.entries[i].memclk_mhz = clock_table->MemPstateTable[max_pstate].MemClk;
                bw_params->clk_table.entries[i].voltage = clock_table->MemPstateTable[max_pstate].Voltage;
        }
        bw_params->clk_table.num_entries = i--;
 
+       /* Make sure all highest clocks are included*/
        bw_params->clk_table.entries[i].socclk_mhz =
                find_max_clk_value(clock_table->SocClocks, NUM_SOCCLK_DPM_LEVELS);
        bw_params->clk_table.entries[i].dispclk_mhz =
        bw_params->clk_table.num_entries_per_clk.num_fclk_levels = clock_table->NumFclkLevelsEnabled;
        bw_params->clk_table.num_entries_per_clk.num_memclk_levels = clock_table->NumMemPstatesEnabled;
        bw_params->clk_table.num_entries_per_clk.num_socclk_levels = clock_table->NumSocClkLevelsEnabled;
+
+       /*
+        * Set any 0 clocks to max default setting. Not an issue for
+        * power since we aren't doing switching in such case anyway
+        */
        for (i = 0; i < bw_params->clk_table.num_entries; i++) {
                if (!bw_params->clk_table.entries[i].fclk_mhz) {
                        bw_params->clk_table.entries[i].fclk_mhz = def_max.fclk_mhz;