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 #include <linux/delay.h>
0025 #include <linux/gfp.h>
0026 #include <linux/kernel.h>
0027 #include <linux/ktime.h>
0028 #include <linux/slab.h>
0029 #include <linux/types.h>
0030 
0031 #include "cgs_common.h"
0032 #include "smu/smu_8_0_d.h"
0033 #include "smu/smu_8_0_sh_mask.h"
0034 #include "smu8.h"
0035 #include "smu8_fusion.h"
0036 #include "smu8_smumgr.h"
0037 #include "cz_ppsmc.h"
0038 #include "smu_ucode_xfer_cz.h"
0039 #include "gca/gfx_8_0_d.h"
0040 #include "gca/gfx_8_0_sh_mask.h"
0041 #include "smumgr.h"
0042 
0043 #define SIZE_ALIGN_32(x)    (((x) + 31) / 32 * 32)
0044 
0045 static const enum smu8_scratch_entry firmware_list[] = {
0046     SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA0,
0047     SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA1,
0048     SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE,
0049     SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP,
0050     SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME,
0051     SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1,
0052     SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2,
0053     SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G,
0054 };
0055 
0056 static uint32_t smu8_get_argument(struct pp_hwmgr *hwmgr)
0057 {
0058     if (hwmgr == NULL || hwmgr->device == NULL)
0059         return 0;
0060 
0061     return cgs_read_register(hwmgr->device,
0062                     mmSMU_MP1_SRBM2P_ARG_0);
0063 }
0064 
0065 /* Send a message to the SMC, and wait for its response.*/
0066 static int smu8_send_msg_to_smc_with_parameter(struct pp_hwmgr *hwmgr,
0067                         uint16_t msg, uint32_t parameter)
0068 {
0069     int result = 0;
0070     ktime_t t_start;
0071     s64 elapsed_us;
0072 
0073     if (hwmgr == NULL || hwmgr->device == NULL)
0074         return -EINVAL;
0075 
0076     result = PHM_WAIT_FIELD_UNEQUAL(hwmgr,
0077                     SMU_MP1_SRBM2P_RESP_0, CONTENT, 0);
0078     if (result != 0) {
0079         /* Read the last message to SMU, to report actual cause */
0080         uint32_t val = cgs_read_register(hwmgr->device,
0081                          mmSMU_MP1_SRBM2P_MSG_0);
0082         pr_err("%s(0x%04x) aborted; SMU still servicing msg (0x%04x)\n",
0083             __func__, msg, val);
0084         return result;
0085     }
0086     t_start = ktime_get();
0087 
0088     cgs_write_register(hwmgr->device, mmSMU_MP1_SRBM2P_ARG_0, parameter);
0089 
0090     cgs_write_register(hwmgr->device, mmSMU_MP1_SRBM2P_RESP_0, 0);
0091     cgs_write_register(hwmgr->device, mmSMU_MP1_SRBM2P_MSG_0, msg);
0092 
0093     result = PHM_WAIT_FIELD_UNEQUAL(hwmgr,
0094                     SMU_MP1_SRBM2P_RESP_0, CONTENT, 0);
0095 
0096     elapsed_us = ktime_us_delta(ktime_get(), t_start);
0097 
0098     WARN(result, "%s(0x%04x, %#x) timed out after %lld us\n",
0099             __func__, msg, parameter, elapsed_us);
0100 
0101     return result;
0102 }
0103 
0104 static int smu8_send_msg_to_smc(struct pp_hwmgr *hwmgr, uint16_t msg)
0105 {
0106     return smu8_send_msg_to_smc_with_parameter(hwmgr, msg, 0);
0107 }
0108 
0109 static int smu8_set_smc_sram_address(struct pp_hwmgr *hwmgr,
0110                      uint32_t smc_address, uint32_t limit)
0111 {
0112     if (hwmgr == NULL || hwmgr->device == NULL)
0113         return -EINVAL;
0114 
0115     if (0 != (3 & smc_address)) {
0116         pr_err("SMC address must be 4 byte aligned\n");
0117         return -EINVAL;
0118     }
0119 
0120     if (limit <= (smc_address + 3)) {
0121         pr_err("SMC address beyond the SMC RAM area\n");
0122         return -EINVAL;
0123     }
0124 
0125     cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX_0,
0126                 SMN_MP1_SRAM_START_ADDR + smc_address);
0127 
0128     return 0;
0129 }
0130 
0131 static int smu8_write_smc_sram_dword(struct pp_hwmgr *hwmgr,
0132         uint32_t smc_address, uint32_t value, uint32_t limit)
0133 {
0134     int result;
0135 
0136     if (hwmgr == NULL || hwmgr->device == NULL)
0137         return -EINVAL;
0138 
0139     result = smu8_set_smc_sram_address(hwmgr, smc_address, limit);
0140     if (!result)
0141         cgs_write_register(hwmgr->device, mmMP0PUB_IND_DATA_0, value);
0142 
0143     return result;
0144 }
0145 
0146 static int smu8_check_fw_load_finish(struct pp_hwmgr *hwmgr,
0147                    uint32_t firmware)
0148 {
0149     int i;
0150     uint32_t index = SMN_MP1_SRAM_START_ADDR +
0151              SMU8_FIRMWARE_HEADER_LOCATION +
0152              offsetof(struct SMU8_Firmware_Header, UcodeLoadStatus);
0153 
0154     if (hwmgr == NULL || hwmgr->device == NULL)
0155         return -EINVAL;
0156 
0157     cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index);
0158 
0159     for (i = 0; i < hwmgr->usec_timeout; i++) {
0160         if (firmware ==
0161             (cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA) & firmware))
0162             break;
0163         udelay(1);
0164     }
0165 
0166     if (i >= hwmgr->usec_timeout) {
0167         pr_err("SMU check loaded firmware failed.\n");
0168         return -EINVAL;
0169     }
0170 
0171     return 0;
0172 }
0173 
0174 static int smu8_load_mec_firmware(struct pp_hwmgr *hwmgr)
0175 {
0176     uint32_t reg_data;
0177     uint32_t tmp;
0178     int ret = 0;
0179     struct cgs_firmware_info info = {0};
0180 
0181     if (hwmgr == NULL || hwmgr->device == NULL)
0182         return -EINVAL;
0183 
0184     ret = cgs_get_firmware_info(hwmgr->device,
0185                         CGS_UCODE_ID_CP_MEC, &info);
0186 
0187     if (ret)
0188         return -EINVAL;
0189 
0190     /* Disable MEC parsing/prefetching */
0191     tmp = cgs_read_register(hwmgr->device,
0192                     mmCP_MEC_CNTL);
0193     tmp = PHM_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME1_HALT, 1);
0194     tmp = PHM_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME2_HALT, 1);
0195     cgs_write_register(hwmgr->device, mmCP_MEC_CNTL, tmp);
0196 
0197     tmp = cgs_read_register(hwmgr->device,
0198                     mmCP_CPC_IC_BASE_CNTL);
0199 
0200     tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, VMID, 0);
0201     tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, ATC, 0);
0202     tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, CACHE_POLICY, 0);
0203     tmp = PHM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, MTYPE, 1);
0204     cgs_write_register(hwmgr->device, mmCP_CPC_IC_BASE_CNTL, tmp);
0205 
0206     reg_data = lower_32_bits(info.mc_addr) &
0207             PHM_FIELD_MASK(CP_CPC_IC_BASE_LO, IC_BASE_LO);
0208     cgs_write_register(hwmgr->device, mmCP_CPC_IC_BASE_LO, reg_data);
0209 
0210     reg_data = upper_32_bits(info.mc_addr) &
0211             PHM_FIELD_MASK(CP_CPC_IC_BASE_HI, IC_BASE_HI);
0212     cgs_write_register(hwmgr->device, mmCP_CPC_IC_BASE_HI, reg_data);
0213 
0214     return 0;
0215 }
0216 
0217 static uint8_t smu8_translate_firmware_enum_to_arg(struct pp_hwmgr *hwmgr,
0218             enum smu8_scratch_entry firmware_enum)
0219 {
0220     uint8_t ret = 0;
0221 
0222     switch (firmware_enum) {
0223     case SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA0:
0224         ret = UCODE_ID_SDMA0;
0225         break;
0226     case SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA1:
0227         if (hwmgr->chip_id == CHIP_STONEY)
0228             ret = UCODE_ID_SDMA0;
0229         else
0230             ret = UCODE_ID_SDMA1;
0231         break;
0232     case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE:
0233         ret = UCODE_ID_CP_CE;
0234         break;
0235     case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP:
0236         ret = UCODE_ID_CP_PFP;
0237         break;
0238     case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME:
0239         ret = UCODE_ID_CP_ME;
0240         break;
0241     case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1:
0242         ret = UCODE_ID_CP_MEC_JT1;
0243         break;
0244     case SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2:
0245         if (hwmgr->chip_id == CHIP_STONEY)
0246             ret = UCODE_ID_CP_MEC_JT1;
0247         else
0248             ret = UCODE_ID_CP_MEC_JT2;
0249         break;
0250     case SMU8_SCRATCH_ENTRY_UCODE_ID_GMCON_RENG:
0251         ret = UCODE_ID_GMCON_RENG;
0252         break;
0253     case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G:
0254         ret = UCODE_ID_RLC_G;
0255         break;
0256     case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH:
0257         ret = UCODE_ID_RLC_SCRATCH;
0258         break;
0259     case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM:
0260         ret = UCODE_ID_RLC_SRM_ARAM;
0261         break;
0262     case SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM:
0263         ret = UCODE_ID_RLC_SRM_DRAM;
0264         break;
0265     case SMU8_SCRATCH_ENTRY_UCODE_ID_DMCU_ERAM:
0266         ret = UCODE_ID_DMCU_ERAM;
0267         break;
0268     case SMU8_SCRATCH_ENTRY_UCODE_ID_DMCU_IRAM:
0269         ret = UCODE_ID_DMCU_IRAM;
0270         break;
0271     case SMU8_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING:
0272         ret = TASK_ARG_INIT_MM_PWR_LOG;
0273         break;
0274     case SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_HALT:
0275     case SMU8_SCRATCH_ENTRY_DATA_ID_SYS_CLOCKGATING:
0276     case SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_RING_REGS:
0277     case SMU8_SCRATCH_ENTRY_DATA_ID_NONGFX_REINIT:
0278     case SMU8_SCRATCH_ENTRY_DATA_ID_SDMA_START:
0279     case SMU8_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS:
0280         ret = TASK_ARG_REG_MMIO;
0281         break;
0282     case SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE:
0283         ret = TASK_ARG_INIT_CLK_TABLE;
0284         break;
0285     }
0286 
0287     return ret;
0288 }
0289 
0290 static enum cgs_ucode_id smu8_convert_fw_type_to_cgs(uint32_t fw_type)
0291 {
0292     enum cgs_ucode_id result = CGS_UCODE_ID_MAXIMUM;
0293 
0294     switch (fw_type) {
0295     case UCODE_ID_SDMA0:
0296         result = CGS_UCODE_ID_SDMA0;
0297         break;
0298     case UCODE_ID_SDMA1:
0299         result = CGS_UCODE_ID_SDMA1;
0300         break;
0301     case UCODE_ID_CP_CE:
0302         result = CGS_UCODE_ID_CP_CE;
0303         break;
0304     case UCODE_ID_CP_PFP:
0305         result = CGS_UCODE_ID_CP_PFP;
0306         break;
0307     case UCODE_ID_CP_ME:
0308         result = CGS_UCODE_ID_CP_ME;
0309         break;
0310     case UCODE_ID_CP_MEC_JT1:
0311         result = CGS_UCODE_ID_CP_MEC_JT1;
0312         break;
0313     case UCODE_ID_CP_MEC_JT2:
0314         result = CGS_UCODE_ID_CP_MEC_JT2;
0315         break;
0316     case UCODE_ID_RLC_G:
0317         result = CGS_UCODE_ID_RLC_G;
0318         break;
0319     default:
0320         break;
0321     }
0322 
0323     return result;
0324 }
0325 
0326 static int smu8_smu_populate_single_scratch_task(
0327             struct pp_hwmgr *hwmgr,
0328             enum smu8_scratch_entry fw_enum,
0329             uint8_t type, bool is_last)
0330 {
0331     uint8_t i;
0332     struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0333     struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr;
0334     struct SMU_Task *task = &toc->tasks[smu8_smu->toc_entry_used_count++];
0335 
0336     task->type = type;
0337     task->arg = smu8_translate_firmware_enum_to_arg(hwmgr, fw_enum);
0338     task->next = is_last ? END_OF_TASK_LIST : smu8_smu->toc_entry_used_count;
0339 
0340     for (i = 0; i < smu8_smu->scratch_buffer_length; i++)
0341         if (smu8_smu->scratch_buffer[i].firmware_ID == fw_enum)
0342             break;
0343 
0344     if (i >= smu8_smu->scratch_buffer_length) {
0345         pr_err("Invalid Firmware Type\n");
0346         return -EINVAL;
0347     }
0348 
0349     task->addr.low = lower_32_bits(smu8_smu->scratch_buffer[i].mc_addr);
0350     task->addr.high = upper_32_bits(smu8_smu->scratch_buffer[i].mc_addr);
0351     task->size_bytes = smu8_smu->scratch_buffer[i].data_size;
0352 
0353     if (SMU8_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS == fw_enum) {
0354         struct smu8_ih_meta_data *pIHReg_restore =
0355              (struct smu8_ih_meta_data *)smu8_smu->scratch_buffer[i].kaddr;
0356         pIHReg_restore->command =
0357             METADATA_CMD_MODE0 | METADATA_PERFORM_ON_LOAD;
0358     }
0359 
0360     return 0;
0361 }
0362 
0363 static int smu8_smu_populate_single_ucode_load_task(
0364                     struct pp_hwmgr *hwmgr,
0365                     enum smu8_scratch_entry fw_enum,
0366                     bool is_last)
0367 {
0368     uint8_t i;
0369     struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0370     struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr;
0371     struct SMU_Task *task = &toc->tasks[smu8_smu->toc_entry_used_count++];
0372 
0373     task->type = TASK_TYPE_UCODE_LOAD;
0374     task->arg = smu8_translate_firmware_enum_to_arg(hwmgr, fw_enum);
0375     task->next = is_last ? END_OF_TASK_LIST : smu8_smu->toc_entry_used_count;
0376 
0377     for (i = 0; i < smu8_smu->driver_buffer_length; i++)
0378         if (smu8_smu->driver_buffer[i].firmware_ID == fw_enum)
0379             break;
0380 
0381     if (i >= smu8_smu->driver_buffer_length) {
0382         pr_err("Invalid Firmware Type\n");
0383         return -EINVAL;
0384     }
0385 
0386     task->addr.low = lower_32_bits(smu8_smu->driver_buffer[i].mc_addr);
0387     task->addr.high = upper_32_bits(smu8_smu->driver_buffer[i].mc_addr);
0388     task->size_bytes = smu8_smu->driver_buffer[i].data_size;
0389 
0390     return 0;
0391 }
0392 
0393 static int smu8_smu_construct_toc_for_rlc_aram_save(struct pp_hwmgr *hwmgr)
0394 {
0395     struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0396 
0397     smu8_smu->toc_entry_aram = smu8_smu->toc_entry_used_count;
0398     smu8_smu_populate_single_scratch_task(hwmgr,
0399                 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM,
0400                 TASK_TYPE_UCODE_SAVE, true);
0401 
0402     return 0;
0403 }
0404 
0405 static int smu8_smu_initialize_toc_empty_job_list(struct pp_hwmgr *hwmgr)
0406 {
0407     int i;
0408     struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0409     struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr;
0410 
0411     for (i = 0; i < NUM_JOBLIST_ENTRIES; i++)
0412         toc->JobList[i] = (uint8_t)IGNORE_JOB;
0413 
0414     return 0;
0415 }
0416 
0417 static int smu8_smu_construct_toc_for_vddgfx_enter(struct pp_hwmgr *hwmgr)
0418 {
0419     struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0420     struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr;
0421 
0422     toc->JobList[JOB_GFX_SAVE] = (uint8_t)smu8_smu->toc_entry_used_count;
0423     smu8_smu_populate_single_scratch_task(hwmgr,
0424                     SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH,
0425                     TASK_TYPE_UCODE_SAVE, false);
0426 
0427     smu8_smu_populate_single_scratch_task(hwmgr,
0428                     SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM,
0429                     TASK_TYPE_UCODE_SAVE, true);
0430 
0431     return 0;
0432 }
0433 
0434 
0435 static int smu8_smu_construct_toc_for_vddgfx_exit(struct pp_hwmgr *hwmgr)
0436 {
0437     struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0438     struct TOC *toc = (struct TOC *)smu8_smu->toc_buffer.kaddr;
0439 
0440     toc->JobList[JOB_GFX_RESTORE] = (uint8_t)smu8_smu->toc_entry_used_count;
0441 
0442     smu8_smu_populate_single_ucode_load_task(hwmgr,
0443                 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE, false);
0444     smu8_smu_populate_single_ucode_load_task(hwmgr,
0445                 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP, false);
0446     smu8_smu_populate_single_ucode_load_task(hwmgr,
0447                 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME, false);
0448     smu8_smu_populate_single_ucode_load_task(hwmgr,
0449                 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
0450 
0451     if (hwmgr->chip_id == CHIP_STONEY)
0452         smu8_smu_populate_single_ucode_load_task(hwmgr,
0453                 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
0454     else
0455         smu8_smu_populate_single_ucode_load_task(hwmgr,
0456                 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false);
0457 
0458     smu8_smu_populate_single_ucode_load_task(hwmgr,
0459                 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G, false);
0460 
0461     /* populate scratch */
0462     smu8_smu_populate_single_scratch_task(hwmgr,
0463                 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH,
0464                 TASK_TYPE_UCODE_LOAD, false);
0465 
0466     smu8_smu_populate_single_scratch_task(hwmgr,
0467                 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM,
0468                 TASK_TYPE_UCODE_LOAD, false);
0469 
0470     smu8_smu_populate_single_scratch_task(hwmgr,
0471                 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM,
0472                 TASK_TYPE_UCODE_LOAD, true);
0473 
0474     return 0;
0475 }
0476 
0477 static int smu8_smu_construct_toc_for_power_profiling(struct pp_hwmgr *hwmgr)
0478 {
0479     struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0480 
0481     smu8_smu->toc_entry_power_profiling_index = smu8_smu->toc_entry_used_count;
0482 
0483     smu8_smu_populate_single_scratch_task(hwmgr,
0484                 SMU8_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING,
0485                 TASK_TYPE_INITIALIZE, true);
0486     return 0;
0487 }
0488 
0489 static int smu8_smu_construct_toc_for_bootup(struct pp_hwmgr *hwmgr)
0490 {
0491     struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0492 
0493     smu8_smu->toc_entry_initialize_index = smu8_smu->toc_entry_used_count;
0494 
0495     smu8_smu_populate_single_ucode_load_task(hwmgr,
0496                 SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA0, false);
0497     if (hwmgr->chip_id != CHIP_STONEY)
0498         smu8_smu_populate_single_ucode_load_task(hwmgr,
0499                 SMU8_SCRATCH_ENTRY_UCODE_ID_SDMA1, false);
0500     smu8_smu_populate_single_ucode_load_task(hwmgr,
0501                 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_CE, false);
0502     smu8_smu_populate_single_ucode_load_task(hwmgr,
0503                 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_PFP, false);
0504     smu8_smu_populate_single_ucode_load_task(hwmgr,
0505                 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_ME, false);
0506     smu8_smu_populate_single_ucode_load_task(hwmgr,
0507                 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false);
0508     if (hwmgr->chip_id != CHIP_STONEY)
0509         smu8_smu_populate_single_ucode_load_task(hwmgr,
0510                 SMU8_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false);
0511     smu8_smu_populate_single_ucode_load_task(hwmgr,
0512                 SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_G, true);
0513 
0514     return 0;
0515 }
0516 
0517 static int smu8_smu_construct_toc_for_clock_table(struct pp_hwmgr *hwmgr)
0518 {
0519     struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0520 
0521     smu8_smu->toc_entry_clock_table = smu8_smu->toc_entry_used_count;
0522 
0523     smu8_smu_populate_single_scratch_task(hwmgr,
0524                 SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE,
0525                 TASK_TYPE_INITIALIZE, true);
0526 
0527     return 0;
0528 }
0529 
0530 static int smu8_smu_construct_toc(struct pp_hwmgr *hwmgr)
0531 {
0532     struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0533 
0534     smu8_smu->toc_entry_used_count = 0;
0535     smu8_smu_initialize_toc_empty_job_list(hwmgr);
0536     smu8_smu_construct_toc_for_rlc_aram_save(hwmgr);
0537     smu8_smu_construct_toc_for_vddgfx_enter(hwmgr);
0538     smu8_smu_construct_toc_for_vddgfx_exit(hwmgr);
0539     smu8_smu_construct_toc_for_power_profiling(hwmgr);
0540     smu8_smu_construct_toc_for_bootup(hwmgr);
0541     smu8_smu_construct_toc_for_clock_table(hwmgr);
0542 
0543     return 0;
0544 }
0545 
0546 static int smu8_smu_populate_firmware_entries(struct pp_hwmgr *hwmgr)
0547 {
0548     struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0549     uint32_t firmware_type;
0550     uint32_t i;
0551     int ret;
0552     enum cgs_ucode_id ucode_id;
0553     struct cgs_firmware_info info = {0};
0554 
0555     smu8_smu->driver_buffer_length = 0;
0556 
0557     for (i = 0; i < ARRAY_SIZE(firmware_list); i++) {
0558 
0559         firmware_type = smu8_translate_firmware_enum_to_arg(hwmgr,
0560                     firmware_list[i]);
0561 
0562         ucode_id = smu8_convert_fw_type_to_cgs(firmware_type);
0563 
0564         ret = cgs_get_firmware_info(hwmgr->device,
0565                             ucode_id, &info);
0566 
0567         if (ret == 0) {
0568             smu8_smu->driver_buffer[i].mc_addr = info.mc_addr;
0569 
0570             smu8_smu->driver_buffer[i].data_size = info.image_size;
0571 
0572             smu8_smu->driver_buffer[i].firmware_ID = firmware_list[i];
0573             smu8_smu->driver_buffer_length++;
0574         }
0575     }
0576 
0577     return 0;
0578 }
0579 
0580 static int smu8_smu_populate_single_scratch_entry(
0581                 struct pp_hwmgr *hwmgr,
0582                 enum smu8_scratch_entry scratch_type,
0583                 uint32_t ulsize_byte,
0584                 struct smu8_buffer_entry *entry)
0585 {
0586     struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0587     uint32_t ulsize_aligned = SIZE_ALIGN_32(ulsize_byte);
0588 
0589     entry->data_size = ulsize_byte;
0590     entry->kaddr = (char *) smu8_smu->smu_buffer.kaddr +
0591                 smu8_smu->smu_buffer_used_bytes;
0592     entry->mc_addr = smu8_smu->smu_buffer.mc_addr + smu8_smu->smu_buffer_used_bytes;
0593     entry->firmware_ID = scratch_type;
0594 
0595     smu8_smu->smu_buffer_used_bytes += ulsize_aligned;
0596 
0597     return 0;
0598 }
0599 
0600 static int smu8_download_pptable_settings(struct pp_hwmgr *hwmgr, void **table)
0601 {
0602     struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0603     unsigned long i;
0604 
0605     for (i = 0; i < smu8_smu->scratch_buffer_length; i++) {
0606         if (smu8_smu->scratch_buffer[i].firmware_ID
0607             == SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE)
0608             break;
0609     }
0610 
0611     *table = (struct SMU8_Fusion_ClkTable *)smu8_smu->scratch_buffer[i].kaddr;
0612 
0613     smum_send_msg_to_smc_with_parameter(hwmgr,
0614                 PPSMC_MSG_SetClkTableAddrHi,
0615                 upper_32_bits(smu8_smu->scratch_buffer[i].mc_addr),
0616                 NULL);
0617 
0618     smum_send_msg_to_smc_with_parameter(hwmgr,
0619                 PPSMC_MSG_SetClkTableAddrLo,
0620                 lower_32_bits(smu8_smu->scratch_buffer[i].mc_addr),
0621                 NULL);
0622 
0623     smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob,
0624                 smu8_smu->toc_entry_clock_table,
0625                 NULL);
0626 
0627     smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ClkTableXferToDram, NULL);
0628 
0629     return 0;
0630 }
0631 
0632 static int smu8_upload_pptable_settings(struct pp_hwmgr *hwmgr)
0633 {
0634     struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0635     unsigned long i;
0636 
0637     for (i = 0; i < smu8_smu->scratch_buffer_length; i++) {
0638         if (smu8_smu->scratch_buffer[i].firmware_ID
0639                 == SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE)
0640             break;
0641     }
0642 
0643     smum_send_msg_to_smc_with_parameter(hwmgr,
0644                 PPSMC_MSG_SetClkTableAddrHi,
0645                 upper_32_bits(smu8_smu->scratch_buffer[i].mc_addr),
0646                 NULL);
0647 
0648     smum_send_msg_to_smc_with_parameter(hwmgr,
0649                 PPSMC_MSG_SetClkTableAddrLo,
0650                 lower_32_bits(smu8_smu->scratch_buffer[i].mc_addr),
0651                 NULL);
0652 
0653     smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob,
0654                 smu8_smu->toc_entry_clock_table,
0655                 NULL);
0656 
0657     smum_send_msg_to_smc(hwmgr, PPSMC_MSG_ClkTableXferToSmu, NULL);
0658 
0659     return 0;
0660 }
0661 
0662 static int smu8_request_smu_load_fw(struct pp_hwmgr *hwmgr)
0663 {
0664     struct smu8_smumgr *smu8_smu = hwmgr->smu_backend;
0665     uint32_t smc_address;
0666     uint32_t fw_to_check = 0;
0667     int ret;
0668 
0669     amdgpu_ucode_init_bo(hwmgr->adev);
0670 
0671     smu8_smu_populate_firmware_entries(hwmgr);
0672 
0673     smu8_smu_construct_toc(hwmgr);
0674 
0675     smc_address = SMU8_FIRMWARE_HEADER_LOCATION +
0676         offsetof(struct SMU8_Firmware_Header, UcodeLoadStatus);
0677 
0678     smu8_write_smc_sram_dword(hwmgr, smc_address, 0, smc_address+4);
0679 
0680     smum_send_msg_to_smc_with_parameter(hwmgr,
0681                     PPSMC_MSG_DriverDramAddrHi,
0682                     upper_32_bits(smu8_smu->toc_buffer.mc_addr),
0683                     NULL);
0684 
0685     smum_send_msg_to_smc_with_parameter(hwmgr,
0686                     PPSMC_MSG_DriverDramAddrLo,
0687                     lower_32_bits(smu8_smu->toc_buffer.mc_addr),
0688                     NULL);
0689 
0690     smum_send_msg_to_smc(hwmgr, PPSMC_MSG_InitJobs, NULL);
0691 
0692     smum_send_msg_to_smc_with_parameter(hwmgr,
0693                     PPSMC_MSG_ExecuteJob,
0694                     smu8_smu->toc_entry_aram,
0695                     NULL);
0696     smum_send_msg_to_smc_with_parameter(hwmgr, PPSMC_MSG_ExecuteJob,
0697                 smu8_smu->toc_entry_power_profiling_index,
0698                 NULL);
0699 
0700     smum_send_msg_to_smc_with_parameter(hwmgr,
0701                     PPSMC_MSG_ExecuteJob,
0702                     smu8_smu->toc_entry_initialize_index,
0703                     NULL);
0704 
0705     fw_to_check = UCODE_ID_RLC_G_MASK |
0706             UCODE_ID_SDMA0_MASK |
0707             UCODE_ID_SDMA1_MASK |
0708             UCODE_ID_CP_CE_MASK |
0709             UCODE_ID_CP_ME_MASK |
0710             UCODE_ID_CP_PFP_MASK |
0711             UCODE_ID_CP_MEC_JT1_MASK |
0712             UCODE_ID_CP_MEC_JT2_MASK;
0713 
0714     if (hwmgr->chip_id == CHIP_STONEY)
0715         fw_to_check &= ~(UCODE_ID_SDMA1_MASK | UCODE_ID_CP_MEC_JT2_MASK);
0716 
0717     ret = smu8_check_fw_load_finish(hwmgr, fw_to_check);
0718     if (ret) {
0719         pr_err("SMU firmware load failed\n");
0720         return ret;
0721     }
0722 
0723     ret = smu8_load_mec_firmware(hwmgr);
0724     if (ret) {
0725         pr_err("Mec Firmware load failed\n");
0726         return ret;
0727     }
0728 
0729     return 0;
0730 }
0731 
0732 static int smu8_start_smu(struct pp_hwmgr *hwmgr)
0733 {
0734     struct amdgpu_device *adev;
0735 
0736     uint32_t index = SMN_MP1_SRAM_START_ADDR +
0737              SMU8_FIRMWARE_HEADER_LOCATION +
0738              offsetof(struct SMU8_Firmware_Header, Version);
0739 
0740     if (hwmgr == NULL || hwmgr->device == NULL)
0741         return -EINVAL;
0742 
0743     adev = hwmgr->adev;
0744 
0745     cgs_write_register(hwmgr->device, mmMP0PUB_IND_INDEX, index);
0746     hwmgr->smu_version = cgs_read_register(hwmgr->device, mmMP0PUB_IND_DATA);
0747     pr_info("smu version %02d.%02d.%02d\n",
0748         ((hwmgr->smu_version >> 16) & 0xFF),
0749         ((hwmgr->smu_version >> 8) & 0xFF),
0750         (hwmgr->smu_version & 0xFF));
0751     adev->pm.fw_version = hwmgr->smu_version >> 8;
0752 
0753     return smu8_request_smu_load_fw(hwmgr);
0754 }
0755 
0756 static int smu8_smu_init(struct pp_hwmgr *hwmgr)
0757 {
0758     int ret = 0;
0759     struct smu8_smumgr *smu8_smu;
0760 
0761     smu8_smu = kzalloc(sizeof(struct smu8_smumgr), GFP_KERNEL);
0762     if (smu8_smu == NULL)
0763         return -ENOMEM;
0764 
0765     hwmgr->smu_backend = smu8_smu;
0766 
0767     smu8_smu->toc_buffer.data_size = 4096;
0768     smu8_smu->smu_buffer.data_size =
0769         ALIGN(UCODE_ID_RLC_SCRATCH_SIZE_BYTE, 32) +
0770         ALIGN(UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE, 32) +
0771         ALIGN(UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE, 32) +
0772         ALIGN(sizeof(struct SMU8_MultimediaPowerLogData), 32) +
0773         ALIGN(sizeof(struct SMU8_Fusion_ClkTable), 32);
0774 
0775     ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0776                 smu8_smu->toc_buffer.data_size,
0777                 PAGE_SIZE,
0778                 AMDGPU_GEM_DOMAIN_VRAM,
0779                 &smu8_smu->toc_buffer.handle,
0780                 &smu8_smu->toc_buffer.mc_addr,
0781                 &smu8_smu->toc_buffer.kaddr);
0782     if (ret)
0783         goto err2;
0784 
0785     ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
0786                 smu8_smu->smu_buffer.data_size,
0787                 PAGE_SIZE,
0788                 AMDGPU_GEM_DOMAIN_VRAM,
0789                 &smu8_smu->smu_buffer.handle,
0790                 &smu8_smu->smu_buffer.mc_addr,
0791                 &smu8_smu->smu_buffer.kaddr);
0792     if (ret)
0793         goto err1;
0794 
0795     if (0 != smu8_smu_populate_single_scratch_entry(hwmgr,
0796         SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH,
0797         UCODE_ID_RLC_SCRATCH_SIZE_BYTE,
0798         &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) {
0799         pr_err("Error when Populate Firmware Entry.\n");
0800         goto err0;
0801     }
0802 
0803     if (0 != smu8_smu_populate_single_scratch_entry(hwmgr,
0804         SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM,
0805         UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE,
0806         &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) {
0807         pr_err("Error when Populate Firmware Entry.\n");
0808         goto err0;
0809     }
0810     if (0 != smu8_smu_populate_single_scratch_entry(hwmgr,
0811         SMU8_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM,
0812         UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE,
0813         &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) {
0814         pr_err("Error when Populate Firmware Entry.\n");
0815         goto err0;
0816     }
0817 
0818     if (0 != smu8_smu_populate_single_scratch_entry(hwmgr,
0819         SMU8_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING,
0820         sizeof(struct SMU8_MultimediaPowerLogData),
0821         &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) {
0822         pr_err("Error when Populate Firmware Entry.\n");
0823         goto err0;
0824     }
0825 
0826     if (0 != smu8_smu_populate_single_scratch_entry(hwmgr,
0827         SMU8_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE,
0828         sizeof(struct SMU8_Fusion_ClkTable),
0829         &smu8_smu->scratch_buffer[smu8_smu->scratch_buffer_length++])) {
0830         pr_err("Error when Populate Firmware Entry.\n");
0831         goto err0;
0832     }
0833 
0834     return 0;
0835 
0836 err0:
0837     amdgpu_bo_free_kernel(&smu8_smu->smu_buffer.handle,
0838                 &smu8_smu->smu_buffer.mc_addr,
0839                 &smu8_smu->smu_buffer.kaddr);
0840 err1:
0841     amdgpu_bo_free_kernel(&smu8_smu->toc_buffer.handle,
0842                 &smu8_smu->toc_buffer.mc_addr,
0843                 &smu8_smu->toc_buffer.kaddr);
0844 err2:
0845     kfree(smu8_smu);
0846     return -EINVAL;
0847 }
0848 
0849 static int smu8_smu_fini(struct pp_hwmgr *hwmgr)
0850 {
0851     struct smu8_smumgr *smu8_smu;
0852 
0853     if (hwmgr == NULL || hwmgr->device == NULL)
0854         return -EINVAL;
0855 
0856     smu8_smu = hwmgr->smu_backend;
0857     if (smu8_smu) {
0858         amdgpu_bo_free_kernel(&smu8_smu->toc_buffer.handle,
0859                     &smu8_smu->toc_buffer.mc_addr,
0860                     &smu8_smu->toc_buffer.kaddr);
0861         amdgpu_bo_free_kernel(&smu8_smu->smu_buffer.handle,
0862                     &smu8_smu->smu_buffer.mc_addr,
0863                     &smu8_smu->smu_buffer.kaddr);
0864         kfree(smu8_smu);
0865     }
0866 
0867     return 0;
0868 }
0869 
0870 static bool smu8_dpm_check_smu_features(struct pp_hwmgr *hwmgr,
0871                 unsigned long check_feature)
0872 {
0873     int result;
0874     uint32_t features;
0875 
0876     result = smum_send_msg_to_smc_with_parameter(hwmgr,
0877                 PPSMC_MSG_GetFeatureStatus,
0878                 0,
0879                 &features);
0880     if (result == 0) {
0881         if (features & check_feature)
0882             return true;
0883     }
0884 
0885     return false;
0886 }
0887 
0888 static bool smu8_is_dpm_running(struct pp_hwmgr *hwmgr)
0889 {
0890     if (smu8_dpm_check_smu_features(hwmgr, SMU_EnabledFeatureScoreboard_SclkDpmOn))
0891         return true;
0892     return false;
0893 }
0894 
0895 const struct pp_smumgr_func smu8_smu_funcs = {
0896     .name = "smu8_smu",
0897     .smu_init = smu8_smu_init,
0898     .smu_fini = smu8_smu_fini,
0899     .start_smu = smu8_start_smu,
0900     .check_fw_load_finish = smu8_check_fw_load_finish,
0901     .request_smu_load_fw = NULL,
0902     .request_smu_load_specific_fw = NULL,
0903     .get_argument = smu8_get_argument,
0904     .send_msg_to_smc = smu8_send_msg_to_smc,
0905     .send_msg_to_smc_with_parameter = smu8_send_msg_to_smc_with_parameter,
0906     .download_pptable_settings = smu8_download_pptable_settings,
0907     .upload_pptable_settings = smu8_upload_pptable_settings,
0908     .is_dpm_running = smu8_is_dpm_running,
0909 };
0910