drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.c
Source file repositories/reference/linux-study-clean/drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/gpu/drm/amd/pm/powerplay/smumgr/iceland_smumgr.c- Extension
.c- Size
- 90403 bytes
- Lines
- 2687
- Domain
- Driver Families
- Bucket
- drivers/gpu
- Inferred role
- Driver Families: implementation source
- Status
- source implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
pp_debug.hlinux/types.hlinux/kernel.hlinux/pci.hlinux/slab.hlinux/gfp.hsmumgr.hiceland_smumgr.hppsmc.hcgs_common.hsmu7_dyn_defaults.hsmu7_hwmgr.hhardwaremanager.hppatomctrl.hatombios.hpppcielanes.hpp_endian.hprocesspptables.hsmu/smu_7_1_1_d.hsmu/smu_7_1_1_sh_mask.hsmu71_discrete.hsmu_ucode_xfer_vi.hgmc/gmc_8_1_d.hgmc/gmc_8_1_sh_mask.hbif/bif_5_0_d.hbif/bif_5_0_sh_mask.hdce/dce_10_0_d.hdce/dce_10_0_sh_mask.h
Detected Declarations
function iceland_start_smcfunction iceland_reset_smcfunction iceland_stop_smc_clockfunction iceland_start_smc_clockfunction iceland_smu_start_smcfunction iceland_upload_smc_firmware_datafunction iceland_smu_upload_firmware_imagefunction iceland_request_smu_load_specific_fwfunction iceland_start_smufunction iceland_smu_initfunction iceland_initialize_power_tune_defaultsfunction iceland_populate_svi_load_linefunction iceland_populate_tdc_limitfunction iceland_populate_dw8function iceland_populate_temperature_scalerfunction iceland_populate_gnb_lpmlfunction iceland_populate_bapm_vddc_base_leakage_siddfunction iceland_populate_bapm_vddc_vid_siddfunction iceland_populate_vddc_vidfunction iceland_populate_pm_fusesfunction iceland_get_dependency_volt_by_clkfunction iceland_get_std_voltage_value_siddfunction iceland_populate_smc_voltage_tablefunction iceland_populate_smc_vddc_tablefunction iceland_populate_smc_vdd_ci_tablefunction iceland_populate_smc_mvdd_tablefunction iceland_populate_smc_voltage_tablesfunction iceland_populate_ulv_levelfunction iceland_populate_ulv_statefunction iceland_populate_smc_link_levelfunction iceland_calculate_sclk_paramsfunction iceland_populate_phase_value_based_on_sclkfunction iceland_populate_single_graphic_levelfunction iceland_populate_all_graphic_levelsfunction iceland_calculate_mclk_paramsfunction iceland_get_mclk_frequency_ratiofunction iceland_get_ddr3_mclk_frequency_ratiofunction iceland_populate_phase_value_based_on_mclkfunction iceland_populate_single_memory_levelfunction iceland_populate_all_memory_levelsfunction iceland_populate_mvdd_valuefunction iceland_populate_smc_acpi_levelfunction iceland_populate_smc_uvd_levelfunction iceland_populate_smc_vce_levelfunction iceland_populate_smc_acp_levelfunction iceland_populate_memory_timing_parametersfunction iceland_program_memory_timing_parametersfunction iceland_populate_smc_boot_level
Annotated Snippet
if (allowed_clock_voltage_table->entries[i].clk >= clock) {
*vol = allowed_clock_voltage_table->entries[i].v;
return 0;
}
}
/* sclk is bigger than max sclk in the dependence table */
*vol = allowed_clock_voltage_table->entries[i - 1].v;
return 0;
}
static int iceland_get_std_voltage_value_sidd(struct pp_hwmgr *hwmgr,
pp_atomctrl_voltage_table_entry *tab, uint16_t *hi,
uint16_t *lo)
{
uint16_t v_index;
bool vol_found = false;
*hi = tab->value * VOLTAGE_SCALE;
*lo = tab->value * VOLTAGE_SCALE;
/* SCLK/VDDC Dependency Table has to exist. */
PP_ASSERT_WITH_CODE(NULL != hwmgr->dyn_state.vddc_dependency_on_sclk,
"The SCLK/VDDC Dependency Table does not exist.",
return -EINVAL);
if (NULL == hwmgr->dyn_state.cac_leakage_table) {
pr_warn("CAC Leakage Table does not exist, using vddc.\n");
return 0;
}
/*
* Since voltage in the sclk/vddc dependency table is not
* necessarily in ascending order because of ELB voltage
* patching, loop through entire list to find exact voltage.
*/
for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) {
if (tab->value == hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) {
vol_found = true;
if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) {
*lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE;
*hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage * VOLTAGE_SCALE);
} else {
pr_warn("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index, using maximum index from CAC table.\n");
*lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE;
*hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE);
}
break;
}
}
/*
* If voltage is not found in the first pass, loop again to
* find the best match, equal or higher value.
*/
if (!vol_found) {
for (v_index = 0; (uint32_t)v_index < hwmgr->dyn_state.vddc_dependency_on_sclk->count; v_index++) {
if (tab->value <= hwmgr->dyn_state.vddc_dependency_on_sclk->entries[v_index].v) {
vol_found = true;
if ((uint32_t)v_index < hwmgr->dyn_state.cac_leakage_table->count) {
*lo = hwmgr->dyn_state.cac_leakage_table->entries[v_index].Vddc * VOLTAGE_SCALE;
*hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[v_index].Leakage) * VOLTAGE_SCALE;
} else {
pr_warn("Index from SCLK/VDDC Dependency Table exceeds the CAC Leakage Table index in second look up, using maximum index from CAC table.");
*lo = hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Vddc * VOLTAGE_SCALE;
*hi = (uint16_t)(hwmgr->dyn_state.cac_leakage_table->entries[hwmgr->dyn_state.cac_leakage_table->count - 1].Leakage * VOLTAGE_SCALE);
}
break;
}
}
if (!vol_found)
pr_warn("Unable to get std_vddc from SCLK/VDDC Dependency Table, using vddc.\n");
}
return 0;
}
static int iceland_populate_smc_voltage_table(struct pp_hwmgr *hwmgr,
pp_atomctrl_voltage_table_entry *tab,
SMU71_Discrete_VoltageLevel *smc_voltage_tab)
{
int result;
result = iceland_get_std_voltage_value_sidd(hwmgr, tab,
&smc_voltage_tab->StdVoltageHiSidd,
&smc_voltage_tab->StdVoltageLoSidd);
if (0 != result) {
smc_voltage_tab->StdVoltageHiSidd = tab->value * VOLTAGE_SCALE;
smc_voltage_tab->StdVoltageLoSidd = tab->value * VOLTAGE_SCALE;
Annotation
- Immediate include surface: `pp_debug.h`, `linux/types.h`, `linux/kernel.h`, `linux/pci.h`, `linux/slab.h`, `linux/gfp.h`, `smumgr.h`, `iceland_smumgr.h`.
- Detected declarations: `function iceland_start_smc`, `function iceland_reset_smc`, `function iceland_stop_smc_clock`, `function iceland_start_smc_clock`, `function iceland_smu_start_smc`, `function iceland_upload_smc_firmware_data`, `function iceland_smu_upload_firmware_image`, `function iceland_request_smu_load_specific_fw`, `function iceland_start_smu`, `function iceland_smu_init`.
- Atlas domain: Driver Families / drivers/gpu.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.