linux/drivers/gpu/drm/amd/pm/powerplay/smumgr/smu7_smumgr.c
<<
>>
Prefs
   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
  24
  25#include "pp_debug.h"
  26#include "smumgr.h"
  27#include "smu_ucode_xfer_vi.h"
  28#include "ppatomctrl.h"
  29#include "cgs_common.h"
  30#include "smu7_ppsmc.h"
  31#include "smu7_smumgr.h"
  32#include "smu7_common.h"
  33
  34#include "polaris10_pwrvirus.h"
  35
  36#define SMU7_SMC_SIZE 0x20000
  37
  38static int smu7_set_smc_sram_address(struct pp_hwmgr *hwmgr, uint32_t smc_addr, uint32_t limit)
  39{
  40        PP_ASSERT_WITH_CODE((0 == (3 & smc_addr)), "SMC address must be 4 byte aligned.", return -EINVAL);
  41        PP_ASSERT_WITH_CODE((limit > (smc_addr + 3)), "SMC addr is beyond the SMC RAM area.", return -EINVAL);
  42
  43        cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_11, smc_addr);
  44        PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 0); /* on ci, SMC_IND_ACCESS_CNTL is different */
  45        return 0;
  46}
  47
  48
  49int smu7_copy_bytes_from_smc(struct pp_hwmgr *hwmgr, uint32_t smc_start_address, uint32_t *dest, uint32_t byte_count, uint32_t limit)
  50{
  51        uint32_t data;
  52        uint32_t addr;
  53        uint8_t *dest_byte;
  54        uint8_t i, data_byte[4] = {0};
  55        uint32_t *pdata = (uint32_t *)&data_byte;
  56
  57        PP_ASSERT_WITH_CODE((0 == (3 & smc_start_address)), "SMC address must be 4 byte aligned.", return -EINVAL);
  58        PP_ASSERT_WITH_CODE((limit > (smc_start_address + byte_count)), "SMC address is beyond the SMC RAM area.", return -EINVAL);
  59
  60        addr = smc_start_address;
  61
  62        while (byte_count >= 4) {
  63                smu7_read_smc_sram_dword(hwmgr, addr, &data, limit);
  64
  65                *dest = PP_SMC_TO_HOST_UL(data);
  66
  67                dest += 1;
  68                byte_count -= 4;
  69                addr += 4;
  70        }
  71
  72        if (byte_count) {
  73                smu7_read_smc_sram_dword(hwmgr, addr, &data, limit);
  74                *pdata = PP_SMC_TO_HOST_UL(data);
  75        /* Cast dest into byte type in dest_byte.  This way, we don't overflow if the allocated memory is not 4-byte aligned. */
  76                dest_byte = (uint8_t *)dest;
  77                for (i = 0; i < byte_count; i++)
  78                        dest_byte[i] = data_byte[i];
  79        }
  80
  81        return 0;
  82}
  83
  84
  85int smu7_copy_bytes_to_smc(struct pp_hwmgr *hwmgr, uint32_t smc_start_address,
  86                                const uint8_t *src, uint32_t byte_count, uint32_t limit)
  87{
  88        int result;
  89        uint32_t data = 0;
  90        uint32_t original_data;
  91        uint32_t addr = 0;
  92        uint32_t extra_shift;
  93
  94        PP_ASSERT_WITH_CODE((0 == (3 & smc_start_address)), "SMC address must be 4 byte aligned.", return -EINVAL);
  95        PP_ASSERT_WITH_CODE((limit > (smc_start_address + byte_count)), "SMC address is beyond the SMC RAM area.", return -EINVAL);
  96
  97        addr = smc_start_address;
  98
  99        while (byte_count >= 4) {
 100        /* Bytes are written into the SMC addres space with the MSB first. */
 101                data = src[0] * 0x1000000 + src[1] * 0x10000 + src[2] * 0x100 + src[3];
 102
 103                result = smu7_set_smc_sram_address(hwmgr, addr, limit);
 104
 105                if (0 != result)
 106                        return result;
 107
 108                cgs_write_register(hwmgr->device, mmSMC_IND_DATA_11, data);
 109
 110                src += 4;
 111                byte_count -= 4;
 112                addr += 4;
 113        }
 114
 115        if (0 != byte_count) {
 116
 117                data = 0;
 118
 119                result = smu7_set_smc_sram_address(hwmgr, addr, limit);
 120
 121                if (0 != result)
 122                        return result;
 123
 124
 125                original_data = cgs_read_register(hwmgr->device, mmSMC_IND_DATA_11);
 126
 127                extra_shift = 8 * (4 - byte_count);
 128
 129                while (byte_count > 0) {
 130                        /* Bytes are written into the SMC addres space with the MSB first. */
 131                        data = (0x100 * data) + *src++;
 132                        byte_count--;
 133                }
 134
 135                data <<= extra_shift;
 136
 137                data |= (original_data & ~((~0UL) << extra_shift));
 138
 139                result = smu7_set_smc_sram_address(hwmgr, addr, limit);
 140
 141                if (0 != result)
 142                        return result;
 143
 144                cgs_write_register(hwmgr->device, mmSMC_IND_DATA_11, data);
 145        }
 146
 147        return 0;
 148}
 149
 150
 151int smu7_program_jump_on_start(struct pp_hwmgr *hwmgr)
 152{
 153        static const unsigned char data[4] = { 0xE0, 0x00, 0x80, 0x40 };
 154
 155        smu7_copy_bytes_to_smc(hwmgr, 0x0, data, 4, sizeof(data)+1);
 156
 157        return 0;
 158}
 159
 160bool smu7_is_smc_ram_running(struct pp_hwmgr *hwmgr)
 161{
 162        return ((0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SMC_SYSCON_CLOCK_CNTL_0, ck_disable))
 163        && (0x20100 <= cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMC_PC_C)));
 164}
 165
 166int smu7_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg)
 167{
 168        int ret;
 169
 170        PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0);
 171
 172        ret = PHM_READ_FIELD(hwmgr->device, SMC_RESP_0, SMC_RESP);
 173
 174        if (ret == 0xFE)
 175                pr_debug("last message was not supported\n");
 176        else if (ret != 1)
 177                pr_info("\n last message was failed ret is %d\n", ret);
 178
 179        cgs_write_register(hwmgr->device, mmSMC_RESP_0, 0);
 180        cgs_write_register(hwmgr->device, mmSMC_MESSAGE_0, msg);
 181
 182        PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0);
 183
 184        ret = PHM_READ_FIELD(hwmgr->device, SMC_RESP_0, SMC_RESP);
 185
 186        if (ret == 0xFE)
 187                pr_debug("message %x was not supported\n", msg);
 188        else if (ret != 1)
 189                pr_info("\n failed to send message %x ret is %d \n",  msg, ret);
 190
 191        return 0;
 192}
 193
 194int smu7_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, uint16_t msg, uint32_t parameter)
 195{
 196        PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0);
 197
 198        cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, parameter);
 199
 200        return smu7_send_msg_to_smc(hwmgr, msg);
 201}
 202
 203uint32_t smu7_get_argument(struct pp_hwmgr *hwmgr)
 204{
 205        return cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0);
 206}
 207
 208int smu7_send_msg_to_smc_offset(struct pp_hwmgr *hwmgr)
 209{
 210        return smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_Test, 0x20000, NULL);
 211}
 212
 213enum cgs_ucode_id smu7_convert_fw_type_to_cgs(uint32_t fw_type)
 214{
 215        enum cgs_ucode_id result = CGS_UCODE_ID_MAXIMUM;
 216
 217        switch (fw_type) {
 218        case UCODE_ID_SMU:
 219                result = CGS_UCODE_ID_SMU;
 220                break;
 221        case UCODE_ID_SMU_SK:
 222                result = CGS_UCODE_ID_SMU_SK;
 223                break;
 224        case UCODE_ID_SDMA0:
 225                result = CGS_UCODE_ID_SDMA0;
 226                break;
 227        case UCODE_ID_SDMA1:
 228                result = CGS_UCODE_ID_SDMA1;
 229                break;
 230        case UCODE_ID_CP_CE:
 231                result = CGS_UCODE_ID_CP_CE;
 232                break;
 233        case UCODE_ID_CP_PFP:
 234                result = CGS_UCODE_ID_CP_PFP;
 235                break;
 236        case UCODE_ID_CP_ME:
 237                result = CGS_UCODE_ID_CP_ME;
 238                break;
 239        case UCODE_ID_CP_MEC:
 240                result = CGS_UCODE_ID_CP_MEC;
 241                break;
 242        case UCODE_ID_CP_MEC_JT1:
 243                result = CGS_UCODE_ID_CP_MEC_JT1;
 244                break;
 245        case UCODE_ID_CP_MEC_JT2:
 246                result = CGS_UCODE_ID_CP_MEC_JT2;
 247                break;
 248        case UCODE_ID_RLC_G:
 249                result = CGS_UCODE_ID_RLC_G;
 250                break;
 251        case UCODE_ID_MEC_STORAGE:
 252                result = CGS_UCODE_ID_STORAGE;
 253                break;
 254        default:
 255                break;
 256        }
 257
 258        return result;
 259}
 260
 261
 262int smu7_read_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr, uint32_t *value, uint32_t limit)
 263{
 264        int result;
 265
 266        result = smu7_set_smc_sram_address(hwmgr, smc_addr, limit);
 267
 268        *value = result ? 0 : cgs_read_register(hwmgr->device, mmSMC_IND_DATA_11);
 269
 270        return result;
 271}
 272
 273int smu7_write_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr, uint32_t value, uint32_t limit)
 274{
 275        int result;
 276
 277        result = smu7_set_smc_sram_address(hwmgr, smc_addr, limit);
 278
 279        if (result)
 280                return result;
 281
 282        cgs_write_register(hwmgr->device, mmSMC_IND_DATA_11, value);
 283
 284        return 0;
 285}
 286
 287static int smu7_populate_single_firmware_entry(struct pp_hwmgr *hwmgr,
 288                                                uint32_t fw_type,
 289                                                struct SMU_Entry *entry)
 290{
 291        int result = 0;
 292        struct cgs_firmware_info info = {0};
 293
 294        result = cgs_get_firmware_info(hwmgr->device,
 295                                smu7_convert_fw_type_to_cgs(fw_type),
 296                                &info);
 297
 298        if (!result) {
 299                entry->version = info.fw_version;
 300                entry->id = (uint16_t)fw_type;
 301                entry->image_addr_high = upper_32_bits(info.mc_addr);
 302                entry->image_addr_low = lower_32_bits(info.mc_addr);
 303                entry->meta_data_addr_high = 0;
 304                entry->meta_data_addr_low = 0;
 305
 306                /* digest need be excluded out */
 307                if (!hwmgr->not_vf)
 308                        info.image_size -= 20;
 309                entry->data_size_byte = info.image_size;
 310                entry->num_register_entries = 0;
 311        }
 312
 313        if ((fw_type == UCODE_ID_RLC_G)
 314                || (fw_type == UCODE_ID_CP_MEC))
 315                entry->flags = 1;
 316        else
 317                entry->flags = 0;
 318
 319        return 0;
 320}
 321
 322int smu7_request_smu_load_fw(struct pp_hwmgr *hwmgr)
 323{
 324        struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
 325        uint32_t fw_to_load;
 326        int r = 0;
 327
 328        amdgpu_ucode_init_bo(hwmgr->adev);
 329
 330        if (smu_data->soft_regs_start)
 331                cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
 332                                        smu_data->soft_regs_start + smum_get_offsetof(hwmgr,
 333                                        SMU_SoftRegisters, UcodeLoadStatus),
 334                                        0x0);
 335
 336        if (hwmgr->chip_id > CHIP_TOPAZ) { /* add support for Topaz */
 337                if (hwmgr->not_vf) {
 338                        smum_send_msg_to_smc_with_parameter(hwmgr,
 339                                                PPSMC_MSG_SMU_DRAM_ADDR_HI,
 340                                                upper_32_bits(smu_data->smu_buffer.mc_addr),
 341                                                NULL);
 342                        smum_send_msg_to_smc_with_parameter(hwmgr,
 343                                                PPSMC_MSG_SMU_DRAM_ADDR_LO,
 344                                                lower_32_bits(smu_data->smu_buffer.mc_addr),
 345                                                NULL);
 346                }
 347                fw_to_load = UCODE_ID_RLC_G_MASK
 348                           + UCODE_ID_SDMA0_MASK
 349                           + UCODE_ID_SDMA1_MASK
 350                           + UCODE_ID_CP_CE_MASK
 351                           + UCODE_ID_CP_ME_MASK
 352                           + UCODE_ID_CP_PFP_MASK
 353                           + UCODE_ID_CP_MEC_MASK;
 354        } else {
 355                fw_to_load = UCODE_ID_RLC_G_MASK
 356                           + UCODE_ID_SDMA0_MASK
 357                           + UCODE_ID_SDMA1_MASK
 358                           + UCODE_ID_CP_CE_MASK
 359                           + UCODE_ID_CP_ME_MASK
 360                           + UCODE_ID_CP_PFP_MASK
 361                           + UCODE_ID_CP_MEC_MASK
 362                           + UCODE_ID_CP_MEC_JT1_MASK
 363                           + UCODE_ID_CP_MEC_JT2_MASK;
 364        }
 365
 366        if (!smu_data->toc) {
 367                struct SMU_DRAMData_TOC *toc;
 368
 369                smu_data->toc = kzalloc(sizeof(struct SMU_DRAMData_TOC), GFP_KERNEL);
 370                if (!smu_data->toc)
 371                        return -ENOMEM;
 372                toc = smu_data->toc;
 373                toc->num_entries = 0;
 374                toc->structure_version = 1;
 375
 376                PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
 377                                UCODE_ID_RLC_G, &toc->entry[toc->num_entries++]),
 378                                "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
 379                PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
 380                                UCODE_ID_CP_CE, &toc->entry[toc->num_entries++]),
 381                                "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
 382                PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
 383                                UCODE_ID_CP_PFP, &toc->entry[toc->num_entries++]),
 384                                "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
 385                PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
 386                                UCODE_ID_CP_ME, &toc->entry[toc->num_entries++]),
 387                                "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
 388                PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
 389                                UCODE_ID_CP_MEC, &toc->entry[toc->num_entries++]),
 390                                "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
 391                PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
 392                                UCODE_ID_CP_MEC_JT1, &toc->entry[toc->num_entries++]),
 393                                "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
 394                PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
 395                                UCODE_ID_CP_MEC_JT2, &toc->entry[toc->num_entries++]),
 396                                "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
 397                PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
 398                                UCODE_ID_SDMA0, &toc->entry[toc->num_entries++]),
 399                                "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
 400                PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
 401                                UCODE_ID_SDMA1, &toc->entry[toc->num_entries++]),
 402                                "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
 403                if (!hwmgr->not_vf)
 404                        PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
 405                                UCODE_ID_MEC_STORAGE, &toc->entry[toc->num_entries++]),
 406                                "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
 407        }
 408        memcpy_toio(smu_data->header_buffer.kaddr, smu_data->toc,
 409                    sizeof(struct SMU_DRAMData_TOC));
 410        smum_send_msg_to_smc_with_parameter(hwmgr,
 411                        PPSMC_MSG_DRV_DRAM_ADDR_HI,
 412                        upper_32_bits(smu_data->header_buffer.mc_addr),
 413                        NULL);
 414        smum_send_msg_to_smc_with_parameter(hwmgr,
 415                        PPSMC_MSG_DRV_DRAM_ADDR_LO,
 416                        lower_32_bits(smu_data->header_buffer.mc_addr),
 417                        NULL);
 418
 419        smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_LoadUcodes, fw_to_load, NULL);
 420
 421        r = smu7_check_fw_load_finish(hwmgr, fw_to_load);
 422        if (!r)
 423                return 0;
 424
 425        pr_err("SMU load firmware failed\n");
 426
 427failed:
 428        kfree(smu_data->toc);
 429        smu_data->toc = NULL;
 430        return r;
 431}
 432
 433/* Check if the FW has been loaded, SMU will not return if loading has not finished. */
 434int smu7_check_fw_load_finish(struct pp_hwmgr *hwmgr, uint32_t fw_type)
 435{
 436        struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
 437        uint32_t ret;
 438
 439        ret = phm_wait_on_indirect_register(hwmgr, mmSMC_IND_INDEX_11,
 440                                        smu_data->soft_regs_start + smum_get_offsetof(hwmgr,
 441                                        SMU_SoftRegisters, UcodeLoadStatus),
 442                                        fw_type, fw_type);
 443        return ret;
 444}
 445
 446int smu7_reload_firmware(struct pp_hwmgr *hwmgr)
 447{
 448        return hwmgr->smumgr_funcs->start_smu(hwmgr);
 449}
 450
 451static int smu7_upload_smc_firmware_data(struct pp_hwmgr *hwmgr, uint32_t length, uint32_t *src, uint32_t limit)
 452{
 453        uint32_t byte_count = length;
 454
 455        PP_ASSERT_WITH_CODE((limit >= byte_count), "SMC address is beyond the SMC RAM area.", return -EINVAL);
 456
 457        cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_11, 0x20000);
 458        PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 1);
 459
 460        for (; byte_count >= 4; byte_count -= 4)
 461                cgs_write_register(hwmgr->device, mmSMC_IND_DATA_11, *src++);
 462
 463        PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 0);
 464
 465        PP_ASSERT_WITH_CODE((0 == byte_count), "SMC size must be divisible by 4.", return -EINVAL);
 466
 467        return 0;
 468}
 469
 470
 471int smu7_upload_smu_firmware_image(struct pp_hwmgr *hwmgr)
 472{
 473        int result = 0;
 474        struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
 475
 476        struct cgs_firmware_info info = {0};
 477
 478        if (smu_data->security_hard_key == 1)
 479                cgs_get_firmware_info(hwmgr->device,
 480                        smu7_convert_fw_type_to_cgs(UCODE_ID_SMU), &info);
 481        else
 482                cgs_get_firmware_info(hwmgr->device,
 483                        smu7_convert_fw_type_to_cgs(UCODE_ID_SMU_SK), &info);
 484
 485        hwmgr->is_kicker = info.is_kicker;
 486        hwmgr->smu_version = info.version;
 487        result = smu7_upload_smc_firmware_data(hwmgr, info.image_size, (uint32_t *)info.kptr, SMU7_SMC_SIZE);
 488
 489        return result;
 490}
 491
 492static void execute_pwr_table(struct pp_hwmgr *hwmgr, const PWR_Command_Table *pvirus, int size)
 493{
 494        int i;
 495        uint32_t reg, data;
 496
 497        for (i = 0; i < size; i++) {
 498                reg  = pvirus->reg;
 499                data = pvirus->data;
 500                if (reg != 0xffffffff)
 501                        cgs_write_register(hwmgr->device, reg, data);
 502                else
 503                        break;
 504                pvirus++;
 505        }
 506}
 507
 508static void execute_pwr_dfy_table(struct pp_hwmgr *hwmgr, const PWR_DFY_Section *section)
 509{
 510        int i;
 511
 512        cgs_write_register(hwmgr->device, mmCP_DFY_CNTL, section->dfy_cntl);
 513        cgs_write_register(hwmgr->device, mmCP_DFY_ADDR_HI, section->dfy_addr_hi);
 514        cgs_write_register(hwmgr->device, mmCP_DFY_ADDR_LO, section->dfy_addr_lo);
 515        for (i = 0; i < section->dfy_size; i++)
 516                cgs_write_register(hwmgr->device, mmCP_DFY_DATA_0, section->dfy_data[i]);
 517}
 518
 519int smu7_setup_pwr_virus(struct pp_hwmgr *hwmgr)
 520{
 521        execute_pwr_table(hwmgr, pwr_virus_table_pre, ARRAY_SIZE(pwr_virus_table_pre));
 522        execute_pwr_dfy_table(hwmgr, &pwr_virus_section1);
 523        execute_pwr_dfy_table(hwmgr, &pwr_virus_section2);
 524        execute_pwr_dfy_table(hwmgr, &pwr_virus_section3);
 525        execute_pwr_dfy_table(hwmgr, &pwr_virus_section4);
 526        execute_pwr_dfy_table(hwmgr, &pwr_virus_section5);
 527        execute_pwr_dfy_table(hwmgr, &pwr_virus_section6);
 528        execute_pwr_table(hwmgr, pwr_virus_table_post, ARRAY_SIZE(pwr_virus_table_post));
 529
 530        return 0;
 531}
 532
 533int smu7_init(struct pp_hwmgr *hwmgr)
 534{
 535        struct smu7_smumgr *smu_data;
 536        int r;
 537        /* Allocate memory for backend private data */
 538        smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
 539        smu_data->header_buffer.data_size =
 540                        ((sizeof(struct SMU_DRAMData_TOC) / 4096) + 1) * 4096;
 541
 542/* Allocate FW image data structure and header buffer and
 543 * send the header buffer address to SMU */
 544        r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
 545                smu_data->header_buffer.data_size,
 546                PAGE_SIZE,
 547                AMDGPU_GEM_DOMAIN_VRAM,
 548                &smu_data->header_buffer.handle,
 549                &smu_data->header_buffer.mc_addr,
 550                &smu_data->header_buffer.kaddr);
 551
 552        if (r)
 553                return -EINVAL;
 554
 555        if (!hwmgr->not_vf)
 556                return 0;
 557
 558        smu_data->smu_buffer.data_size = 200*4096;
 559        r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
 560                smu_data->smu_buffer.data_size,
 561                PAGE_SIZE,
 562                AMDGPU_GEM_DOMAIN_VRAM,
 563                &smu_data->smu_buffer.handle,
 564                &smu_data->smu_buffer.mc_addr,
 565                &smu_data->smu_buffer.kaddr);
 566
 567        if (r) {
 568                amdgpu_bo_free_kernel(&smu_data->header_buffer.handle,
 569                                        &smu_data->header_buffer.mc_addr,
 570                                        &smu_data->header_buffer.kaddr);
 571                return -EINVAL;
 572        }
 573
 574        if (smum_is_hw_avfs_present(hwmgr) &&
 575            (hwmgr->feature_mask & PP_AVFS_MASK))
 576                hwmgr->avfs_supported = true;
 577
 578        return 0;
 579}
 580
 581
 582int smu7_smu_fini(struct pp_hwmgr *hwmgr)
 583{
 584        struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
 585
 586        amdgpu_bo_free_kernel(&smu_data->header_buffer.handle,
 587                                        &smu_data->header_buffer.mc_addr,
 588                                        &smu_data->header_buffer.kaddr);
 589
 590        if (hwmgr->not_vf)
 591                amdgpu_bo_free_kernel(&smu_data->smu_buffer.handle,
 592                                        &smu_data->smu_buffer.mc_addr,
 593                                        &smu_data->smu_buffer.kaddr);
 594
 595
 596        kfree(smu_data->toc);
 597        smu_data->toc = NULL;
 598        kfree(hwmgr->smu_backend);
 599        hwmgr->smu_backend = NULL;
 600        return 0;
 601}
 602