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.
25 #include <linux/types.h>
26 #include "pp_instance.h"
27 #include "amd_powerplay.h"
33 #define smu_lower_32_bits(n) ((uint32_t)(n))
34 #define smu_upper_32_bits(n) ((uint32_t)(((n)>>16)>>16))
36 extern const struct pp_smumgr_func cz_smu_funcs;
37 extern const struct pp_smumgr_func iceland_smu_funcs;
38 extern const struct pp_smumgr_func tonga_smu_funcs;
39 extern const struct pp_smumgr_func fiji_smu_funcs;
40 extern const struct pp_smumgr_func polaris10_smu_funcs;
41 extern const struct pp_smumgr_func vega10_smu_funcs;
42 extern const struct pp_smumgr_func rv_smu_funcs;
44 enum AVFS_BTC_STATUS {
46 AVFS_BTC_BOOT_STARTEDSMU,
48 AVFS_BTC_VIRUS_LOADED,
50 AVFS_BTC_COMPLETED_PREVIOUSLY,
54 AVFS_BTC_RESTOREVFT_FAILED,
55 AVFS_BTC_SAVEVFT_FAILED,
56 AVFS_BTC_DPMTABLESETUP_FAILED,
57 AVFS_BTC_COMPLETED_UNSAVED,
58 AVFS_BTC_COMPLETED_SAVED,
59 AVFS_BTC_COMPLETED_RESTORED,
61 AVFS_BTC_NOTSUPPORTED,
73 SMU_SoftRegisters = 0,
74 SMU_Discrete_DpmTable,
78 HandshakeDisables = 0,
80 AverageGraphicsActivity,
87 LowSclkInterruptThreshold,
91 enum SMU_MAC_DEFINITION {
92 SMU_MAX_LEVELS_GRAPHICS = 0,
93 SMU_MAX_LEVELS_MEMORY,
97 SMU_MAX_LEVELS_VDDGFX,
100 SMU_UVD_MCLK_HANDSHAKE_DISABLE,
104 struct pp_smumgr_func {
105 int (*smu_init)(struct pp_smumgr *smumgr);
106 int (*smu_fini)(struct pp_smumgr *smumgr);
107 int (*start_smu)(struct pp_smumgr *smumgr);
108 int (*check_fw_load_finish)(struct pp_smumgr *smumgr,
110 int (*request_smu_load_fw)(struct pp_smumgr *smumgr);
111 int (*request_smu_load_specific_fw)(struct pp_smumgr *smumgr,
113 int (*get_argument)(struct pp_smumgr *smumgr);
114 int (*send_msg_to_smc)(struct pp_smumgr *smumgr, uint16_t msg);
115 int (*send_msg_to_smc_with_parameter)(struct pp_smumgr *smumgr,
116 uint16_t msg, uint32_t parameter);
117 int (*download_pptable_settings)(struct pp_smumgr *smumgr,
119 int (*upload_pptable_settings)(struct pp_smumgr *smumgr);
120 int (*update_smc_table)(struct pp_hwmgr *hwmgr, uint32_t type);
121 int (*process_firmware_header)(struct pp_hwmgr *hwmgr);
122 int (*update_sclk_threshold)(struct pp_hwmgr *hwmgr);
123 int (*thermal_setup_fan_table)(struct pp_hwmgr *hwmgr);
124 int (*thermal_avfs_enable)(struct pp_hwmgr *hwmgr);
125 int (*init_smc_table)(struct pp_hwmgr *hwmgr);
126 int (*populate_all_graphic_levels)(struct pp_hwmgr *hwmgr);
127 int (*populate_all_memory_levels)(struct pp_hwmgr *hwmgr);
128 int (*initialize_mc_reg_table)(struct pp_hwmgr *hwmgr);
129 uint32_t (*get_offsetof)(uint32_t type, uint32_t member);
130 uint32_t (*get_mac_definition)(uint32_t value);
131 bool (*is_dpm_running)(struct pp_hwmgr *hwmgr);
132 int (*populate_requested_graphic_levels)(struct pp_hwmgr *hwmgr,
133 struct amd_pp_profile *request);
134 bool (*is_hw_avfs_present)(struct pp_smumgr *smumgr);
138 uint32_t chip_family;
142 uint32_t usec_timeout;
144 const struct pp_smumgr_func *smumgr_funcs;
148 extern int smum_early_init(struct pp_instance *handle);
150 extern int smum_get_argument(struct pp_smumgr *smumgr);
152 extern int smum_download_powerplay_table(struct pp_smumgr *smumgr, void **table);
154 extern int smum_upload_powerplay_table(struct pp_smumgr *smumgr);
156 extern int smum_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg);
158 extern int smum_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr,
159 uint16_t msg, uint32_t parameter);
161 extern int smum_wait_on_register(struct pp_smumgr *smumgr,
162 uint32_t index, uint32_t value, uint32_t mask);
164 extern int smum_wait_for_register_unequal(struct pp_smumgr *smumgr,
165 uint32_t index, uint32_t value, uint32_t mask);
167 extern int smum_wait_on_indirect_register(struct pp_smumgr *smumgr,
168 uint32_t indirect_port, uint32_t index,
169 uint32_t value, uint32_t mask);
172 extern void smum_wait_for_indirect_register_unequal(
173 struct pp_smumgr *smumgr,
174 uint32_t indirect_port, uint32_t index,
175 uint32_t value, uint32_t mask);
177 extern int smu_allocate_memory(void *device, uint32_t size,
178 enum cgs_gpu_mem_type type,
179 uint32_t byte_align, uint64_t *mc_addr,
180 void **kptr, void *handle);
182 extern int smu_free_memory(void *device, void *handle);
183 extern int vega10_smum_init(struct pp_smumgr *smumgr);
185 extern int smum_update_sclk_threshold(struct pp_hwmgr *hwmgr);
187 extern int smum_update_smc_table(struct pp_hwmgr *hwmgr, uint32_t type);
188 extern int smum_process_firmware_header(struct pp_hwmgr *hwmgr);
189 extern int smum_thermal_avfs_enable(struct pp_hwmgr *hwmgr,
190 void *input, void *output, void *storage, int result);
191 extern int smum_thermal_setup_fan_table(struct pp_hwmgr *hwmgr,
192 void *input, void *output, void *storage, int result);
193 extern int smum_init_smc_table(struct pp_hwmgr *hwmgr);
194 extern int smum_populate_all_graphic_levels(struct pp_hwmgr *hwmgr);
195 extern int smum_populate_all_memory_levels(struct pp_hwmgr *hwmgr);
196 extern int smum_initialize_mc_reg_table(struct pp_hwmgr *hwmgr);
197 extern uint32_t smum_get_offsetof(struct pp_smumgr *smumgr,
198 uint32_t type, uint32_t member);
199 extern uint32_t smum_get_mac_definition(struct pp_smumgr *smumgr, uint32_t value);
201 extern bool smum_is_dpm_running(struct pp_hwmgr *hwmgr);
203 extern int smum_populate_requested_graphic_levels(struct pp_hwmgr *hwmgr,
204 struct amd_pp_profile *request);
206 extern bool smum_is_hw_avfs_present(struct pp_smumgr *smumgr);
208 #define SMUM_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT
210 #define SMUM_FIELD_MASK(reg, field) reg##__##field##_MASK
212 #define SMUM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(smumgr, \
213 port, index, value, mask) \
214 smum_wait_on_indirect_register(smumgr, \
215 mm##port##_INDEX, index, value, mask)
217 #define SMUM_WAIT_INDIRECT_REGISTER(smumgr, port, reg, value, mask) \
218 SMUM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(smumgr, port, ix##reg, value, mask)
220 #define SMUM_WAIT_INDIRECT_FIELD(smumgr, port, reg, field, fieldval) \
221 SMUM_WAIT_INDIRECT_REGISTER(smumgr, port, reg, (fieldval) << SMUM_FIELD_SHIFT(reg, field), \
222 SMUM_FIELD_MASK(reg, field) )
224 #define SMUM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, \
225 index, value, mask) \
226 smum_wait_for_register_unequal(smumgr, \
229 #define SMUM_WAIT_REGISTER_UNEQUAL(smumgr, reg, value, mask) \
230 SMUM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, \
231 mm##reg, value, mask)
233 #define SMUM_WAIT_FIELD_UNEQUAL(smumgr, reg, field, fieldval) \
234 SMUM_WAIT_REGISTER_UNEQUAL(smumgr, reg, \
235 (fieldval) << SMUM_FIELD_SHIFT(reg, field), \
236 SMUM_FIELD_MASK(reg, field))
238 #define SMUM_GET_FIELD(value, reg, field) \
239 (((value) & SMUM_FIELD_MASK(reg, field)) \
240 >> SMUM_FIELD_SHIFT(reg, field))
242 #define SMUM_READ_FIELD(device, reg, field) \
243 SMUM_GET_FIELD(cgs_read_register(device, mm##reg), reg, field)
245 #define SMUM_SET_FIELD(value, reg, field, field_val) \
246 (((value) & ~SMUM_FIELD_MASK(reg, field)) | \
247 (SMUM_FIELD_MASK(reg, field) & ((field_val) << \
248 SMUM_FIELD_SHIFT(reg, field))))
250 #define SMUM_READ_INDIRECT_FIELD(device, port, reg, field) \
251 SMUM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \
254 #define SMUM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(smumgr, \
255 port, index, value, mask) \
256 smum_wait_on_indirect_register(smumgr, \
257 mm##port##_INDEX_0, index, value, mask)
259 #define SMUM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, \
260 port, index, value, mask) \
261 smum_wait_for_indirect_register_unequal(smumgr, \
262 mm##port##_INDEX_0, index, value, mask)
265 #define SMUM_WAIT_VFPF_INDIRECT_REGISTER(smumgr, port, reg, value, mask) \
266 SMUM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(smumgr, port, ix##reg, value, mask)
268 #define SMUM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(smumgr, port, reg, value, mask) \
269 SMUM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, port, ix##reg, value, mask)
272 /*Operations on named fields.*/
274 #define SMUM_READ_VFPF_INDIRECT_FIELD(device, port, reg, field) \
275 SMUM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \
278 #define SMUM_WRITE_FIELD(device, reg, field, fieldval) \
279 cgs_write_register(device, mm##reg, \
280 SMUM_SET_FIELD(cgs_read_register(device, mm##reg), reg, field, fieldval))
282 #define SMUM_WRITE_VFPF_INDIRECT_FIELD(device, port, reg, field, fieldval) \
283 cgs_write_ind_register(device, port, ix##reg, \
284 SMUM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg), \
285 reg, field, fieldval))
288 #define SMUM_WRITE_INDIRECT_FIELD(device, port, reg, field, fieldval) \
289 cgs_write_ind_register(device, port, ix##reg, \
290 SMUM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg), \
291 reg, field, fieldval))
294 #define SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, port, reg, field, fieldval) \
295 SMUM_WAIT_VFPF_INDIRECT_REGISTER(smumgr, port, reg, \
296 (fieldval) << SMUM_FIELD_SHIFT(reg, field), \
297 SMUM_FIELD_MASK(reg, field))
299 #define SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, port, reg, field, fieldval) \
300 SMUM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(smumgr, port, reg, \
301 (fieldval) << SMUM_FIELD_SHIFT(reg, field), \
302 SMUM_FIELD_MASK(reg, field))
304 #define SMUM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, port, index, value, mask) \
305 smum_wait_for_indirect_register_unequal(smumgr, \
306 mm##port##_INDEX, index, value, mask)
308 #define SMUM_WAIT_INDIRECT_REGISTER_UNEQUAL(smumgr, port, reg, value, mask) \
309 SMUM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, port, ix##reg, value, mask)
311 #define SMUM_WAIT_INDIRECT_FIELD_UNEQUAL(smumgr, port, reg, field, fieldval) \
312 SMUM_WAIT_INDIRECT_REGISTER_UNEQUAL(smumgr, port, reg, (fieldval) << SMUM_FIELD_SHIFT(reg, field), \
313 SMUM_FIELD_MASK(reg, field) )