1 /* $NetBSD: amdgpu_smu10_smumgr.c,v 1.2 2021/12/18 23:45:27 riastradh Exp $ */ 2 3 /* 4 * Copyright 2016 Advanced Micro Devices, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 * 24 */ 25 26 #include <sys/cdefs.h> 27 __KERNEL_RCSID(0, "$NetBSD: amdgpu_smu10_smumgr.c,v 1.2 2021/12/18 23:45:27 riastradh Exp $"); 28 29 #include <linux/pci.h> 30 31 #include "smumgr.h" 32 #include "smu10_inc.h" 33 #include "soc15_common.h" 34 #include "smu10_smumgr.h" 35 #include "ppatomctrl.h" 36 #include "rv_ppsmc.h" 37 #include "smu10_driver_if.h" 38 #include "smu10.h" 39 #include "pp_debug.h" 40 41 42 #define BUFFER_SIZE 80000 43 #define MAX_STRING_SIZE 15 44 #define BUFFER_SIZETWO 131072 45 46 #define MP0_Public 0x03800000 47 #define MP0_SRAM 0x03900000 48 #define MP1_Public 0x03b00000 49 #define MP1_SRAM 0x03c00004 50 51 #define smnMP1_FIRMWARE_FLAGS 0x3010028 52 53 54 static uint32_t smu10_wait_for_response(struct pp_hwmgr *hwmgr) 55 { 56 struct amdgpu_device *adev = hwmgr->adev; 57 uint32_t reg; 58 59 reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_90); 60 61 phm_wait_for_register_unequal(hwmgr, reg, 62 0, MP1_C2PMSG_90__CONTENT_MASK); 63 64 return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90); 65 } 66 67 static int smu10_send_msg_to_smc_without_waiting(struct pp_hwmgr *hwmgr, 68 uint16_t msg) 69 { 70 struct amdgpu_device *adev = hwmgr->adev; 71 72 WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_66, msg); 73 74 return 0; 75 } 76 77 static uint32_t smu10_read_arg_from_smc(struct pp_hwmgr *hwmgr) 78 { 79 struct amdgpu_device *adev = hwmgr->adev; 80 81 return RREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82); 82 } 83 84 static int smu10_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg) 85 { 86 struct amdgpu_device *adev = hwmgr->adev; 87 88 smu10_wait_for_response(hwmgr); 89 90 WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0); 91 92 smu10_send_msg_to_smc_without_waiting(hwmgr, msg); 93 94 if (smu10_wait_for_response(hwmgr) == 0) 95 printk("Failed to send Message %x.\n", msg); 96 97 return 0; 98 } 99 100 101 static int smu10_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, 102 uint16_t msg, uint32_t parameter) 103 { 104 struct amdgpu_device *adev = hwmgr->adev; 105 106 smu10_wait_for_response(hwmgr); 107 108 WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_90, 0); 109 110 WREG32_SOC15(MP1, 0, mmMP1_SMN_C2PMSG_82, parameter); 111 112 smu10_send_msg_to_smc_without_waiting(hwmgr, msg); 113 114 115 if (smu10_wait_for_response(hwmgr) == 0) 116 printk("Failed to send Message %x.\n", msg); 117 118 return 0; 119 } 120 121 static int smu10_copy_table_from_smc(struct pp_hwmgr *hwmgr, 122 uint8_t *table, int16_t table_id) 123 { 124 struct smu10_smumgr *priv = 125 (struct smu10_smumgr *)(hwmgr->smu_backend); 126 struct amdgpu_device *adev = hwmgr->adev; 127 128 PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE, 129 "Invalid SMU Table ID!", return -EINVAL;); 130 PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0, 131 "Invalid SMU Table version!", return -EINVAL;); 132 PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0, 133 "Invalid SMU Table Length!", return -EINVAL;); 134 smu10_send_msg_to_smc_with_parameter(hwmgr, 135 PPSMC_MSG_SetDriverDramAddrHigh, 136 upper_32_bits(priv->smu_tables.entry[table_id].mc_addr)); 137 smu10_send_msg_to_smc_with_parameter(hwmgr, 138 PPSMC_MSG_SetDriverDramAddrLow, 139 lower_32_bits(priv->smu_tables.entry[table_id].mc_addr)); 140 smu10_send_msg_to_smc_with_parameter(hwmgr, 141 PPSMC_MSG_TransferTableSmu2Dram, 142 priv->smu_tables.entry[table_id].table_id); 143 144 /* flush hdp cache */ 145 amdgpu_asic_flush_hdp(adev, NULL); 146 147 memcpy(table, (uint8_t *)priv->smu_tables.entry[table_id].table, 148 priv->smu_tables.entry[table_id].size); 149 150 return 0; 151 } 152 153 static int smu10_copy_table_to_smc(struct pp_hwmgr *hwmgr, 154 uint8_t *table, int16_t table_id) 155 { 156 struct smu10_smumgr *priv = 157 (struct smu10_smumgr *)(hwmgr->smu_backend); 158 struct amdgpu_device *adev = hwmgr->adev; 159 160 PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE, 161 "Invalid SMU Table ID!", return -EINVAL;); 162 PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0, 163 "Invalid SMU Table version!", return -EINVAL;); 164 PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0, 165 "Invalid SMU Table Length!", return -EINVAL;); 166 167 memcpy(priv->smu_tables.entry[table_id].table, table, 168 priv->smu_tables.entry[table_id].size); 169 170 amdgpu_asic_flush_hdp(adev, NULL); 171 172 smu10_send_msg_to_smc_with_parameter(hwmgr, 173 PPSMC_MSG_SetDriverDramAddrHigh, 174 upper_32_bits(priv->smu_tables.entry[table_id].mc_addr)); 175 smu10_send_msg_to_smc_with_parameter(hwmgr, 176 PPSMC_MSG_SetDriverDramAddrLow, 177 lower_32_bits(priv->smu_tables.entry[table_id].mc_addr)); 178 smu10_send_msg_to_smc_with_parameter(hwmgr, 179 PPSMC_MSG_TransferTableDram2Smu, 180 priv->smu_tables.entry[table_id].table_id); 181 182 return 0; 183 } 184 185 static int smu10_verify_smc_interface(struct pp_hwmgr *hwmgr) 186 { 187 uint32_t smc_driver_if_version; 188 189 smu10_send_msg_to_smc(hwmgr, 190 PPSMC_MSG_GetDriverIfVersion); 191 smc_driver_if_version = smu10_read_arg_from_smc(hwmgr); 192 193 if ((smc_driver_if_version != SMU10_DRIVER_IF_VERSION) && 194 (smc_driver_if_version != SMU10_DRIVER_IF_VERSION + 1)) { 195 pr_err("Attempt to read SMC IF Version Number Failed!\n"); 196 return -EINVAL; 197 } 198 199 return 0; 200 } 201 202 static int smu10_smu_fini(struct pp_hwmgr *hwmgr) 203 { 204 struct smu10_smumgr *priv = 205 (struct smu10_smumgr *)(hwmgr->smu_backend); 206 207 if (priv) { 208 amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_WMTABLE].handle, 209 &priv->smu_tables.entry[SMU10_WMTABLE].mc_addr, 210 &priv->smu_tables.entry[SMU10_WMTABLE].table); 211 amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_CLOCKTABLE].handle, 212 &priv->smu_tables.entry[SMU10_CLOCKTABLE].mc_addr, 213 &priv->smu_tables.entry[SMU10_CLOCKTABLE].table); 214 kfree(hwmgr->smu_backend); 215 hwmgr->smu_backend = NULL; 216 } 217 218 return 0; 219 } 220 221 static int smu10_start_smu(struct pp_hwmgr *hwmgr) 222 { 223 struct amdgpu_device *adev = hwmgr->adev; 224 225 smum_send_msg_to_smc(hwmgr, PPSMC_MSG_GetSmuVersion); 226 hwmgr->smu_version = smu10_read_arg_from_smc(hwmgr); 227 adev->pm.fw_version = hwmgr->smu_version >> 8; 228 229 if (adev->rev_id < 0x8 && adev->pdev->device != 0x15d8 && 230 adev->pm.fw_version < 0x1e45) 231 adev->pm.pp_feature &= ~PP_GFXOFF_MASK; 232 233 if (smu10_verify_smc_interface(hwmgr)) 234 return -EINVAL; 235 236 return 0; 237 } 238 239 static int smu10_smu_init(struct pp_hwmgr *hwmgr) 240 { 241 struct smu10_smumgr *priv; 242 int r; 243 244 priv = kzalloc(sizeof(struct smu10_smumgr), GFP_KERNEL); 245 246 if (!priv) 247 return -ENOMEM; 248 249 hwmgr->smu_backend = priv; 250 251 /* allocate space for watermarks table */ 252 r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, 253 sizeof(Watermarks_t), 254 PAGE_SIZE, 255 AMDGPU_GEM_DOMAIN_VRAM, 256 &priv->smu_tables.entry[SMU10_WMTABLE].handle, 257 &priv->smu_tables.entry[SMU10_WMTABLE].mc_addr, 258 &priv->smu_tables.entry[SMU10_WMTABLE].table); 259 260 if (r) 261 goto err0; 262 263 priv->smu_tables.entry[SMU10_WMTABLE].version = 0x01; 264 priv->smu_tables.entry[SMU10_WMTABLE].size = sizeof(Watermarks_t); 265 priv->smu_tables.entry[SMU10_WMTABLE].table_id = TABLE_WATERMARKS; 266 267 /* allocate space for watermarks table */ 268 r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev, 269 sizeof(DpmClocks_t), 270 PAGE_SIZE, 271 AMDGPU_GEM_DOMAIN_VRAM, 272 &priv->smu_tables.entry[SMU10_CLOCKTABLE].handle, 273 &priv->smu_tables.entry[SMU10_CLOCKTABLE].mc_addr, 274 &priv->smu_tables.entry[SMU10_CLOCKTABLE].table); 275 276 if (r) 277 goto err1; 278 279 priv->smu_tables.entry[SMU10_CLOCKTABLE].version = 0x01; 280 priv->smu_tables.entry[SMU10_CLOCKTABLE].size = sizeof(DpmClocks_t); 281 priv->smu_tables.entry[SMU10_CLOCKTABLE].table_id = TABLE_DPMCLOCKS; 282 283 return 0; 284 285 err1: 286 amdgpu_bo_free_kernel(&priv->smu_tables.entry[SMU10_WMTABLE].handle, 287 &priv->smu_tables.entry[SMU10_WMTABLE].mc_addr, 288 &priv->smu_tables.entry[SMU10_WMTABLE].table); 289 err0: 290 kfree(priv); 291 return -EINVAL; 292 } 293 294 static int smu10_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table, uint16_t table_id, bool rw) 295 { 296 int ret; 297 298 if (rw) 299 ret = smu10_copy_table_from_smc(hwmgr, table, table_id); 300 else 301 ret = smu10_copy_table_to_smc(hwmgr, table, table_id); 302 303 return ret; 304 } 305 306 307 const struct pp_smumgr_func smu10_smu_funcs = { 308 .name = "smu10_smu", 309 .smu_init = &smu10_smu_init, 310 .smu_fini = &smu10_smu_fini, 311 .start_smu = &smu10_start_smu, 312 .request_smu_load_specific_fw = NULL, 313 .send_msg_to_smc = &smu10_send_msg_to_smc, 314 .send_msg_to_smc_with_parameter = &smu10_send_msg_to_smc_with_parameter, 315 .download_pptable_settings = NULL, 316 .upload_pptable_settings = NULL, 317 .get_argument = smu10_read_arg_from_smc, 318 .smc_table_manager = smu10_smc_table_manager, 319 }; 320 321 322