1 /* 2 * Copyright 2015 Advanced Micro Devices, Inc. 3 * 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: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 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. 21 * 22 */ 23 #ifndef _SMUMGR_H_ 24 #define _SMUMGR_H_ 25 #include <linux/types.h> 26 #include "pp_instance.h" 27 #include "amd_powerplay.h" 28 29 struct pp_smumgr; 30 struct pp_instance; 31 struct pp_hwmgr; 32 33 #define smu_lower_32_bits(n) ((uint32_t)(n)) 34 #define smu_upper_32_bits(n) ((uint32_t)(((n)>>16)>>16)) 35 36 enum AVFS_BTC_STATUS { 37 AVFS_BTC_BOOT = 0, 38 AVFS_BTC_BOOT_STARTEDSMU, 39 AVFS_LOAD_VIRUS, 40 AVFS_BTC_VIRUS_LOADED, 41 AVFS_BTC_VIRUS_FAIL, 42 AVFS_BTC_COMPLETED_PREVIOUSLY, 43 AVFS_BTC_ENABLEAVFS, 44 AVFS_BTC_STARTED, 45 AVFS_BTC_FAILED, 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, 52 AVFS_BTC_DISABLED, 53 AVFS_BTC_NOTSUPPORTED, 54 AVFS_BTC_SMUMSG_ERROR 55 }; 56 57 enum SMU_TABLE { 58 SMU_UVD_TABLE = 0, 59 SMU_VCE_TABLE, 60 SMU_SAMU_TABLE, 61 SMU_BIF_TABLE, 62 }; 63 64 enum SMU_TYPE { 65 SMU_SoftRegisters = 0, 66 SMU_Discrete_DpmTable, 67 }; 68 69 enum SMU_MEMBER { 70 HandshakeDisables = 0, 71 VoltageChangeTimeout, 72 AverageGraphicsActivity, 73 PreVBlankGap, 74 VBlankTimeout, 75 UcodeLoadStatus, 76 UvdBootLevel, 77 VceBootLevel, 78 SamuBootLevel, 79 LowSclkInterruptThreshold, 80 }; 81 82 83 enum SMU_MAC_DEFINITION { 84 SMU_MAX_LEVELS_GRAPHICS = 0, 85 SMU_MAX_LEVELS_MEMORY, 86 SMU_MAX_LEVELS_LINK, 87 SMU_MAX_ENTRIES_SMIO, 88 SMU_MAX_LEVELS_VDDC, 89 SMU_MAX_LEVELS_VDDGFX, 90 SMU_MAX_LEVELS_VDDCI, 91 SMU_MAX_LEVELS_MVDD, 92 SMU_UVD_MCLK_HANDSHAKE_DISABLE, 93 }; 94 95 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, 101 uint32_t firmware); 102 int (*request_smu_load_fw)(struct pp_smumgr *smumgr); 103 int (*request_smu_load_specific_fw)(struct pp_smumgr *smumgr, 104 uint32_t firmware); 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, 110 void **table); 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); 124 }; 125 126 struct pp_smumgr { 127 uint32_t chip_family; 128 uint32_t chip_id; 129 void *device; 130 void *backend; 131 uint32_t usec_timeout; 132 bool reload_fw; 133 const struct pp_smumgr_func *smumgr_funcs; 134 }; 135 136 137 extern int smum_init(struct amd_pp_init *pp_init, 138 struct pp_instance *handle); 139 140 extern int smum_fini(struct pp_smumgr *smumgr); 141 142 extern int smum_get_argument(struct pp_smumgr *smumgr); 143 144 extern int smum_download_powerplay_table(struct pp_smumgr *smumgr, void **table); 145 146 extern int smum_upload_powerplay_table(struct pp_smumgr *smumgr); 147 148 extern int smum_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg); 149 150 extern int smum_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr, 151 uint16_t msg, uint32_t parameter); 152 153 extern int smum_wait_on_register(struct pp_smumgr *smumgr, 154 uint32_t index, uint32_t value, uint32_t mask); 155 156 extern int smum_wait_for_register_unequal(struct pp_smumgr *smumgr, 157 uint32_t index, uint32_t value, uint32_t mask); 158 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); 162 163 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); 168 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); 173 174 extern int smu_free_memory(void *device, void *handle); 175 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); 181 182 extern int smum_update_sclk_threshold(struct pp_hwmgr *hwmgr); 183 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); 197 198 extern bool smum_is_dpm_running(struct pp_hwmgr *hwmgr); 199 200 #define SMUM_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT 201 202 #define SMUM_FIELD_MASK(reg, field) reg##__##field##_MASK 203 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) 208 209 #define SMUM_WAIT_INDIRECT_REGISTER(smumgr, port, reg, value, mask) \ 210 SMUM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(smumgr, port, ix##reg, value, mask) 211 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) ) 215 216 #define SMUM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, \ 217 index, value, mask) \ 218 smum_wait_for_register_unequal(smumgr, \ 219 index, value, mask) 220 221 #define SMUM_WAIT_REGISTER_UNEQUAL(smumgr, reg, value, mask) \ 222 SMUM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, \ 223 mm##reg, value, mask) 224 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)) 229 230 #define SMUM_GET_FIELD(value, reg, field) \ 231 (((value) & SMUM_FIELD_MASK(reg, field)) \ 232 >> SMUM_FIELD_SHIFT(reg, field)) 233 234 #define SMUM_READ_FIELD(device, reg, field) \ 235 SMUM_GET_FIELD(cgs_read_register(device, mm##reg), reg, field) 236 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)))) 241 242 #define SMUM_READ_INDIRECT_FIELD(device, port, reg, field) \ 243 SMUM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ 244 reg, field) 245 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) 250 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) 255 256 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) 259 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) 262 263 264 /*Operations on named fields.*/ 265 266 #define SMUM_READ_VFPF_INDIRECT_FIELD(device, port, reg, field) \ 267 SMUM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ 268 reg, field) 269 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)) 273 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)) 278 279 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)) 284 285 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)) 290 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)) 295 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) 299 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) 302 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) ) 306 307 #endif 308