Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright 2015 Advanced Micro Devices, Inc.
0003  *
0004  * Permission is hereby granted, free of charge, to any person obtaining a
0005  * copy of this software and associated documentation files (the "Software"),
0006  * to deal in the Software without restriction, including without limitation
0007  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
0008  * and/or sell copies of the Software, and to permit persons to whom the
0009  * Software is furnished to do so, subject to the following conditions:
0010  *
0011  * The above copyright notice and this permission notice shall be included in
0012  * all copies or substantial portions of the Software.
0013  *
0014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
0017  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
0018  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
0019  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
0020  * OTHER DEALINGS IN THE SOFTWARE.
0021  *
0022  */
0023 
0024 
0025 #include "pp_debug.h"
0026 #include "smumgr.h"
0027 #include "smu_ucode_xfer_vi.h"
0028 #include "ppatomctrl.h"
0029 #include "cgs_common.h"
0030 #include "smu7_ppsmc.h"
0031 #include "smu7_smumgr.h"
0032 #include "smu7_common.h"
0033 
0034 #include "polaris10_pwrvirus.h"
0035 
0036 #define SMU7_SMC_SIZE 0x20000
0037 
0038 static int smu7_set_smc_sram_address(struct pp_hwmgr *hwmgr, uint32_t smc_addr, uint32_t limit)
0039 {
0040     PP_ASSERT_WITH_CODE((0 == (3 & smc_addr)), "SMC address must be 4 byte aligned.", return -EINVAL);
0041     PP_ASSERT_WITH_CODE((limit > (smc_addr + 3)), "SMC addr is beyond the SMC RAM area.", return -EINVAL);
0042 
0043     cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_11, smc_addr);
0044     PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 0); /* on ci, SMC_IND_ACCESS_CNTL is different */
0045     return 0;
0046 }
0047 
0048 
0049 int smu7_copy_bytes_from_smc(struct pp_hwmgr *hwmgr, uint32_t smc_start_address, uint32_t *dest, uint32_t byte_count, uint32_t limit)
0050 {
0051     uint32_t data;
0052     uint32_t addr;
0053     uint8_t *dest_byte;
0054     uint8_t i, data_byte[4] = {0};
0055     uint32_t *pdata = (uint32_t *)&data_byte;
0056 
0057     PP_ASSERT_WITH_CODE((0 == (3 & smc_start_address)), "SMC address must be 4 byte aligned.", return -EINVAL);
0058     PP_ASSERT_WITH_CODE((limit > (smc_start_address + byte_count)), "SMC address is beyond the SMC RAM area.", return -EINVAL);
0059 
0060     addr = smc_start_address;
0061 
0062     while (byte_count >= 4) {
0063         smu7_read_smc_sram_dword(hwmgr, addr, &data, limit);
0064 
0065         *dest = PP_SMC_TO_HOST_UL(data);
0066 
0067         dest += 1;
0068         byte_count -= 4;
0069         addr += 4;
0070     }
0071 
0072     if (byte_count) {
0073         smu7_read_smc_sram_dword(hwmgr, addr, &data, limit);
0074         *pdata = PP_SMC_TO_HOST_UL(data);
0075     /* Cast dest into byte type in dest_byte.  This way, we don't overflow if the allocated memory is not 4-byte aligned. */
0076         dest_byte = (uint8_t *)dest;
0077         for (i = 0; i < byte_count; i++)
0078             dest_byte[i] = data_byte[i];
0079     }
0080 
0081     return 0;
0082 }
0083 
0084 
0085 int smu7_copy_bytes_to_smc(struct pp_hwmgr *hwmgr, uint32_t smc_start_address,
0086                 const uint8_t *src, uint32_t byte_count, uint32_t limit)
0087 {
0088     int result;
0089     uint32_t data = 0;
0090     uint32_t original_data;
0091     uint32_t addr = 0;
0092     uint32_t extra_shift;
0093 
0094     PP_ASSERT_WITH_CODE((0 == (3 & smc_start_address)), "SMC address must be 4 byte aligned.", return -EINVAL);
0095     PP_ASSERT_WITH_CODE((limit > (smc_start_address + byte_count)), "SMC address is beyond the SMC RAM area.", return -EINVAL);
0096 
0097     addr = smc_start_address;
0098 
0099     while (byte_count >= 4) {
0100     /* Bytes are written into the SMC addres space with the MSB first. */
0101         data = src[0] * 0x1000000 + src[1] * 0x10000 + src[2] * 0x100 + src[3];
0102 
0103         result = smu7_set_smc_sram_address(hwmgr, addr, limit);
0104 
0105         if (0 != result)
0106             return result;
0107 
0108         cgs_write_register(hwmgr->device, mmSMC_IND_DATA_11, data);
0109 
0110         src += 4;
0111         byte_count -= 4;
0112         addr += 4;
0113     }
0114 
0115     if (0 != byte_count) {
0116 
0117         data = 0;
0118 
0119         result = smu7_set_smc_sram_address(hwmgr, addr, limit);
0120 
0121         if (0 != result)
0122             return result;
0123 
0124 
0125         original_data = cgs_read_register(hwmgr->device, mmSMC_IND_DATA_11);
0126 
0127         extra_shift = 8 * (4 - byte_count);
0128 
0129         while (byte_count > 0) {
0130             /* Bytes are written into the SMC addres space with the MSB first. */
0131             data = (0x100 * data) + *src++;
0132             byte_count--;
0133         }
0134 
0135         data <<= extra_shift;
0136 
0137         data |= (original_data & ~((~0UL) << extra_shift));
0138 
0139         result = smu7_set_smc_sram_address(hwmgr, addr, limit);
0140 
0141         if (0 != result)
0142             return result;
0143 
0144         cgs_write_register(hwmgr->device, mmSMC_IND_DATA_11, data);
0145     }
0146 
0147     return 0;
0148 }
0149 
0150 
0151 int smu7_program_jump_on_start(struct pp_hwmgr *hwmgr)
0152 {
0153     static const unsigned char data[4] = { 0xE0, 0x00, 0x80, 0x40 };
0154 
0155     smu7_copy_bytes_to_smc(hwmgr, 0x0, data, 4, sizeof(data)+1);
0156 
0157     return 0;
0158 }
0159 
0160 bool smu7_is_smc_ram_running(struct pp_hwmgr *hwmgr)
0161 {
0162     return ((0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable))
0163     && (0x20100 <= cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMC_PC_C)));
0164 }
0165 
0166 int smu7_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg)
0167 {
0168     struct amdgpu_device *adev = hwmgr->adev;
0169     int ret;
0170 
0171     PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0);
0172 
0173     ret = PHM_READ_FIELD(hwmgr->device, SMC_RESP_0, SMC_RESP);
0174 
0175     if (ret == 0xFE)
0176         dev_dbg(adev->dev, "last message was not supported\n");
0177     else if (ret != 1)
0178         dev_info(adev->dev,
0179             "\nlast message was failed ret is %d\n", ret);
0180 
0181     cgs_write_register(hwmgr->device, mmSMC_RESP_0, 0);
0182     cgs_write_register(hwmgr->device, mmSMC_MESSAGE_0, msg);
0183 
0184     PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0);
0185 
0186     ret = PHM_READ_FIELD(hwmgr->device, SMC_RESP_0, SMC_RESP);
0187 
0188     if (ret == 0xFE)
0189         dev_dbg(adev->dev, "message %x was not supported\n", msg);
0190     else if (ret != 1)
0191         dev_dbg(adev->dev,
0192             "failed to send message %x ret is %d \n",  msg, ret);
0193 
0194     return 0;
0195 }
0196 
0197 int smu7_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, uint16_t msg, uint32_t parameter)
0198 {
0199     PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0);
0200 
0201     cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, parameter);
0202 
0203     return smu7_send_msg_to_smc(hwmgr, msg);
0204 }
0205 
0206 uint32_t smu7_get_argument(struct pp_hwmgr *hwmgr)
0207 {
0208     return cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0);
0209 }
0210 
0211 int smu7_send_msg_to_smc_offset(struct pp_hwmgr *hwmgr)
0212 {
0213     return smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_Test, 0x20000, NULL);
0214 }
0215 
0216 enum cgs_ucode_id smu7_convert_fw_type_to_cgs(uint32_t fw_type)
0217 {
0218     enum cgs_ucode_id result = CGS_UCODE_ID_MAXIMUM;
0219 
0220     switch (fw_type) {
0221     case UCODE_ID_SMU:
0222         result = CGS_UCODE_ID_SMU;
0223         break;
0224     case UCODE_ID_SMU_SK:
0225         result = CGS_UCODE_ID_SMU_SK;
0226         break;
0227     case UCODE_ID_SDMA0:
0228         result = CGS_UCODE_ID_SDMA0;
0229         break;
0230     case UCODE_ID_SDMA1:
0231         result = CGS_UCODE_ID_SDMA1;
0232         break;
0233     case UCODE_ID_CP_CE:
0234         result = CGS_UCODE_ID_CP_CE;
0235         break;
0236     case UCODE_ID_CP_PFP:
0237         result = CGS_UCODE_ID_CP_PFP;
0238         break;
0239     case UCODE_ID_CP_ME:
0240         result = CGS_UCODE_ID_CP_ME;
0241         break;
0242     case UCODE_ID_CP_MEC:
0243         result = CGS_UCODE_ID_CP_MEC;
0244         break;
0245     case UCODE_ID_CP_MEC_JT1:
0246         result = CGS_UCODE_ID_CP_MEC_JT1;
0247         break;
0248     case UCODE_ID_CP_MEC_JT2:
0249         result = CGS_UCODE_ID_CP_MEC_JT2;
0250         break;
0251     case UCODE_ID_RLC_G:
0252         result = CGS_UCODE_ID_RLC_G;
0253         break;
0254     case UCODE_ID_MEC_STORAGE:
0255         result = CGS_UCODE_ID_STORAGE;
0256         break;
0257     default:
0258         break;
0259     }
0260 
0261     return result;
0262 }
0263 
0264 
0265 int smu7_read_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr, uint32_t *value, uint32_t limit)
0266 {
0267     int result;
0268 
0269     result = smu7_set_smc_sram_address(hwmgr, smc_addr, limit);
0270 
0271     *value = result ? 0 : cgs_read_register(hwmgr->device, mmSMC_IND_DATA_11);
0272 
0273     return result;
0274 }
0275 
0276 int smu7_write_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr, uint32_t value, uint32_t limit)
0277 {
0278     int result;
0279 
0280     result = smu7_set_smc_sram_address(hwmgr, smc_addr, limit);
0281 
0282     if (result)
0283         return result;
0284 
0285     cgs_write_register(hwmgr->device, mmSMC_IND_DATA_11, value);
0286 
0287     return 0;
0288 }
0289 
0290 static int smu7_populate_single_firmware_entry(struct pp_hwmgr *hwmgr,
0291                         uint32_t fw_type,
0292                         struct SMU_Entry *entry)
0293 {
0294     int result = 0;
0295     struct cgs_firmware_info info = {0};
0296 
0297     result = cgs_get_firmware_info(hwmgr->device,
0298                 smu7_convert_fw_type_to_cgs(fw_type),
0299                 &info);
0300 
0301     if (!result) {
0302         entry->version = info.fw_version;
0303         entry->id = (uint16_t)fw_type;
0304         entry->image_addr_high = upper_32_bits(info.mc_addr);
0305         entry->image_addr_low = lower_32_bits(info.mc_addr);
0306         entry->meta_data_addr_high = 0;
0307         entry->meta_data_addr_low = 0;
0308 
0309         /* digest need be excluded out */
0310         if (!hwmgr->not_vf)
0311             info.image_size -= 20;
0312         entry->data_size_byte = info.image_size;
0313         entry->num_register_entries = 0;
0314     }
0315 
0316     if ((fw_type == UCODE_ID_RLC_G)
0317         || (fw_type == UCODE_ID_CP_MEC))
0318         entry->flags = 1;
0319     else
0320         entry->flags = 0;
0321 
0322     return 0;
0323 }
0324 
0325 int smu7_request_smu_load_fw(struct pp_hwmgr *hwmgr)
0326 {
0327     struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
0328     uint32_t fw_to_load;
0329     int r = 0;
0330 
0331     amdgpu_ucode_init_bo(hwmgr->adev);
0332 
0333     if (smu_data->soft_regs_start)
0334         cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
0335                     smu_data->soft_regs_start + smum_get_offsetof(hwmgr,
0336                     SMU_SoftRegisters, UcodeLoadStatus),
0337                     0x0);
0338 
0339     if (hwmgr->chip_id > CHIP_TOPAZ) { /* add support for Topaz */
0340         if (hwmgr->not_vf) {
0341             smum_send_msg_to_smc_with_parameter(hwmgr,
0342                         PPSMC_MSG_SMU_DRAM_ADDR_HI,
0343                         upper_32_bits(smu_data->smu_buffer.mc_addr),
0344                         NULL);
0345             smum_send_msg_to_smc_with_parameter(hwmgr,
0346                         PPSMC_MSG_SMU_DRAM_ADDR_LO,
0347                         lower_32_bits(smu_data->smu_buffer.mc_addr),
0348                         NULL);
0349         }
0350         fw_to_load = UCODE_ID_RLC_G_MASK
0351                + UCODE_ID_SDMA0_MASK
0352                + UCODE_ID_SDMA1_MASK
0353                + UCODE_ID_CP_CE_MASK
0354                + UCODE_ID_CP_ME_MASK
0355                + UCODE_ID_CP_PFP_MASK
0356                + UCODE_ID_CP_MEC_MASK;
0357     } else {
0358         fw_to_load = UCODE_ID_RLC_G_MASK
0359                + UCODE_ID_SDMA0_MASK
0360                + UCODE_ID_SDMA1_MASK
0361                + UCODE_ID_CP_CE_MASK
0362                + UCODE_ID_CP_ME_MASK
0363                + UCODE_ID_CP_PFP_MASK
0364                + UCODE_ID_CP_MEC_MASK
0365                + UCODE_ID_CP_MEC_JT1_MASK
0366                + UCODE_ID_CP_MEC_JT2_MASK;
0367     }
0368 
0369     if (!smu_data->toc) {
0370         struct SMU_DRAMData_TOC *toc;
0371 
0372         smu_data->toc = kzalloc(sizeof(struct SMU_DRAMData_TOC), GFP_KERNEL);
0373         if (!smu_data->toc)
0374             return -ENOMEM;
0375         toc = smu_data->toc;
0376         toc->num_entries = 0;
0377         toc->structure_version = 1;
0378 
0379         PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
0380                 UCODE_ID_RLC_G, &toc->entry[toc->num_entries++]),
0381                 "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
0382         PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
0383                 UCODE_ID_CP_CE, &toc->entry[toc->num_entries++]),
0384                 "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
0385         PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
0386                 UCODE_ID_CP_PFP, &toc->entry[toc->num_entries++]),
0387                 "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
0388         PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
0389                 UCODE_ID_CP_ME, &toc->entry[toc->num_entries++]),
0390                 "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
0391         PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
0392                 UCODE_ID_CP_MEC, &toc->entry[toc->num_entries++]),
0393                 "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
0394         PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
0395                 UCODE_ID_CP_MEC_JT1, &toc->entry[toc->num_entries++]),
0396                 "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
0397         PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
0398                 UCODE_ID_CP_MEC_JT2, &toc->entry[toc->num_entries++]),
0399                 "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
0400         PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
0401                 UCODE_ID_SDMA0, &toc->entry[toc->num_entries++]),
0402                 "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
0403         PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
0404                 UCODE_ID_SDMA1, &toc->entry[toc->num_entries++]),
0405                 "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
0406         if (!hwmgr->not_vf)
0407             PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
0408                 UCODE_ID_MEC_STORAGE, &toc->entry[toc->num_entries++]),
0409                 "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
0410     }
0411     memcpy_toio(smu_data->header_buffer.kaddr, smu_data->toc,
0412             sizeof(struct SMU_DRAMData_TOC));
0413     smum_send_msg_to_smc_with_parameter(hwmgr,
0414             PPSMC_MSG_DRV_DRAM_ADDR_HI,
0415             upper_32_bits(smu_data->header_buffer.mc_addr),
0416             NULL);
0417     smum_send_msg_to_smc_with_parameter(hwmgr,
0418             PPSMC_MSG_DRV_DRAM_ADDR_LO,
0419             lower_32_bits(smu_data->header_buffer.mc_addr),
0420             NULL);
0421 
0422     smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_LoadUcodes, fw_to_load, NULL);
0423 
0424     r = smu7_check_fw_load_finish(hwmgr, fw_to_load);
0425     if (!r)
0426         return 0;
0427 
0428     pr_err("SMU load firmware failed\n");
0429 
0430 failed:
0431     kfree(smu_data->toc);
0432     smu_data->toc = NULL;
0433     return r;
0434 }
0435 
0436 /* Check if the FW has been loaded, SMU will not return if loading has not finished. */
0437 int smu7_check_fw_load_finish(struct pp_hwmgr *hwmgr, uint32_t fw_type)
0438 {
0439     struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
0440     uint32_t ret;
0441 
0442     ret = phm_wait_on_indirect_register(hwmgr, mmSMC_IND_INDEX_11,
0443                     smu_data->soft_regs_start + smum_get_offsetof(hwmgr,
0444                     SMU_SoftRegisters, UcodeLoadStatus),
0445                     fw_type, fw_type);
0446     return ret;
0447 }
0448 
0449 int smu7_reload_firmware(struct pp_hwmgr *hwmgr)
0450 {
0451     return hwmgr->smumgr_funcs->start_smu(hwmgr);
0452 }
0453 
0454 static int smu7_upload_smc_firmware_data(struct pp_hwmgr *hwmgr, uint32_t length, uint32_t *src, uint32_t limit)
0455 {
0456     uint32_t byte_count = length;
0457 
0458     PP_ASSERT_WITH_CODE((limit >= byte_count), "SMC address is beyond the SMC RAM area.", return -EINVAL);
0459 
0460     cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_11, 0x20000);
0461     PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 1);
0462 
0463     for (; byte_count >= 4; byte_count -= 4)
0464         cgs_write_register(hwmgr->device, mmSMC_IND_DATA_11, *src++);
0465 
0466     PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 0);
0467 
0468     PP_ASSERT_WITH_CODE((0 == byte_count), "SMC size must be divisible by 4.", return -EINVAL);
0469 
0470     return 0;
0471 }
0472 
0473 
0474 int smu7_upload_smu_firmware_image(struct pp_hwmgr *hwmgr)
0475 {
0476     int result = 0;
0477     struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
0478 
0479     struct cgs_firmware_info info = {0};
0480 
0481     if (smu_data->security_hard_key == 1)
0482         cgs_get_firmware_info(hwmgr->device,
0483             smu7_convert_fw_type_to_cgs(UCODE_ID_SMU), &info);
0484     else
0485         cgs_get_firmware_info(hwmgr->device,
0486             smu7_convert_fw_type_to_cgs(UCODE_ID_SMU_SK), &info);
0487 
0488     hwmgr->is_kicker = info.is_kicker;
0489     hwmgr->smu_version = info.version;
0490     result = smu7_upload_smc_firmware_data(hwmgr, info.image_size, (uint32_t *)info.kptr, SMU7_SMC_SIZE);
0491 
0492     return result;
0493 }
0494 
0495 static void execute_pwr_table(struct pp_hwmgr *hwmgr, const PWR_Command_Table *pvirus, int size)
0496 {
0497     int i;
0498     uint32_t reg, data;
0499 
0500     for (i = 0; i < size; i++) {
0501         reg  = pvirus->reg;
0502         data = pvirus->data;
0503         if (reg != 0xffffffff)
0504             cgs_write_register(hwmgr->device, reg, data);
0505         else
0506             break;
0507         pvirus++;
0508     }
0509 }
0510 
0511 static void execute_pwr_dfy_table(struct pp_hwmgr *hwmgr, const PWR_DFY_Section *section)
0512 {
0513     int i;
0514 
0515     cgs_write_register(hwmgr->device, mmCP_DFY_CNTL, section->dfy_cntl);
0516     cgs_write_register(hwmgr->device, mmCP_DFY_ADDR_HI, section->dfy_addr_hi);
0517     cgs_write_register(hwmgr->device, mmCP_DFY_ADDR_LO, section->dfy_addr_lo);
0518     for (i = 0; i < section->dfy_size; i++)
0519         cgs_write_register(hwmgr->device, mmCP_DFY_DATA_0, section->dfy_data[i]);
0520 }
0521 
0522 int smu7_setup_pwr_virus(struct pp_hwmgr *hwmgr)
0523 {
0524     execute_pwr_table(hwmgr, pwr_virus_table_pre, ARRAY_SIZE(pwr_virus_table_pre));
0525     execute_pwr_dfy_table(hwmgr, &pwr_virus_section1);
0526     execute_pwr_dfy_table(hwmgr, &pwr_virus_section2);
0527     execute_pwr_dfy_table(hwmgr, &pwr_virus_section3);
0528     execute_pwr_dfy_table(hwmgr, &pwr_virus_section4);
0529     execute_pwr_dfy_table(hwmgr, &pwr_virus_section5);
0530     execute_pwr_dfy_table(hwmgr, &pwr_virus_section6);
0531     execute_pwr_table(hwmgr, pwr_virus_table_post, ARRAY_SIZE(pwr_virus_table_post));
0532 
0533     return 0;
0534 }
0535 
0536 int smu7_init(struct pp_hwmgr *hwmgr)
0537 {
0538     struct smu7_smumgr *smu_data;
0539     int r;
0540     /* Allocate memory for backend private data */
0541     smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
0542     smu_data->header_buffer.data_size =
0543             ((sizeof(struct SMU_DRAMData_TOC) / 4096) + 1) * 4096;
0544 
0545 /* Allocate FW image data structure and header buffer and
0546  * send the header buffer address to SMU */
0547     r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0548         smu_data->header_buffer.data_size,
0549         PAGE_SIZE,
0550         AMDGPU_GEM_DOMAIN_VRAM,
0551         &smu_data->header_buffer.handle,
0552         &smu_data->header_buffer.mc_addr,
0553         &smu_data->header_buffer.kaddr);
0554 
0555     if (r)
0556         return -EINVAL;
0557 
0558     if (!hwmgr->not_vf)
0559         return 0;
0560 
0561     smu_data->smu_buffer.data_size = 200*4096;
0562     r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0563         smu_data->smu_buffer.data_size,
0564         PAGE_SIZE,
0565         AMDGPU_GEM_DOMAIN_VRAM,
0566         &smu_data->smu_buffer.handle,
0567         &smu_data->smu_buffer.mc_addr,
0568         &smu_data->smu_buffer.kaddr);
0569 
0570     if (r) {
0571         amdgpu_bo_free_kernel(&smu_data->header_buffer.handle,
0572                     &smu_data->header_buffer.mc_addr,
0573                     &smu_data->header_buffer.kaddr);
0574         return -EINVAL;
0575     }
0576 
0577     if (smum_is_hw_avfs_present(hwmgr) &&
0578         (hwmgr->feature_mask & PP_AVFS_MASK))
0579         hwmgr->avfs_supported = true;
0580 
0581     return 0;
0582 }
0583 
0584 
0585 int smu7_smu_fini(struct pp_hwmgr *hwmgr)
0586 {
0587     struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
0588 
0589     amdgpu_bo_free_kernel(&smu_data->header_buffer.handle,
0590                     &smu_data->header_buffer.mc_addr,
0591                     &smu_data->header_buffer.kaddr);
0592 
0593     if (hwmgr->not_vf)
0594         amdgpu_bo_free_kernel(&smu_data->smu_buffer.handle,
0595                     &smu_data->smu_buffer.mc_addr,
0596                     &smu_data->smu_buffer.kaddr);
0597 
0598 
0599     kfree(smu_data->toc);
0600     smu_data->toc = NULL;
0601     kfree(hwmgr->smu_backend);
0602     hwmgr->smu_backend = NULL;
0603     return 0;
0604 }