2 * Copyright 2015 Advanced Micro Devices, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * 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 OR
20 * OTHER DEALINGS IN THE SOFTWARE.
24 #include <linux/delay.h>
25 #include <linux/kernel.h>
26 #include <linux/module.h>
27 #include <linux/slab.h>
28 #include <linux/types.h>
29 #include <drm/amdgpu_drm.h>
30 #include "pp_instance.h"
32 #include "cgs_common.h"
36 int smum_early_init(struct pp_instance *handle)
38 struct pp_smumgr *smumgr;
43 smumgr = kzalloc(sizeof(struct pp_smumgr), GFP_KERNEL);
47 smumgr->device = handle->device;
48 smumgr->chip_family = handle->chip_family;
49 smumgr->chip_id = handle->chip_id;
50 smumgr->usec_timeout = AMD_MAX_USEC_TIMEOUT;
51 smumgr->reload_fw = 1;
52 handle->smu_mgr = smumgr;
54 switch (smumgr->chip_family) {
55 case AMDGPU_FAMILY_CZ:
56 smumgr->smumgr_funcs = &cz_smu_funcs;
58 case AMDGPU_FAMILY_VI:
59 switch (smumgr->chip_id) {
61 smumgr->smumgr_funcs = &iceland_smu_funcs;
64 smumgr->smumgr_funcs = &tonga_smu_funcs;
67 smumgr->smumgr_funcs = &fiji_smu_funcs;
72 smumgr->smumgr_funcs = &polaris10_smu_funcs;
78 case AMDGPU_FAMILY_AI:
79 switch (smumgr->chip_id) {
81 smumgr->smumgr_funcs = &vega10_smu_funcs;
87 case AMDGPU_FAMILY_RV:
88 switch (smumgr->chip_id) {
90 smumgr->smumgr_funcs = &rv_smu_funcs;
104 int smum_thermal_avfs_enable(struct pp_hwmgr *hwmgr,
105 void *input, void *output, void *storage, int result)
107 if (NULL != hwmgr->smumgr->smumgr_funcs->thermal_avfs_enable)
108 return hwmgr->smumgr->smumgr_funcs->thermal_avfs_enable(hwmgr);
113 int smum_thermal_setup_fan_table(struct pp_hwmgr *hwmgr,
114 void *input, void *output, void *storage, int result)
116 if (NULL != hwmgr->smumgr->smumgr_funcs->thermal_setup_fan_table)
117 return hwmgr->smumgr->smumgr_funcs->thermal_setup_fan_table(hwmgr);
122 int smum_update_sclk_threshold(struct pp_hwmgr *hwmgr)
125 if (NULL != hwmgr->smumgr->smumgr_funcs->update_sclk_threshold)
126 return hwmgr->smumgr->smumgr_funcs->update_sclk_threshold(hwmgr);
131 int smum_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type)
134 if (NULL != hwmgr->smumgr->smumgr_funcs->update_smc_table)
135 return hwmgr->smumgr->smumgr_funcs->update_smc_table(hwmgr, type);
140 uint32_t smum_get_offsetof(struct pp_smumgr *smumgr, uint32_t type, uint32_t member)
142 if (NULL != smumgr->smumgr_funcs->get_offsetof)
143 return smumgr->smumgr_funcs->get_offsetof(type, member);
148 int smum_process_firmware_header(struct pp_hwmgr *hwmgr)
150 if (NULL != hwmgr->smumgr->smumgr_funcs->process_firmware_header)
151 return hwmgr->smumgr->smumgr_funcs->process_firmware_header(hwmgr);
155 int smum_get_argument(struct pp_smumgr *smumgr)
157 if (NULL != smumgr->smumgr_funcs->get_argument)
158 return smumgr->smumgr_funcs->get_argument(smumgr);
163 uint32_t smum_get_mac_definition(struct pp_smumgr *smumgr, uint32_t value)
165 if (NULL != smumgr->smumgr_funcs->get_mac_definition)
166 return smumgr->smumgr_funcs->get_mac_definition(value);
171 int smum_download_powerplay_table(struct pp_smumgr *smumgr,
174 if (NULL != smumgr->smumgr_funcs->download_pptable_settings)
175 return smumgr->smumgr_funcs->download_pptable_settings(smumgr,
180 int smum_upload_powerplay_table(struct pp_smumgr *smumgr)
182 if (NULL != smumgr->smumgr_funcs->upload_pptable_settings)
183 return smumgr->smumgr_funcs->upload_pptable_settings(smumgr);
188 int smum_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg)
190 if (smumgr == NULL || smumgr->smumgr_funcs->send_msg_to_smc == NULL)
193 return smumgr->smumgr_funcs->send_msg_to_smc(smumgr, msg);
196 int smum_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr,
197 uint16_t msg, uint32_t parameter)
199 if (smumgr == NULL ||
200 smumgr->smumgr_funcs->send_msg_to_smc_with_parameter == NULL)
202 return smumgr->smumgr_funcs->send_msg_to_smc_with_parameter(
203 smumgr, msg, parameter);
207 * Returns once the part of the register indicated by the mask has
208 * reached the given value.
210 int smum_wait_on_register(struct pp_smumgr *smumgr,
212 uint32_t value, uint32_t mask)
217 if (smumgr == NULL || smumgr->device == NULL)
220 for (i = 0; i < smumgr->usec_timeout; i++) {
221 cur_value = cgs_read_register(smumgr->device, index);
222 if ((cur_value & mask) == (value & mask))
227 /* timeout means wrong logic*/
228 if (i == smumgr->usec_timeout)
234 int smum_wait_for_register_unequal(struct pp_smumgr *smumgr,
236 uint32_t value, uint32_t mask)
244 for (i = 0; i < smumgr->usec_timeout; i++) {
245 cur_value = cgs_read_register(smumgr->device,
247 if ((cur_value & mask) != (value & mask))
252 /* timeout means wrong logic */
253 if (i == smumgr->usec_timeout)
261 * Returns once the part of the register indicated by the mask
262 * has reached the given value.The indirect space is described by
263 * giving the memory-mapped index of the indirect index register.
265 int smum_wait_on_indirect_register(struct pp_smumgr *smumgr,
266 uint32_t indirect_port,
271 if (smumgr == NULL || smumgr->device == NULL)
274 cgs_write_register(smumgr->device, indirect_port, index);
275 return smum_wait_on_register(smumgr, indirect_port + 1,
279 void smum_wait_for_indirect_register_unequal(
280 struct pp_smumgr *smumgr,
281 uint32_t indirect_port,
286 if (smumgr == NULL || smumgr->device == NULL)
288 cgs_write_register(smumgr->device, indirect_port, index);
289 smum_wait_for_register_unequal(smumgr, indirect_port + 1,
293 int smu_allocate_memory(void *device, uint32_t size,
294 enum cgs_gpu_mem_type type,
295 uint32_t byte_align, uint64_t *mc_addr,
296 void **kptr, void *handle)
299 cgs_handle_t cgs_handle;
301 if (device == NULL || handle == NULL ||
302 mc_addr == NULL || kptr == NULL)
305 ret = cgs_alloc_gpu_mem(device, type, size, byte_align,
306 0, 0, (cgs_handle_t *)handle);
310 cgs_handle = *(cgs_handle_t *)handle;
312 ret = cgs_gmap_gpu_mem(device, cgs_handle, mc_addr);
316 ret = cgs_kmap_gpu_mem(device, cgs_handle, kptr);
323 cgs_gunmap_gpu_mem(device, cgs_handle);
326 cgs_free_gpu_mem(device, cgs_handle);
330 int smu_free_memory(void *device, void *handle)
332 cgs_handle_t cgs_handle = (cgs_handle_t)handle;
334 if (device == NULL || handle == NULL)
337 cgs_kunmap_gpu_mem(device, cgs_handle);
338 cgs_gunmap_gpu_mem(device, cgs_handle);
339 cgs_free_gpu_mem(device, cgs_handle);
344 int smum_init_smc_table(struct pp_hwmgr *hwmgr)
346 if (NULL != hwmgr->smumgr->smumgr_funcs->init_smc_table)
347 return hwmgr->smumgr->smumgr_funcs->init_smc_table(hwmgr);
352 int smum_populate_all_graphic_levels(struct pp_hwmgr *hwmgr)
354 if (NULL != hwmgr->smumgr->smumgr_funcs->populate_all_graphic_levels)
355 return hwmgr->smumgr->smumgr_funcs->populate_all_graphic_levels(hwmgr);
360 int smum_populate_all_memory_levels(struct pp_hwmgr *hwmgr)
362 if (NULL != hwmgr->smumgr->smumgr_funcs->populate_all_memory_levels)
363 return hwmgr->smumgr->smumgr_funcs->populate_all_memory_levels(hwmgr);
368 /*this interface is needed by island ci/vi */
369 int smum_initialize_mc_reg_table(struct pp_hwmgr *hwmgr)
371 if (NULL != hwmgr->smumgr->smumgr_funcs->initialize_mc_reg_table)
372 return hwmgr->smumgr->smumgr_funcs->initialize_mc_reg_table(hwmgr);
377 bool smum_is_dpm_running(struct pp_hwmgr *hwmgr)
379 if (NULL != hwmgr->smumgr->smumgr_funcs->is_dpm_running)
380 return hwmgr->smumgr->smumgr_funcs->is_dpm_running(hwmgr);
385 int smum_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr,
386 struct amd_pp_profile *request)
388 if (hwmgr->smumgr->smumgr_funcs->populate_requested_graphic_levels)
389 return hwmgr->smumgr->smumgr_funcs->populate_requested_graphic_levels(
395 bool smum_is_hw_avfs_present(struct pp_smumgr *smumgr)
397 if (smumgr->smumgr_funcs->is_hw_avfs_present)
398 return smumgr->smumgr_funcs->is_hw_avfs_present(smumgr);