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 enum AVFS_BTC_STATUS
{
38 AVFS_BTC_BOOT_STARTEDSMU
,
40 AVFS_BTC_VIRUS_LOADED
,
42 AVFS_BTC_COMPLETED_PREVIOUSLY
,
46 AVFS_BTC_RESTOREVFT_FAILED
,
47 AVFS_BTC_SAVEVFT_FAILED
,
48 AVFS_BTC_DPMTABLESETUP_FAILED
,
49 AVFS_BTC_COMPLETED_UNSAVED
,
50 AVFS_BTC_COMPLETED_SAVED
,
51 AVFS_BTC_COMPLETED_RESTORED
,
53 AVFS_BTC_NOTSUPPORTED
,
65 SMU_SoftRegisters
= 0,
66 SMU_Discrete_DpmTable
,
70 HandshakeDisables
= 0,
72 AverageGraphicsActivity
,
79 LowSclkInterruptThreshold
,
83 enum SMU_MAC_DEFINITION
{
84 SMU_MAX_LEVELS_GRAPHICS
= 0,
85 SMU_MAX_LEVELS_MEMORY
,
89 SMU_MAX_LEVELS_VDDGFX
,
92 SMU_UVD_MCLK_HANDSHAKE_DISABLE
,
96 struct pp_smumgr_func
{
97 int (*smu_init
)(struct pp_smumgr
*smumgr
);
98 int (*smu_fini
)(struct pp_smumgr
*smumgr
);
99 int (*start_smu
)(struct pp_smumgr
*smumgr
);
100 int (*check_fw_load_finish
)(struct pp_smumgr
*smumgr
,
102 int (*request_smu_load_fw
)(struct pp_smumgr
*smumgr
);
103 int (*request_smu_load_specific_fw
)(struct pp_smumgr
*smumgr
,
105 int (*get_argument
)(struct pp_smumgr
*smumgr
);
106 int (*send_msg_to_smc
)(struct pp_smumgr
*smumgr
, uint16_t msg
);
107 int (*send_msg_to_smc_with_parameter
)(struct pp_smumgr
*smumgr
,
108 uint16_t msg
, uint32_t parameter
);
109 int (*download_pptable_settings
)(struct pp_smumgr
*smumgr
,
111 int (*upload_pptable_settings
)(struct pp_smumgr
*smumgr
);
112 int (*update_smc_table
)(struct pp_hwmgr
*hwmgr
, uint32_t type
);
113 int (*process_firmware_header
)(struct pp_hwmgr
*hwmgr
);
114 int (*update_sclk_threshold
)(struct pp_hwmgr
*hwmgr
);
115 int (*thermal_setup_fan_table
)(struct pp_hwmgr
*hwmgr
);
116 int (*thermal_avfs_enable
)(struct pp_hwmgr
*hwmgr
);
117 int (*init_smc_table
)(struct pp_hwmgr
*hwmgr
);
118 int (*populate_all_graphic_levels
)(struct pp_hwmgr
*hwmgr
);
119 int (*populate_all_memory_levels
)(struct pp_hwmgr
*hwmgr
);
120 int (*initialize_mc_reg_table
)(struct pp_hwmgr
*hwmgr
);
121 uint32_t (*get_offsetof
)(uint32_t type
, uint32_t member
);
122 uint32_t (*get_mac_definition
)(uint32_t value
);
123 bool (*is_dpm_running
)(struct pp_hwmgr
*hwmgr
);
127 uint32_t chip_family
;
131 uint32_t usec_timeout
;
133 const struct pp_smumgr_func
*smumgr_funcs
;
137 extern int smum_init(struct amd_pp_init
*pp_init
,
138 struct pp_instance
*handle
);
140 extern int smum_fini(struct pp_smumgr
*smumgr
);
142 extern int smum_get_argument(struct pp_smumgr
*smumgr
);
144 extern int smum_download_powerplay_table(struct pp_smumgr
*smumgr
, void **table
);
146 extern int smum_upload_powerplay_table(struct pp_smumgr
*smumgr
);
148 extern int smum_send_msg_to_smc(struct pp_smumgr
*smumgr
, uint16_t msg
);
150 extern int smum_send_msg_to_smc_with_parameter(struct pp_smumgr
*smumgr
,
151 uint16_t msg
, uint32_t parameter
);
153 extern int smum_wait_on_register(struct pp_smumgr
*smumgr
,
154 uint32_t index
, uint32_t value
, uint32_t mask
);
156 extern int smum_wait_for_register_unequal(struct pp_smumgr
*smumgr
,
157 uint32_t index
, uint32_t value
, uint32_t mask
);
159 extern int smum_wait_on_indirect_register(struct pp_smumgr
*smumgr
,
160 uint32_t indirect_port
, uint32_t index
,
161 uint32_t value
, uint32_t mask
);
164 extern void smum_wait_for_indirect_register_unequal(
165 struct pp_smumgr
*smumgr
,
166 uint32_t indirect_port
, uint32_t index
,
167 uint32_t value
, uint32_t mask
);
169 extern int smu_allocate_memory(void *device
, uint32_t size
,
170 enum cgs_gpu_mem_type type
,
171 uint32_t byte_align
, uint64_t *mc_addr
,
172 void **kptr
, void *handle
);
174 extern int smu_free_memory(void *device
, void *handle
);
176 extern int cz_smum_init(struct pp_smumgr
*smumgr
);
177 extern int iceland_smum_init(struct pp_smumgr
*smumgr
);
178 extern int tonga_smum_init(struct pp_smumgr
*smumgr
);
179 extern int fiji_smum_init(struct pp_smumgr
*smumgr
);
180 extern int polaris10_smum_init(struct pp_smumgr
*smumgr
);
182 extern int smum_update_sclk_threshold(struct pp_hwmgr
*hwmgr
);
184 extern int smum_update_smc_table(struct pp_hwmgr
*hwmgr
, uint32_t type
);
185 extern int smum_process_firmware_header(struct pp_hwmgr
*hwmgr
);
186 extern int smum_thermal_avfs_enable(struct pp_hwmgr
*hwmgr
,
187 void *input
, void *output
, void *storage
, int result
);
188 extern int smum_thermal_setup_fan_table(struct pp_hwmgr
*hwmgr
,
189 void *input
, void *output
, void *storage
, int result
);
190 extern int smum_init_smc_table(struct pp_hwmgr
*hwmgr
);
191 extern int smum_populate_all_graphic_levels(struct pp_hwmgr
*hwmgr
);
192 extern int smum_populate_all_memory_levels(struct pp_hwmgr
*hwmgr
);
193 extern int smum_initialize_mc_reg_table(struct pp_hwmgr
*hwmgr
);
194 extern uint32_t smum_get_offsetof(struct pp_smumgr
*smumgr
,
195 uint32_t type
, uint32_t member
);
196 extern uint32_t smum_get_mac_definition(struct pp_smumgr
*smumgr
, uint32_t value
);
198 extern bool smum_is_dpm_running(struct pp_hwmgr
*hwmgr
);
200 #define SMUM_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT
202 #define SMUM_FIELD_MASK(reg, field) reg##__##field##_MASK
204 #define SMUM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(smumgr, \
205 port, index, value, mask) \
206 smum_wait_on_indirect_register(smumgr, \
207 mm##port##_INDEX, index, value, mask)
209 #define SMUM_WAIT_INDIRECT_REGISTER(smumgr, port, reg, value, mask) \
210 SMUM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(smumgr, port, ix##reg, value, mask)
212 #define SMUM_WAIT_INDIRECT_FIELD(smumgr, port, reg, field, fieldval) \
213 SMUM_WAIT_INDIRECT_REGISTER(smumgr, port, reg, (fieldval) << SMUM_FIELD_SHIFT(reg, field), \
214 SMUM_FIELD_MASK(reg, field) )
216 #define SMUM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, \
217 index, value, mask) \
218 smum_wait_for_register_unequal(smumgr, \
221 #define SMUM_WAIT_REGISTER_UNEQUAL(smumgr, reg, value, mask) \
222 SMUM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, \
223 mm##reg, value, mask)
225 #define SMUM_WAIT_FIELD_UNEQUAL(smumgr, reg, field, fieldval) \
226 SMUM_WAIT_REGISTER_UNEQUAL(smumgr, reg, \
227 (fieldval) << SMUM_FIELD_SHIFT(reg, field), \
228 SMUM_FIELD_MASK(reg, field))
230 #define SMUM_GET_FIELD(value, reg, field) \
231 (((value) & SMUM_FIELD_MASK(reg, field)) \
232 >> SMUM_FIELD_SHIFT(reg, field))
234 #define SMUM_READ_FIELD(device, reg, field) \
235 SMUM_GET_FIELD(cgs_read_register(device, mm##reg), reg, field)
237 #define SMUM_SET_FIELD(value, reg, field, field_val) \
238 (((value) & ~SMUM_FIELD_MASK(reg, field)) | \
239 (SMUM_FIELD_MASK(reg, field) & ((field_val) << \
240 SMUM_FIELD_SHIFT(reg, field))))
242 #define SMUM_READ_INDIRECT_FIELD(device, port, reg, field) \
243 SMUM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \
246 #define SMUM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(smumgr, \
247 port, index, value, mask) \
248 smum_wait_on_indirect_register(smumgr, \
249 mm##port##_INDEX_0, index, value, mask)
251 #define SMUM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, \
252 port, index, value, mask) \
253 smum_wait_for_indirect_register_unequal(smumgr, \
254 mm##port##_INDEX_0, index, value, mask)
257 #define SMUM_WAIT_VFPF_INDIRECT_REGISTER(smumgr, port, reg, value, mask) \
258 SMUM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(smumgr, port, ix##reg, value, mask)
260 #define SMUM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(smumgr, port, reg, value, mask) \
261 SMUM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, port, ix##reg, value, mask)
264 /*Operations on named fields.*/
266 #define SMUM_READ_VFPF_INDIRECT_FIELD(device, port, reg, field) \
267 SMUM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \
270 #define SMUM_WRITE_FIELD(device, reg, field, fieldval) \
271 cgs_write_register(device, mm##reg, \
272 SMUM_SET_FIELD(cgs_read_register(device, mm##reg), reg, field, fieldval))
274 #define SMUM_WRITE_VFPF_INDIRECT_FIELD(device, port, reg, field, fieldval) \
275 cgs_write_ind_register(device, port, ix##reg, \
276 SMUM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg), \
277 reg, field, fieldval))
280 #define SMUM_WRITE_INDIRECT_FIELD(device, port, reg, field, fieldval) \
281 cgs_write_ind_register(device, port, ix##reg, \
282 SMUM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg), \
283 reg, field, fieldval))
286 #define SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, port, reg, field, fieldval) \
287 SMUM_WAIT_VFPF_INDIRECT_REGISTER(smumgr, port, reg, \
288 (fieldval) << SMUM_FIELD_SHIFT(reg, field), \
289 SMUM_FIELD_MASK(reg, field))
291 #define SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, port, reg, field, fieldval) \
292 SMUM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(smumgr, port, reg, \
293 (fieldval) << SMUM_FIELD_SHIFT(reg, field), \
294 SMUM_FIELD_MASK(reg, field))
296 #define SMUM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, port, index, value, mask) \
297 smum_wait_for_indirect_register_unequal(smumgr, \
298 mm##port##_INDEX, index, value, mask)
300 #define SMUM_WAIT_INDIRECT_REGISTER_UNEQUAL(smumgr, port, reg, value, mask) \
301 SMUM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, port, ix##reg, value, mask)
303 #define SMUM_WAIT_INDIRECT_FIELD_UNEQUAL(smumgr, port, reg, field, fieldval) \
304 SMUM_WAIT_INDIRECT_REGISTER_UNEQUAL(smumgr, port, reg, (fieldval) << SMUM_FIELD_SHIFT(reg, field), \
305 SMUM_FIELD_MASK(reg, field) )