1 /* 2 * Copyright 2016 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 24 #include "smumgr.h" 25 #include "smu10_inc.h" 26 #include "soc15_common.h" 27 #include "smu10_smumgr.h" 28 #include "ppatomctrl.h" 29 #include "rv_ppsmc.h" 30 #include "smu10_driver_if.h" 31 #include "smu10.h" 32 #include "ppatomctrl.h" 33 #include "pp_debug.h" 34 35 36 #define BUFFER_SIZE 80000 37 #define MAX_STRING_SIZE 15 38 #define BUFFER_SIZETWO 131072 39 40 #define MP0_Public 0x03800000 41 #define MP0_SRAM 0x03900000 42 #define MP1_Public 0x03b00000 43 #define MP1_SRAM 0x03c00004 44 45 #define smnMP1_FIRMWARE_FLAGS 0x3010028 46 47 48 static uint32_t smu10_wait_for_response(struct pp_hwmgr *hwmgr) 49 { 50 struct amdgpu_device *adev = hwmgr->adev; 51 uint32_t reg; 52 53 reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_90); 54 55 phm_wait_for_register_unequal(hwmgr, reg, 56 0, MP1_C2PMSG_90__CONTENT_MASK); 57 58 return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90); 59 } 60 61 static int smu10_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr, 62 uint16_t msg) 63 { 64 struct amdgpu_device *adev = hwmgr->adev; 65 66 WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_66, msg); 67 68 return 0; 69 } 70 71 static uint32_t smu10_read_arg_from_smc(struct pp_hwmgr *hwmgr) 72 { 73 struct amdgpu_device *adev = hwmgr->adev; 74 75 return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82); 76 } 77 78 static int smu10_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) 79 { 80 struct amdgpu_device *adev = hwmgr->adev; 81 82 smu10_wait_for_response(hwmgr); 83 84 WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0); 85 86 smu10_send_msg_to_smc_without_waiting(hwmgr, msg); 87 88 if (smu10_wait_for_response(hwmgr) == 0) 89 printk("Failed to send Message %x.\n", msg); 90 91 return 0; 92 } 93 94 95 static int smu10_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, 96 uint16_t msg, uint32_t parameter) 97 { 98 struct amdgpu_device *adev = hwmgr->adev; 99 100 smu10_wait_for_response(hwmgr); 101 102 WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0); 103 104 WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82, parameter); 105 106 smu10_send_msg_to_smc_without_waiting(hwmgr, msg); 107 108 109 if (smu10_wait_for_response(hwmgr) == 0) 110 printk("Failed to send Message %x.\n", msg); 111 112 return 0; 113 } 114 115 static int smu10_copy_table_from_smc(struct pp_hwmgr *hwmgr, 116 uint8_t *table, int16_t table_id) 117 { 118 struct smu10_smumgr *priv = 119 (struct smu10_smumgr *)(hwmgr->smu_backend); 120 121 PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE, 122 "Invalid SMU Table ID!", return -EINVAL;); 123 PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0, 124 "Invalid SMU Table version!", return -EINVAL;); 125 PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0, 126 "Invalid SMU Table Length!", return -EINVAL;); 127 smu10_send_msg_to_smc_with_parameter(hwmgr, 128 PPSMC_MSG_SetDriverDramAddrHigh, 129 upper_32_bits(priv->smu_tables.entry[table_id].mc_addr)); 130 smu10_send_msg_to_smc_with_parameter(hwmgr, 131 PPSMC_MSG_SetDriverDramAddrLow, 132 lower_32_bits(priv->smu_tables.entry[table_id].mc_addr)); 133 smu10_send_msg_to_smc_with_parameter(hwmgr, 134 PPSMC_MSG_TransferTableSmu2Dram, 135 priv->smu_tables.entry[table_id].table_id); 136 137 memcpy(table, (uint8_t *)priv->smu_tables.entry[table_id].table, 138 priv->smu_tables.entry[table_id].size); 139 140 return 0; 141 } 142 143 static int smu10_copy_table_to_smc(struct pp_hwmgr *hwmgr, 144 uint8_t *table, int16_t table_id) 145 { 146 struct smu10_smumgr *priv = 147 (struct smu10_smumgr *)(hwmgr->smu_backend); 148 149 PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE, 150 "Invalid SMU Table ID!", return -EINVAL;); 151 PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0, 152 "Invalid SMU Table version!", return -EINVAL;); 153 PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0, 154 "Invalid SMU Table Length!", return -EINVAL;); 155 156 memcpy(priv->smu_tables.entry[table_id].table, table, 157 priv->smu_tables.entry[table_id].size); 158 159 smu10_send_msg_to_smc_with_parameter(hwmgr, 160 PPSMC_MSG_SetDriverDramAddrHigh, 161 upper_32_bits(priv->smu_tables.entry[table_id].mc_addr)); 162 smu10_send_msg_to_smc_with_parameter(hwmgr, 163 PPSMC_MSG_SetDriverDramAddrLow, 164 lower_32_bits(priv->smu_tables.entry[table_id].mc_addr)); 165 smu10_send_msg_to_smc_with_parameter(hwmgr, 166 PPSMC_MSG_TransferTableDram2Smu, 167 priv->smu_tables.entry[table_id].table_id); 168 169 return 0; 170 } 171 172 static int smu10_verify_smc_interface(struct pp_hwmgr *hwmgr) 173 { 174 uint32_t smc_driver_if_version; 175 176 smu10_send_msg_to_smc(hwmgr, 177 PPSMC_MSG_GetDriverIfVersion); 178 smc_driver_if_version = smu10_read_arg_from_smc(hwmgr); 179 180 if (smc_driver_if_version != SMU10_DRIVER_IF_VERSION) { 181 pr_err("Attempt to read SMC IF Version Number Failed!\n"); 182 return -EINVAL; 183 } 184 185 return 0; 186 } 187 188 /* sdma is disabled by default in vbios, need to re-enable in driver */ 189 static void smu10_smc_enable_sdma(struct pp_hwmgr *hwmgr) 190 { 191 smu10_send_msg_to_smc(hwmgr, 192 PPSMC_MSG_PowerUpSdma); 193 } 194 195 static void smu10_smc_disable_sdma(struct pp_hwmgr *hwmgr) 196 { 197 smu10_send_msg_to_smc(hwmgr, 198 PPSMC_MSG_PowerDownSdma); 199 } 200 201 /* vcn is disabled by default in vbios, need to re-enable in driver */ 202 static void smu10_smc_enable_vcn(struct pp_hwmgr *hwmgr) 203 { 204 smu10_send_msg_to_smc_with_parameter(hwmgr, 205 PPSMC_MSG_PowerUpVcn, 0); 206 } 207 208 static void smu10_smc_disable_vcn(struct pp_hwmgr *hwmgr) 209 { 210 smu10_send_msg_to_smc_with_parameter(hwmgr, 211 PPSMC_MSG_PowerDownVcn, 0); 212 } 213 214 static int smu10_smu_fini(struct pp_hwmgr *hwmgr) 215 { 216 struct smu10_smumgr *priv = 217 (struct smu10_smumgr *)(hwmgr->smu_backend); 218 219 if (priv) { 220 smu10_smc_disable_sdma(hwmgr); 221 smu10_smc_disable_vcn(hwmgr); 222 amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_WMTABLE].handle, 223 (u64 *)&priv->smu_tables.entry[SMU10_WMTABLE].mc_addr, 224 &priv->smu_tables.entry[SMU10_WMTABLE].table); 225 amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_CLOCKTABLE].handle, 226 (u64 *)&priv->smu_tables.entry[SMU10_CLOCKTABLE].mc_addr, 227 &priv->smu_tables.entry[SMU10_CLOCKTABLE].table); 228 kfree(hwmgr->smu_backend); 229 hwmgr->smu_backend = NULL; 230 } 231 232 return 0; 233 } 234 235 static int smu10_start_smu(struct pp_hwmgr *hwmgr) 236 { 237 struct amdgpu_device *adev = hwmgr->adev; 238 239 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetSmuVersion); 240 hwmgr->smu_version = smu10_read_arg_from_smc(hwmgr); 241 adev->pm.fw_version = hwmgr->smu_version >> 8; 242 243 if (smu10_verify_smc_interface(hwmgr)) 244 return -EINVAL; 245 smu10_smc_enable_sdma(hwmgr); 246 smu10_smc_enable_vcn(hwmgr); 247 return 0; 248 } 249 250 static int smu10_smu_init(struct pp_hwmgr *hwmgr) 251 { 252 struct smu10_smumgr *priv; 253 int r; 254 255 priv = kzalloc(sizeof(struct smu10_smumgr), GFP_KERNEL); 256 257 if (!priv) 258 return -ENOMEM; 259 260 hwmgr->smu_backend = priv; 261 262 /* allocate space for watermarks table */ 263 r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, 264 sizeof(Watermarks_t), 265 PAGE_SIZE, 266 AMDGPU_GEM_DOMAIN_VRAM, 267 &priv->smu_tables.entry[SMU10_WMTABLE].handle, 268 (u64 *)&priv->smu_tables.entry[SMU10_WMTABLE].mc_addr, 269 &priv->smu_tables.entry[SMU10_WMTABLE].table); 270 271 if (r) 272 goto err0; 273 274 priv->smu_tables.entry[SMU10_WMTABLE].version = 0x01; 275 priv->smu_tables.entry[SMU10_WMTABLE].size = sizeof(Watermarks_t); 276 priv->smu_tables.entry[SMU10_WMTABLE].table_id = TABLE_WATERMARKS; 277 278 /* allocate space for watermarks table */ 279 r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, 280 sizeof(DpmClocks_t), 281 PAGE_SIZE, 282 AMDGPU_GEM_DOMAIN_VRAM, 283 &priv->smu_tables.entry[SMU10_CLOCKTABLE].handle, 284 (u64 *)&priv->smu_tables.entry[SMU10_CLOCKTABLE].mc_addr, 285 &priv->smu_tables.entry[SMU10_CLOCKTABLE].table); 286 287 if (r) 288 goto err1; 289 290 priv->smu_tables.entry[SMU10_CLOCKTABLE].version = 0x01; 291 priv->smu_tables.entry[SMU10_CLOCKTABLE].size = sizeof(DpmClocks_t); 292 priv->smu_tables.entry[SMU10_CLOCKTABLE].table_id = TABLE_DPMCLOCKS; 293 294 return 0; 295 296 err1: 297 amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_WMTABLE].handle, 298 (u64 *)&priv->smu_tables.entry[SMU10_WMTABLE].mc_addr, 299 &priv->smu_tables.entry[SMU10_WMTABLE].table); 300 err0: 301 kfree(priv); 302 return -EINVAL; 303 } 304 305 static int smu10_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t table_id, bool rw) 306 { 307 int ret; 308 309 if (rw) 310 ret = smu10_copy_table_from_smc(hwmgr, table, table_id); 311 else 312 ret = smu10_copy_table_to_smc(hwmgr, table, table_id); 313 314 return ret; 315 } 316 317 318 const struct pp_smumgr_func smu10_smu_funcs = { 319 .smu_init = &smu10_smu_init, 320 .smu_fini = &smu10_smu_fini, 321 .start_smu = &smu10_start_smu, 322 .request_smu_load_specific_fw = NULL, 323 .send_msg_to_smc = &smu10_send_msg_to_smc, 324 .send_msg_to_smc_with_parameter = &smu10_send_msg_to_smc_with_parameter, 325 .download_pptable_settings = NULL, 326 .upload_pptable_settings = NULL, 327 .get_argument = smu10_read_arg_from_smc, 328 .smc_table_manager = smu10_smc_table_manager, 329 }; 330 331 332