linux/drivers/gpu/drm/amd/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_without_waiting(struct pp_hwmgr *hwmgr, uint16_t msg)
 195{
 196        cgs_write_register(hwmgr->device, mmSMC_MESSAGE_0, msg);
 197
 198        return 0;
 199}
 200
 201int smu7_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr, uint16_t msg, uint32_t parameter)
 202{
 203        PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0);
 204
 205        cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, parameter);
 206
 207        return smu7_send_msg_to_smc(hwmgr, msg);
 208}
 209
 210int smu7_send_msg_to_smc_with_parameter_without_waiting(struct pp_hwmgr *hwmgr, uint16_t msg, uint32_t parameter)
 211{
 212        cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, parameter);
 213
 214        return smu7_send_msg_to_smc_without_waiting(hwmgr, msg);
 215}
 216
 217int smu7_send_msg_to_smc_offset(struct pp_hwmgr *hwmgr)
 218{
 219        cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, 0x20000);
 220
 221        cgs_write_register(hwmgr->device, mmSMC_MESSAGE_0, PPSMC_MSG_Test);
 222
 223        PHM_WAIT_FIELD_UNEQUAL(hwmgr, SMC_RESP_0, SMC_RESP, 0);
 224
 225        if (1 != PHM_READ_FIELD(hwmgr->device, SMC_RESP_0, SMC_RESP))
 226                pr_info("Failed to send Message.\n");
 227
 228        return 0;
 229}
 230
 231enum cgs_ucode_id smu7_convert_fw_type_to_cgs(uint32_t fw_type)
 232{
 233        enum cgs_ucode_id result = CGS_UCODE_ID_MAXIMUM;
 234
 235        switch (fw_type) {
 236        case UCODE_ID_SMU:
 237                result = CGS_UCODE_ID_SMU;
 238                break;
 239        case UCODE_ID_SMU_SK:
 240                result = CGS_UCODE_ID_SMU_SK;
 241                break;
 242        case UCODE_ID_SDMA0:
 243                result = CGS_UCODE_ID_SDMA0;
 244                break;
 245        case UCODE_ID_SDMA1:
 246                result = CGS_UCODE_ID_SDMA1;
 247                break;
 248        case UCODE_ID_CP_CE:
 249                result = CGS_UCODE_ID_CP_CE;
 250                break;
 251        case UCODE_ID_CP_PFP:
 252                result = CGS_UCODE_ID_CP_PFP;
 253                break;
 254        case UCODE_ID_CP_ME:
 255                result = CGS_UCODE_ID_CP_ME;
 256                break;
 257        case UCODE_ID_CP_MEC:
 258                result = CGS_UCODE_ID_CP_MEC;
 259                break;
 260        case UCODE_ID_CP_MEC_JT1:
 261                result = CGS_UCODE_ID_CP_MEC_JT1;
 262                break;
 263        case UCODE_ID_CP_MEC_JT2:
 264                result = CGS_UCODE_ID_CP_MEC_JT2;
 265                break;
 266        case UCODE_ID_RLC_G:
 267                result = CGS_UCODE_ID_RLC_G;
 268                break;
 269        case UCODE_ID_MEC_STORAGE:
 270                result = CGS_UCODE_ID_STORAGE;
 271                break;
 272        default:
 273                break;
 274        }
 275
 276        return result;
 277}
 278
 279
 280int smu7_read_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr, uint32_t *value, uint32_t limit)
 281{
 282        int result;
 283
 284        result = smu7_set_smc_sram_address(hwmgr, smc_addr, limit);
 285
 286        *value = result ? 0 : cgs_read_register(hwmgr->device, mmSMC_IND_DATA_11);
 287
 288        return result;
 289}
 290
 291int smu7_write_smc_sram_dword(struct pp_hwmgr *hwmgr, uint32_t smc_addr, uint32_t value, uint32_t limit)
 292{
 293        int result;
 294
 295        result = smu7_set_smc_sram_address(hwmgr, smc_addr, limit);
 296
 297        if (result)
 298                return result;
 299
 300        cgs_write_register(hwmgr->device, mmSMC_IND_DATA_11, value);
 301
 302        return 0;
 303}
 304
 305static int smu7_populate_single_firmware_entry(struct pp_hwmgr *hwmgr,
 306                                                uint32_t fw_type,
 307                                                struct SMU_Entry *entry)
 308{
 309        int result = 0;
 310        struct cgs_firmware_info info = {0};
 311
 312        result = cgs_get_firmware_info(hwmgr->device,
 313                                smu7_convert_fw_type_to_cgs(fw_type),
 314                                &info);
 315
 316        if (!result) {
 317                entry->version = info.fw_version;
 318                entry->id = (uint16_t)fw_type;
 319                entry->image_addr_high = upper_32_bits(info.mc_addr);
 320                entry->image_addr_low = lower_32_bits(info.mc_addr);
 321                entry->meta_data_addr_high = 0;
 322                entry->meta_data_addr_low = 0;
 323
 324                /* digest need be excluded out */
 325                if (!hwmgr->not_vf)
 326                        info.image_size -= 20;
 327                entry->data_size_byte = info.image_size;
 328                entry->num_register_entries = 0;
 329        }
 330
 331        if ((fw_type == UCODE_ID_RLC_G)
 332                || (fw_type == UCODE_ID_CP_MEC))
 333                entry->flags = 1;
 334        else
 335                entry->flags = 0;
 336
 337        return 0;
 338}
 339
 340int smu7_request_smu_load_fw(struct pp_hwmgr *hwmgr)
 341{
 342        struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
 343        uint32_t fw_to_load;
 344        int r = 0;
 345
 346        amdgpu_ucode_init_bo(hwmgr->adev);
 347
 348        if (smu_data->soft_regs_start)
 349                cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC,
 350                                        smu_data->soft_regs_start + smum_get_offsetof(hwmgr,
 351                                        SMU_SoftRegisters, UcodeLoadStatus),
 352                                        0x0);
 353
 354        if (hwmgr->chip_id > CHIP_TOPAZ) { /* add support for Topaz */
 355                if (hwmgr->not_vf) {
 356                        smu7_send_msg_to_smc_with_parameter(hwmgr,
 357                                                PPSMC_MSG_SMU_DRAM_ADDR_HI,
 358                                                upper_32_bits(smu_data->smu_buffer.mc_addr));
 359                        smu7_send_msg_to_smc_with_parameter(hwmgr,
 360                                                PPSMC_MSG_SMU_DRAM_ADDR_LO,
 361                                                lower_32_bits(smu_data->smu_buffer.mc_addr));
 362                }
 363                fw_to_load = UCODE_ID_RLC_G_MASK
 364                           + UCODE_ID_SDMA0_MASK
 365                           + UCODE_ID_SDMA1_MASK
 366                           + UCODE_ID_CP_CE_MASK
 367                           + UCODE_ID_CP_ME_MASK
 368                           + UCODE_ID_CP_PFP_MASK
 369                           + UCODE_ID_CP_MEC_MASK;
 370        } else {
 371                fw_to_load = UCODE_ID_RLC_G_MASK
 372                           + UCODE_ID_SDMA0_MASK
 373                           + UCODE_ID_SDMA1_MASK
 374                           + UCODE_ID_CP_CE_MASK
 375                           + UCODE_ID_CP_ME_MASK
 376                           + UCODE_ID_CP_PFP_MASK
 377                           + UCODE_ID_CP_MEC_MASK
 378                           + UCODE_ID_CP_MEC_JT1_MASK
 379                           + UCODE_ID_CP_MEC_JT2_MASK;
 380        }
 381
 382        if (!smu_data->toc) {
 383                struct SMU_DRAMData_TOC *toc;
 384
 385                smu_data->toc = kzalloc(sizeof(struct SMU_DRAMData_TOC), GFP_KERNEL);
 386                if (!smu_data->toc)
 387                        return -ENOMEM;
 388                toc = smu_data->toc;
 389                toc->num_entries = 0;
 390                toc->structure_version = 1;
 391
 392                PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
 393                                UCODE_ID_RLC_G, &toc->entry[toc->num_entries++]),
 394                                "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
 395                PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
 396                                UCODE_ID_CP_CE, &toc->entry[toc->num_entries++]),
 397                                "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
 398                PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
 399                                UCODE_ID_CP_PFP, &toc->entry[toc->num_entries++]),
 400                                "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
 401                PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
 402                                UCODE_ID_CP_ME, &toc->entry[toc->num_entries++]),
 403                                "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
 404                PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
 405                                UCODE_ID_CP_MEC, &toc->entry[toc->num_entries++]),
 406                                "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
 407                PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
 408                                UCODE_ID_CP_MEC_JT1, &toc->entry[toc->num_entries++]),
 409                                "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
 410                PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
 411                                UCODE_ID_CP_MEC_JT2, &toc->entry[toc->num_entries++]),
 412                                "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
 413                PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
 414                                UCODE_ID_SDMA0, &toc->entry[toc->num_entries++]),
 415                                "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
 416                PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
 417                                UCODE_ID_SDMA1, &toc->entry[toc->num_entries++]),
 418                                "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
 419                if (!hwmgr->not_vf)
 420                        PP_ASSERT_WITH_CODE(0 == smu7_populate_single_firmware_entry(hwmgr,
 421                                UCODE_ID_MEC_STORAGE, &toc->entry[toc->num_entries++]),
 422                                "Failed to Get Firmware Entry.", r = -EINVAL; goto failed);
 423        }
 424        memcpy_toio(smu_data->header_buffer.kaddr, smu_data->toc,
 425                    sizeof(struct SMU_DRAMData_TOC));
 426        smu7_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_DRV_DRAM_ADDR_HI, upper_32_bits(smu_data->header_buffer.mc_addr));
 427        smu7_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_DRV_DRAM_ADDR_LO, lower_32_bits(smu_data->header_buffer.mc_addr));
 428
 429        smu7_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_LoadUcodes, fw_to_load);
 430
 431        r = smu7_check_fw_load_finish(hwmgr, fw_to_load);
 432        if (!r)
 433                return 0;
 434
 435        pr_err("SMU load firmware failed\n");
 436
 437failed:
 438        kfree(smu_data->toc);
 439        smu_data->toc = NULL;
 440        return r;
 441}
 442
 443/* Check if the FW has been loaded, SMU will not return if loading has not finished. */
 444int smu7_check_fw_load_finish(struct pp_hwmgr *hwmgr, uint32_t fw_type)
 445{
 446        struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
 447        uint32_t ret;
 448
 449        ret = phm_wait_on_indirect_register(hwmgr, mmSMC_IND_INDEX_11,
 450                                        smu_data->soft_regs_start + smum_get_offsetof(hwmgr,
 451                                        SMU_SoftRegisters, UcodeLoadStatus),
 452                                        fw_type, fw_type);
 453        return ret;
 454}
 455
 456int smu7_reload_firmware(struct pp_hwmgr *hwmgr)
 457{
 458        return hwmgr->smumgr_funcs->start_smu(hwmgr);
 459}
 460
 461static int smu7_upload_smc_firmware_data(struct pp_hwmgr *hwmgr, uint32_t length, uint32_t *src, uint32_t limit)
 462{
 463        uint32_t byte_count = length;
 464
 465        PP_ASSERT_WITH_CODE((limit >= byte_count), "SMC address is beyond the SMC RAM area.", return -EINVAL);
 466
 467        cgs_write_register(hwmgr->device, mmSMC_IND_INDEX_11, 0x20000);
 468        PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 1);
 469
 470        for (; byte_count >= 4; byte_count -= 4)
 471                cgs_write_register(hwmgr->device, mmSMC_IND_DATA_11, *src++);
 472
 473        PHM_WRITE_FIELD(hwmgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 0);
 474
 475        PP_ASSERT_WITH_CODE((0 == byte_count), "SMC size must be divisible by 4.", return -EINVAL);
 476
 477        return 0;
 478}
 479
 480
 481int smu7_upload_smu_firmware_image(struct pp_hwmgr *hwmgr)
 482{
 483        int result = 0;
 484        struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
 485
 486        struct cgs_firmware_info info = {0};
 487
 488        if (smu_data->security_hard_key == 1)
 489                cgs_get_firmware_info(hwmgr->device,
 490                        smu7_convert_fw_type_to_cgs(UCODE_ID_SMU), &info);
 491        else
 492                cgs_get_firmware_info(hwmgr->device,
 493                        smu7_convert_fw_type_to_cgs(UCODE_ID_SMU_SK), &info);
 494
 495        hwmgr->is_kicker = info.is_kicker;
 496        hwmgr->smu_version = info.version;
 497        result = smu7_upload_smc_firmware_data(hwmgr, info.image_size, (uint32_t *)info.kptr, SMU7_SMC_SIZE);
 498
 499        return result;
 500}
 501
 502static void execute_pwr_table(struct pp_hwmgr *hwmgr, const PWR_Command_Table *pvirus, int size)
 503{
 504        int i;
 505        uint32_t reg, data;
 506
 507        for (i = 0; i < size; i++) {
 508                reg  = pvirus->reg;
 509                data = pvirus->data;
 510                if (reg != 0xffffffff)
 511                        cgs_write_register(hwmgr->device, reg, data);
 512                else
 513                        break;
 514                pvirus++;
 515        }
 516}
 517
 518static void execute_pwr_dfy_table(struct pp_hwmgr *hwmgr, const PWR_DFY_Section *section)
 519{
 520        int i;
 521
 522        cgs_write_register(hwmgr->device, mmCP_DFY_CNTL, section->dfy_cntl);
 523        cgs_write_register(hwmgr->device, mmCP_DFY_ADDR_HI, section->dfy_addr_hi);
 524        cgs_write_register(hwmgr->device, mmCP_DFY_ADDR_LO, section->dfy_addr_lo);
 525        for (i = 0; i < section->dfy_size; i++)
 526                cgs_write_register(hwmgr->device, mmCP_DFY_DATA_0, section->dfy_data[i]);
 527}
 528
 529int smu7_setup_pwr_virus(struct pp_hwmgr *hwmgr)
 530{
 531        execute_pwr_table(hwmgr, pwr_virus_table_pre, ARRAY_SIZE(pwr_virus_table_pre));
 532        execute_pwr_dfy_table(hwmgr, &pwr_virus_section1);
 533        execute_pwr_dfy_table(hwmgr, &pwr_virus_section2);
 534        execute_pwr_dfy_table(hwmgr, &pwr_virus_section3);
 535        execute_pwr_dfy_table(hwmgr, &pwr_virus_section4);
 536        execute_pwr_dfy_table(hwmgr, &pwr_virus_section5);
 537        execute_pwr_dfy_table(hwmgr, &pwr_virus_section6);
 538        execute_pwr_table(hwmgr, pwr_virus_table_post, ARRAY_SIZE(pwr_virus_table_post));
 539
 540        return 0;
 541}
 542
 543int smu7_init(struct pp_hwmgr *hwmgr)
 544{
 545        struct smu7_smumgr *smu_data;
 546        int r;
 547        /* Allocate memory for backend private data */
 548        smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
 549        smu_data->header_buffer.data_size =
 550                        ((sizeof(struct SMU_DRAMData_TOC) / 4096) + 1) * 4096;
 551
 552/* Allocate FW image data structure and header buffer and
 553 * send the header buffer address to SMU */
 554        r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
 555                smu_data->header_buffer.data_size,
 556                PAGE_SIZE,
 557                AMDGPU_GEM_DOMAIN_VRAM,
 558                &smu_data->header_buffer.handle,
 559                &smu_data->header_buffer.mc_addr,
 560                &smu_data->header_buffer.kaddr);
 561
 562        if (r)
 563                return -EINVAL;
 564
 565        if (!hwmgr->not_vf)
 566                return 0;
 567
 568        smu_data->smu_buffer.data_size = 200*4096;
 569        r = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
 570                smu_data->smu_buffer.data_size,
 571                PAGE_SIZE,
 572                AMDGPU_GEM_DOMAIN_VRAM,
 573                &smu_data->smu_buffer.handle,
 574                &smu_data->smu_buffer.mc_addr,
 575                &smu_data->smu_buffer.kaddr);
 576
 577        if (r) {
 578                amdgpu_bo_free_kernel(&smu_data->header_buffer.handle,
 579                                        &smu_data->header_buffer.mc_addr,
 580                                        &smu_data->header_buffer.kaddr);
 581                return -EINVAL;
 582        }
 583
 584        if (smum_is_hw_avfs_present(hwmgr) &&
 585            (hwmgr->feature_mask & PP_AVFS_MASK))
 586                hwmgr->avfs_supported = true;
 587
 588        return 0;
 589}
 590
 591
 592int smu7_smu_fini(struct pp_hwmgr *hwmgr)
 593{
 594        struct smu7_smumgr *smu_data = (struct smu7_smumgr *)(hwmgr->smu_backend);
 595
 596        amdgpu_bo_free_kernel(&smu_data->header_buffer.handle,
 597                                        &smu_data->header_buffer.mc_addr,
 598                                        &smu_data->header_buffer.kaddr);
 599
 600        if (hwmgr->not_vf)
 601                amdgpu_bo_free_kernel(&smu_data->smu_buffer.handle,
 602                                        &smu_data->smu_buffer.mc_addr,
 603                                        &smu_data->smu_buffer.kaddr);
 604
 605
 606        kfree(smu_data->toc);
 607        smu_data->toc = NULL;
 608        kfree(hwmgr->smu_backend);
 609        hwmgr->smu_backend = NULL;
 610        return 0;
 611}
 612