LCOV - code coverage report
Current view: top level - drivers/gpu/drm/amd/pm/swsmu/smu11 - smu_v11_0.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 0 943 0.0 %
Date: 2022-12-09 01:23:36 Functions: 0 70 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Copyright 2019 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             : #include <linux/firmware.h>
      24             : #include <linux/module.h>
      25             : #include <linux/pci.h>
      26             : #include <linux/reboot.h>
      27             : 
      28             : #define SMU_11_0_PARTIAL_PPTABLE
      29             : #define SWSMU_CODE_LAYER_L3
      30             : 
      31             : #include "amdgpu.h"
      32             : #include "amdgpu_smu.h"
      33             : #include "atomfirmware.h"
      34             : #include "amdgpu_atomfirmware.h"
      35             : #include "amdgpu_atombios.h"
      36             : #include "smu_v11_0.h"
      37             : #include "soc15_common.h"
      38             : #include "atom.h"
      39             : #include "amdgpu_ras.h"
      40             : #include "smu_cmn.h"
      41             : 
      42             : #include "asic_reg/thm/thm_11_0_2_offset.h"
      43             : #include "asic_reg/thm/thm_11_0_2_sh_mask.h"
      44             : #include "asic_reg/mp/mp_11_0_offset.h"
      45             : #include "asic_reg/mp/mp_11_0_sh_mask.h"
      46             : #include "asic_reg/smuio/smuio_11_0_0_offset.h"
      47             : #include "asic_reg/smuio/smuio_11_0_0_sh_mask.h"
      48             : 
      49             : /*
      50             :  * DO NOT use these for err/warn/info/debug messages.
      51             :  * Use dev_err, dev_warn, dev_info and dev_dbg instead.
      52             :  * They are more MGPU friendly.
      53             :  */
      54             : #undef pr_err
      55             : #undef pr_warn
      56             : #undef pr_info
      57             : #undef pr_debug
      58             : 
      59             : MODULE_FIRMWARE("amdgpu/arcturus_smc.bin");
      60             : MODULE_FIRMWARE("amdgpu/navi10_smc.bin");
      61             : MODULE_FIRMWARE("amdgpu/navi14_smc.bin");
      62             : MODULE_FIRMWARE("amdgpu/navi12_smc.bin");
      63             : MODULE_FIRMWARE("amdgpu/sienna_cichlid_smc.bin");
      64             : MODULE_FIRMWARE("amdgpu/navy_flounder_smc.bin");
      65             : MODULE_FIRMWARE("amdgpu/dimgrey_cavefish_smc.bin");
      66             : MODULE_FIRMWARE("amdgpu/beige_goby_smc.bin");
      67             : 
      68             : #define SMU11_VOLTAGE_SCALE 4
      69             : 
      70             : #define SMU11_MODE1_RESET_WAIT_TIME_IN_MS 500  //500ms
      71             : 
      72             : #define smnPCIE_LC_LINK_WIDTH_CNTL              0x11140288
      73             : #define PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK 0x00000070L
      74             : #define PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT 0x4
      75             : #define smnPCIE_LC_SPEED_CNTL                   0x11140290
      76             : #define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK 0xC000
      77             : #define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT 0xE
      78             : 
      79             : #define mmTHM_BACO_CNTL_ARCT                    0xA7
      80             : #define mmTHM_BACO_CNTL_ARCT_BASE_IDX           0
      81             : 
      82           0 : int smu_v11_0_init_microcode(struct smu_context *smu)
      83             : {
      84           0 :         struct amdgpu_device *adev = smu->adev;
      85             :         const char *chip_name;
      86             :         char fw_name[SMU_FW_NAME_LEN];
      87           0 :         int err = 0;
      88             :         const struct smc_firmware_header_v1_0 *hdr;
      89             :         const struct common_firmware_header *header;
      90           0 :         struct amdgpu_firmware_info *ucode = NULL;
      91             : 
      92           0 :         if (amdgpu_sriov_vf(adev) &&
      93           0 :             ((adev->ip_versions[MP1_HWIP][0] == IP_VERSION(11, 0, 9)) ||
      94             :              (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(11, 0, 7))))
      95             :                 return 0;
      96             : 
      97           0 :         switch (adev->ip_versions[MP1_HWIP][0]) {
      98             :         case IP_VERSION(11, 0, 0):
      99             :                 chip_name = "navi10";
     100             :                 break;
     101             :         case IP_VERSION(11, 0, 5):
     102           0 :                 chip_name = "navi14";
     103           0 :                 break;
     104             :         case IP_VERSION(11, 0, 9):
     105           0 :                 chip_name = "navi12";
     106           0 :                 break;
     107             :         case IP_VERSION(11, 0, 7):
     108           0 :                 chip_name = "sienna_cichlid";
     109           0 :                 break;
     110             :         case IP_VERSION(11, 0, 11):
     111           0 :                 chip_name = "navy_flounder";
     112           0 :                 break;
     113             :         case IP_VERSION(11, 0, 12):
     114           0 :                 chip_name = "dimgrey_cavefish";
     115           0 :                 break;
     116             :         case IP_VERSION(11, 0, 13):
     117           0 :                 chip_name = "beige_goby";
     118           0 :                 break;
     119             :         case IP_VERSION(11, 0, 2):
     120           0 :                 chip_name = "arcturus";
     121           0 :                 break;
     122             :         default:
     123           0 :                 dev_err(adev->dev, "Unsupported IP version 0x%x\n",
     124             :                         adev->ip_versions[MP1_HWIP][0]);
     125           0 :                 return -EINVAL;
     126             :         }
     127             : 
     128           0 :         snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_smc.bin", chip_name);
     129             : 
     130           0 :         err = request_firmware(&adev->pm.fw, fw_name, adev->dev);
     131           0 :         if (err)
     132             :                 goto out;
     133           0 :         err = amdgpu_ucode_validate(adev->pm.fw);
     134           0 :         if (err)
     135             :                 goto out;
     136             : 
     137           0 :         hdr = (const struct smc_firmware_header_v1_0 *) adev->pm.fw->data;
     138           0 :         amdgpu_ucode_print_smc_hdr(&hdr->header);
     139           0 :         adev->pm.fw_version = le32_to_cpu(hdr->header.ucode_version);
     140             : 
     141           0 :         if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
     142           0 :                 ucode = &adev->firmware.ucode[AMDGPU_UCODE_ID_SMC];
     143           0 :                 ucode->ucode_id = AMDGPU_UCODE_ID_SMC;
     144           0 :                 ucode->fw = adev->pm.fw;
     145           0 :                 header = (const struct common_firmware_header *)ucode->fw->data;
     146           0 :                 adev->firmware.fw_size +=
     147           0 :                         ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
     148             :         }
     149             : 
     150             : out:
     151           0 :         if (err) {
     152           0 :                 DRM_ERROR("smu_v11_0: Failed to load firmware \"%s\"\n",
     153             :                           fw_name);
     154           0 :                 release_firmware(adev->pm.fw);
     155           0 :                 adev->pm.fw = NULL;
     156             :         }
     157             :         return err;
     158             : }
     159             : 
     160           0 : void smu_v11_0_fini_microcode(struct smu_context *smu)
     161             : {
     162           0 :         struct amdgpu_device *adev = smu->adev;
     163             : 
     164           0 :         release_firmware(adev->pm.fw);
     165           0 :         adev->pm.fw = NULL;
     166           0 :         adev->pm.fw_version = 0;
     167           0 : }
     168             : 
     169           0 : int smu_v11_0_load_microcode(struct smu_context *smu)
     170             : {
     171           0 :         struct amdgpu_device *adev = smu->adev;
     172             :         const uint32_t *src;
     173             :         const struct smc_firmware_header_v1_0 *hdr;
     174           0 :         uint32_t addr_start = MP1_SRAM;
     175             :         uint32_t i;
     176             :         uint32_t smc_fw_size;
     177             :         uint32_t mp1_fw_flags;
     178             : 
     179           0 :         hdr = (const struct smc_firmware_header_v1_0 *) adev->pm.fw->data;
     180           0 :         src = (const uint32_t *)(adev->pm.fw->data +
     181           0 :                 le32_to_cpu(hdr->header.ucode_array_offset_bytes));
     182           0 :         smc_fw_size = hdr->header.ucode_size_bytes;
     183             : 
     184           0 :         for (i = 1; i < smc_fw_size/4 - 1; i++) {
     185           0 :                 WREG32_PCIE(addr_start, src[i]);
     186           0 :                 addr_start += 4;
     187             :         }
     188             : 
     189           0 :         WREG32_PCIE(MP1_Public | (smnMP1_PUB_CTRL & 0xffffffff),
     190             :                 1 & MP1_SMN_PUB_CTRL__RESET_MASK);
     191           0 :         WREG32_PCIE(MP1_Public | (smnMP1_PUB_CTRL & 0xffffffff),
     192             :                 1 & ~MP1_SMN_PUB_CTRL__RESET_MASK);
     193             : 
     194           0 :         for (i = 0; i < adev->usec_timeout; i++) {
     195           0 :                 mp1_fw_flags = RREG32_PCIE(MP1_Public |
     196             :                         (smnMP1_FIRMWARE_FLAGS & 0xffffffff));
     197           0 :                 if ((mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >>
     198             :                         MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT)
     199             :                         break;
     200           0 :                 udelay(1);
     201             :         }
     202             : 
     203           0 :         if (i == adev->usec_timeout)
     204             :                 return -ETIME;
     205             : 
     206           0 :         return 0;
     207             : }
     208             : 
     209           0 : int smu_v11_0_check_fw_status(struct smu_context *smu)
     210             : {
     211           0 :         struct amdgpu_device *adev = smu->adev;
     212             :         uint32_t mp1_fw_flags;
     213             : 
     214           0 :         mp1_fw_flags = RREG32_PCIE(MP1_Public |
     215             :                                    (smnMP1_FIRMWARE_FLAGS & 0xffffffff));
     216             : 
     217           0 :         if ((mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK) >>
     218             :             MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED__SHIFT)
     219             :                 return 0;
     220             : 
     221           0 :         return -EIO;
     222             : }
     223             : 
     224           0 : int smu_v11_0_check_fw_version(struct smu_context *smu)
     225             : {
     226           0 :         struct amdgpu_device *adev = smu->adev;
     227           0 :         uint32_t if_version = 0xff, smu_version = 0xff;
     228             :         uint8_t smu_program, smu_major, smu_minor, smu_debug;
     229           0 :         int ret = 0;
     230             : 
     231           0 :         ret = smu_cmn_get_smc_version(smu, &if_version, &smu_version);
     232           0 :         if (ret)
     233             :                 return ret;
     234             : 
     235           0 :         smu_program = (smu_version >> 24) & 0xff;
     236           0 :         smu_major = (smu_version >> 16) & 0xff;
     237           0 :         smu_minor = (smu_version >> 8) & 0xff;
     238           0 :         smu_debug = (smu_version >> 0) & 0xff;
     239           0 :         if (smu->is_apu)
     240           0 :                 adev->pm.fw_version = smu_version;
     241             : 
     242           0 :         switch (adev->ip_versions[MP1_HWIP][0]) {
     243             :         case IP_VERSION(11, 0, 0):
     244           0 :                 smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_NV10;
     245           0 :                 break;
     246             :         case IP_VERSION(11, 0, 9):
     247           0 :                 smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_NV12;
     248           0 :                 break;
     249             :         case IP_VERSION(11, 0, 5):
     250           0 :                 smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_NV14;
     251           0 :                 break;
     252             :         case IP_VERSION(11, 0, 7):
     253           0 :                 smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Sienna_Cichlid;
     254           0 :                 break;
     255             :         case IP_VERSION(11, 0, 11):
     256           0 :                 smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Navy_Flounder;
     257           0 :                 break;
     258             :         case IP_VERSION(11, 5, 0):
     259           0 :                 smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_VANGOGH;
     260           0 :                 break;
     261             :         case IP_VERSION(11, 0, 12):
     262           0 :                 smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Dimgrey_Cavefish;
     263           0 :                 break;
     264             :         case IP_VERSION(11, 0, 13):
     265           0 :                 smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Beige_Goby;
     266           0 :                 break;
     267             :         case IP_VERSION(11, 0, 8):
     268           0 :                 smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_Cyan_Skillfish;
     269           0 :                 break;
     270             :         case IP_VERSION(11, 0, 2):
     271           0 :                 smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_ARCT;
     272           0 :                 break;
     273             :         default:
     274           0 :                 dev_err(smu->adev->dev, "smu unsupported IP version: 0x%x.\n",
     275             :                         adev->ip_versions[MP1_HWIP][0]);
     276           0 :                 smu->smc_driver_if_version = SMU11_DRIVER_IF_VERSION_INV;
     277           0 :                 break;
     278             :         }
     279             : 
     280             :         /*
     281             :          * 1. if_version mismatch is not critical as our fw is designed
     282             :          * to be backward compatible.
     283             :          * 2. New fw usually brings some optimizations. But that's visible
     284             :          * only on the paired driver.
     285             :          * Considering above, we just leave user a warning message instead
     286             :          * of halt driver loading.
     287             :          */
     288           0 :         if (if_version != smu->smc_driver_if_version) {
     289           0 :                 dev_info(smu->adev->dev, "smu driver if version = 0x%08x, smu fw if version = 0x%08x, "
     290             :                         "smu fw program = %d, version = 0x%08x (%d.%d.%d)\n",
     291             :                         smu->smc_driver_if_version, if_version,
     292             :                         smu_program, smu_version, smu_major, smu_minor, smu_debug);
     293           0 :                 dev_warn(smu->adev->dev, "SMU driver if version not matched\n");
     294             :         }
     295             : 
     296             :         return ret;
     297             : }
     298             : 
     299             : static int smu_v11_0_set_pptable_v2_0(struct smu_context *smu, void **table, uint32_t *size)
     300             : {
     301           0 :         struct amdgpu_device *adev = smu->adev;
     302             :         uint32_t ppt_offset_bytes;
     303             :         const struct smc_firmware_header_v2_0 *v2;
     304             : 
     305           0 :         v2 = (const struct smc_firmware_header_v2_0 *) adev->pm.fw->data;
     306             : 
     307           0 :         ppt_offset_bytes = le32_to_cpu(v2->ppt_offset_bytes);
     308           0 :         *size = le32_to_cpu(v2->ppt_size_bytes);
     309           0 :         *table = (uint8_t *)v2 + ppt_offset_bytes;
     310             : 
     311             :         return 0;
     312             : }
     313             : 
     314             : static int smu_v11_0_set_pptable_v2_1(struct smu_context *smu, void **table,
     315             :                                       uint32_t *size, uint32_t pptable_id)
     316             : {
     317           0 :         struct amdgpu_device *adev = smu->adev;
     318             :         const struct smc_firmware_header_v2_1 *v2_1;
     319             :         struct smc_soft_pptable_entry *entries;
     320           0 :         uint32_t pptable_count = 0;
     321           0 :         int i = 0;
     322             : 
     323           0 :         v2_1 = (const struct smc_firmware_header_v2_1 *) adev->pm.fw->data;
     324           0 :         entries = (struct smc_soft_pptable_entry *)
     325           0 :                 ((uint8_t *)v2_1 + le32_to_cpu(v2_1->pptable_entry_offset));
     326           0 :         pptable_count = le32_to_cpu(v2_1->pptable_count);
     327           0 :         for (i = 0; i < pptable_count; i++) {
     328           0 :                 if (le32_to_cpu(entries[i].id) == pptable_id) {
     329           0 :                         *table = ((uint8_t *)v2_1 + le32_to_cpu(entries[i].ppt_offset_bytes));
     330           0 :                         *size = le32_to_cpu(entries[i].ppt_size_bytes);
     331             :                         break;
     332             :                 }
     333             :         }
     334             : 
     335           0 :         if (i == pptable_count)
     336             :                 return -EINVAL;
     337             : 
     338             :         return 0;
     339             : }
     340             : 
     341           0 : int smu_v11_0_setup_pptable(struct smu_context *smu)
     342             : {
     343           0 :         struct amdgpu_device *adev = smu->adev;
     344             :         const struct smc_firmware_header_v1_0 *hdr;
     345             :         int ret, index;
     346           0 :         uint32_t size = 0;
     347             :         uint16_t atom_table_size;
     348             :         uint8_t frev, crev;
     349             :         void *table;
     350             :         uint16_t version_major, version_minor;
     351             : 
     352           0 :         if (!amdgpu_sriov_vf(adev)) {
     353           0 :                 hdr = (const struct smc_firmware_header_v1_0 *) adev->pm.fw->data;
     354           0 :                 version_major = le16_to_cpu(hdr->header.header_version_major);
     355           0 :                 version_minor = le16_to_cpu(hdr->header.header_version_minor);
     356           0 :                 if (version_major == 2 && smu->smu_table.boot_values.pp_table_id > 0) {
     357           0 :                         dev_info(adev->dev, "use driver provided pptable %d\n", smu->smu_table.boot_values.pp_table_id);
     358           0 :                         switch (version_minor) {
     359             :                         case 0:
     360           0 :                                 ret = smu_v11_0_set_pptable_v2_0(smu, &table, &size);
     361           0 :                                 break;
     362             :                         case 1:
     363           0 :                                 ret = smu_v11_0_set_pptable_v2_1(smu, &table, &size,
     364             :                                                                 smu->smu_table.boot_values.pp_table_id);
     365             :                                 break;
     366             :                         default:
     367             :                                 ret = -EINVAL;
     368             :                                 break;
     369             :                         }
     370           0 :                         if (ret)
     371             :                                 return ret;
     372             :                         goto out;
     373             :                 }
     374             :         }
     375             : 
     376           0 :         dev_info(adev->dev, "use vbios provided pptable\n");
     377           0 :         index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
     378             :                                                 powerplayinfo);
     379             : 
     380           0 :         ret = amdgpu_atombios_get_data_table(adev, index, &atom_table_size, &frev, &crev,
     381             :                                                 (uint8_t **)&table);
     382           0 :         if (ret)
     383             :                 return ret;
     384           0 :         size = atom_table_size;
     385             : 
     386             : out:
     387           0 :         if (!smu->smu_table.power_play_table)
     388           0 :                 smu->smu_table.power_play_table = table;
     389           0 :         if (!smu->smu_table.power_play_table_size)
     390           0 :                 smu->smu_table.power_play_table_size = size;
     391             : 
     392             :         return 0;
     393             : }
     394             : 
     395           0 : int smu_v11_0_init_smc_tables(struct smu_context *smu)
     396             : {
     397           0 :         struct smu_table_context *smu_table = &smu->smu_table;
     398           0 :         struct smu_table *tables = smu_table->tables;
     399           0 :         int ret = 0;
     400             : 
     401           0 :         smu_table->driver_pptable =
     402           0 :                 kzalloc(tables[SMU_TABLE_PPTABLE].size, GFP_KERNEL);
     403           0 :         if (!smu_table->driver_pptable) {
     404             :                 ret = -ENOMEM;
     405             :                 goto err0_out;
     406             :         }
     407             : 
     408           0 :         smu_table->max_sustainable_clocks =
     409           0 :                 kzalloc(sizeof(struct smu_11_0_max_sustainable_clocks), GFP_KERNEL);
     410           0 :         if (!smu_table->max_sustainable_clocks) {
     411             :                 ret = -ENOMEM;
     412             :                 goto err1_out;
     413             :         }
     414             : 
     415             :         /* Arcturus does not support OVERDRIVE */
     416           0 :         if (tables[SMU_TABLE_OVERDRIVE].size) {
     417           0 :                 smu_table->overdrive_table =
     418           0 :                         kzalloc(tables[SMU_TABLE_OVERDRIVE].size, GFP_KERNEL);
     419           0 :                 if (!smu_table->overdrive_table) {
     420             :                         ret = -ENOMEM;
     421             :                         goto err2_out;
     422             :                 }
     423             : 
     424           0 :                 smu_table->boot_overdrive_table =
     425           0 :                         kzalloc(tables[SMU_TABLE_OVERDRIVE].size, GFP_KERNEL);
     426           0 :                 if (!smu_table->boot_overdrive_table) {
     427             :                         ret = -ENOMEM;
     428             :                         goto err3_out;
     429             :                 }
     430             : 
     431           0 :                 smu_table->user_overdrive_table =
     432           0 :                         kzalloc(tables[SMU_TABLE_OVERDRIVE].size, GFP_KERNEL);
     433           0 :                 if (!smu_table->user_overdrive_table) {
     434           0 :                         ret = -ENOMEM;
     435             :                         goto err4_out;
     436             :                 }
     437             : 
     438             :         }
     439             : 
     440             :         return 0;
     441             : 
     442             : err4_out:
     443           0 :         kfree(smu_table->boot_overdrive_table);
     444             : err3_out:
     445           0 :         kfree(smu_table->overdrive_table);
     446             : err2_out:
     447           0 :         kfree(smu_table->max_sustainable_clocks);
     448             : err1_out:
     449           0 :         kfree(smu_table->driver_pptable);
     450             : err0_out:
     451             :         return ret;
     452             : }
     453             : 
     454           0 : int smu_v11_0_fini_smc_tables(struct smu_context *smu)
     455             : {
     456           0 :         struct smu_table_context *smu_table = &smu->smu_table;
     457           0 :         struct smu_dpm_context *smu_dpm = &smu->smu_dpm;
     458             : 
     459           0 :         kfree(smu_table->gpu_metrics_table);
     460           0 :         kfree(smu_table->user_overdrive_table);
     461           0 :         kfree(smu_table->boot_overdrive_table);
     462           0 :         kfree(smu_table->overdrive_table);
     463           0 :         kfree(smu_table->max_sustainable_clocks);
     464           0 :         kfree(smu_table->driver_pptable);
     465           0 :         kfree(smu_table->clocks_table);
     466           0 :         smu_table->gpu_metrics_table = NULL;
     467           0 :         smu_table->user_overdrive_table = NULL;
     468           0 :         smu_table->boot_overdrive_table = NULL;
     469           0 :         smu_table->overdrive_table = NULL;
     470           0 :         smu_table->max_sustainable_clocks = NULL;
     471           0 :         smu_table->driver_pptable = NULL;
     472           0 :         smu_table->clocks_table = NULL;
     473           0 :         kfree(smu_table->hardcode_pptable);
     474           0 :         smu_table->hardcode_pptable = NULL;
     475             : 
     476           0 :         kfree(smu_table->driver_smu_config_table);
     477           0 :         kfree(smu_table->ecc_table);
     478           0 :         kfree(smu_table->metrics_table);
     479           0 :         kfree(smu_table->watermarks_table);
     480           0 :         smu_table->driver_smu_config_table = NULL;
     481           0 :         smu_table->ecc_table = NULL;
     482           0 :         smu_table->metrics_table = NULL;
     483           0 :         smu_table->watermarks_table = NULL;
     484           0 :         smu_table->metrics_time = 0;
     485             : 
     486           0 :         kfree(smu_dpm->dpm_context);
     487           0 :         kfree(smu_dpm->golden_dpm_context);
     488           0 :         kfree(smu_dpm->dpm_current_power_state);
     489           0 :         kfree(smu_dpm->dpm_request_power_state);
     490           0 :         smu_dpm->dpm_context = NULL;
     491           0 :         smu_dpm->golden_dpm_context = NULL;
     492           0 :         smu_dpm->dpm_context_size = 0;
     493           0 :         smu_dpm->dpm_current_power_state = NULL;
     494           0 :         smu_dpm->dpm_request_power_state = NULL;
     495             : 
     496           0 :         return 0;
     497             : }
     498             : 
     499           0 : int smu_v11_0_init_power(struct smu_context *smu)
     500             : {
     501           0 :         struct amdgpu_device *adev = smu->adev;
     502           0 :         struct smu_power_context *smu_power = &smu->smu_power;
     503           0 :         size_t size = adev->ip_versions[MP1_HWIP][0] == IP_VERSION(11, 5, 0) ?
     504           0 :                         sizeof(struct smu_11_5_power_context) :
     505             :                         sizeof(struct smu_11_0_power_context);
     506             : 
     507           0 :         smu_power->power_context = kzalloc(size, GFP_KERNEL);
     508           0 :         if (!smu_power->power_context)
     509             :                 return -ENOMEM;
     510           0 :         smu_power->power_context_size = size;
     511             : 
     512           0 :         return 0;
     513             : }
     514             : 
     515           0 : int smu_v11_0_fini_power(struct smu_context *smu)
     516             : {
     517           0 :         struct smu_power_context *smu_power = &smu->smu_power;
     518             : 
     519           0 :         kfree(smu_power->power_context);
     520           0 :         smu_power->power_context = NULL;
     521           0 :         smu_power->power_context_size = 0;
     522             : 
     523           0 :         return 0;
     524             : }
     525             : 
     526           0 : static int smu_v11_0_atom_get_smu_clockinfo(struct amdgpu_device *adev,
     527             :                                             uint8_t clk_id,
     528             :                                             uint8_t syspll_id,
     529             :                                             uint32_t *clk_freq)
     530             : {
     531           0 :         struct atom_get_smu_clock_info_parameters_v3_1 input = {0};
     532             :         struct atom_get_smu_clock_info_output_parameters_v3_1 *output;
     533             :         int ret, index;
     534             : 
     535           0 :         input.clk_id = clk_id;
     536           0 :         input.syspll_id = syspll_id;
     537             :         input.command = GET_SMU_CLOCK_INFO_V3_1_GET_CLOCK_FREQ;
     538           0 :         index = get_index_into_master_table(atom_master_list_of_command_functions_v2_1,
     539             :                                             getsmuclockinfo);
     540             : 
     541           0 :         ret = amdgpu_atom_execute_table(adev->mode_info.atom_context, index,
     542             :                                         (uint32_t *)&input);
     543           0 :         if (ret)
     544             :                 return -EINVAL;
     545             : 
     546           0 :         output = (struct atom_get_smu_clock_info_output_parameters_v3_1 *)&input;
     547           0 :         *clk_freq = le32_to_cpu(output->atom_smu_outputclkfreq.smu_clock_freq_hz) / 10000;
     548             : 
     549           0 :         return 0;
     550             : }
     551             : 
     552           0 : int smu_v11_0_get_vbios_bootup_values(struct smu_context *smu)
     553             : {
     554             :         int ret, index;
     555             :         uint16_t size;
     556             :         uint8_t frev, crev;
     557             :         struct atom_common_table_header *header;
     558             :         struct atom_firmware_info_v3_3 *v_3_3;
     559             :         struct atom_firmware_info_v3_1 *v_3_1;
     560             : 
     561           0 :         index = get_index_into_master_table(atom_master_list_of_data_tables_v2_1,
     562             :                                             firmwareinfo);
     563             : 
     564           0 :         ret = amdgpu_atombios_get_data_table(smu->adev, index, &size, &frev, &crev,
     565             :                                       (uint8_t **)&header);
     566           0 :         if (ret)
     567             :                 return ret;
     568             : 
     569           0 :         if (header->format_revision != 3) {
     570           0 :                 dev_err(smu->adev->dev, "unknown atom_firmware_info version! for smu11\n");
     571           0 :                 return -EINVAL;
     572             :         }
     573             : 
     574           0 :         switch (header->content_revision) {
     575             :         case 0:
     576             :         case 1:
     577             :         case 2:
     578           0 :                 v_3_1 = (struct atom_firmware_info_v3_1 *)header;
     579           0 :                 smu->smu_table.boot_values.revision = v_3_1->firmware_revision;
     580           0 :                 smu->smu_table.boot_values.gfxclk = v_3_1->bootup_sclk_in10khz;
     581           0 :                 smu->smu_table.boot_values.uclk = v_3_1->bootup_mclk_in10khz;
     582           0 :                 smu->smu_table.boot_values.socclk = 0;
     583           0 :                 smu->smu_table.boot_values.dcefclk = 0;
     584           0 :                 smu->smu_table.boot_values.vddc = v_3_1->bootup_vddc_mv;
     585           0 :                 smu->smu_table.boot_values.vddci = v_3_1->bootup_vddci_mv;
     586           0 :                 smu->smu_table.boot_values.mvddc = v_3_1->bootup_mvddc_mv;
     587           0 :                 smu->smu_table.boot_values.vdd_gfx = v_3_1->bootup_vddgfx_mv;
     588           0 :                 smu->smu_table.boot_values.cooling_id = v_3_1->coolingsolution_id;
     589           0 :                 smu->smu_table.boot_values.pp_table_id = 0;
     590           0 :                 smu->smu_table.boot_values.firmware_caps = v_3_1->firmware_capability;
     591           0 :                 break;
     592             :         case 3:
     593             :         case 4:
     594             :         default:
     595           0 :                 v_3_3 = (struct atom_firmware_info_v3_3 *)header;
     596           0 :                 smu->smu_table.boot_values.revision = v_3_3->firmware_revision;
     597           0 :                 smu->smu_table.boot_values.gfxclk = v_3_3->bootup_sclk_in10khz;
     598           0 :                 smu->smu_table.boot_values.uclk = v_3_3->bootup_mclk_in10khz;
     599           0 :                 smu->smu_table.boot_values.socclk = 0;
     600           0 :                 smu->smu_table.boot_values.dcefclk = 0;
     601           0 :                 smu->smu_table.boot_values.vddc = v_3_3->bootup_vddc_mv;
     602           0 :                 smu->smu_table.boot_values.vddci = v_3_3->bootup_vddci_mv;
     603           0 :                 smu->smu_table.boot_values.mvddc = v_3_3->bootup_mvddc_mv;
     604           0 :                 smu->smu_table.boot_values.vdd_gfx = v_3_3->bootup_vddgfx_mv;
     605           0 :                 smu->smu_table.boot_values.cooling_id = v_3_3->coolingsolution_id;
     606           0 :                 smu->smu_table.boot_values.pp_table_id = v_3_3->pplib_pptable_id;
     607           0 :                 smu->smu_table.boot_values.firmware_caps = v_3_3->firmware_capability;
     608             :         }
     609             : 
     610           0 :         smu->smu_table.boot_values.format_revision = header->format_revision;
     611           0 :         smu->smu_table.boot_values.content_revision = header->content_revision;
     612             : 
     613           0 :         smu_v11_0_atom_get_smu_clockinfo(smu->adev,
     614             :                                          (uint8_t)SMU11_SYSPLL0_SOCCLK_ID,
     615             :                                          (uint8_t)0,
     616             :                                          &smu->smu_table.boot_values.socclk);
     617             : 
     618           0 :         smu_v11_0_atom_get_smu_clockinfo(smu->adev,
     619             :                                          (uint8_t)SMU11_SYSPLL0_DCEFCLK_ID,
     620             :                                          (uint8_t)0,
     621             :                                          &smu->smu_table.boot_values.dcefclk);
     622             : 
     623           0 :         smu_v11_0_atom_get_smu_clockinfo(smu->adev,
     624             :                                          (uint8_t)SMU11_SYSPLL0_ECLK_ID,
     625             :                                          (uint8_t)0,
     626             :                                          &smu->smu_table.boot_values.eclk);
     627             : 
     628           0 :         smu_v11_0_atom_get_smu_clockinfo(smu->adev,
     629             :                                          (uint8_t)SMU11_SYSPLL0_VCLK_ID,
     630             :                                          (uint8_t)0,
     631             :                                          &smu->smu_table.boot_values.vclk);
     632             : 
     633           0 :         smu_v11_0_atom_get_smu_clockinfo(smu->adev,
     634             :                                          (uint8_t)SMU11_SYSPLL0_DCLK_ID,
     635             :                                          (uint8_t)0,
     636             :                                          &smu->smu_table.boot_values.dclk);
     637             : 
     638           0 :         if ((smu->smu_table.boot_values.format_revision == 3) &&
     639           0 :             (smu->smu_table.boot_values.content_revision >= 2))
     640           0 :                 smu_v11_0_atom_get_smu_clockinfo(smu->adev,
     641             :                                                  (uint8_t)SMU11_SYSPLL1_0_FCLK_ID,
     642             :                                                  (uint8_t)SMU11_SYSPLL1_2_ID,
     643             :                                                  &smu->smu_table.boot_values.fclk);
     644             : 
     645           0 :         smu_v11_0_atom_get_smu_clockinfo(smu->adev,
     646             :                                          (uint8_t)SMU11_SYSPLL3_1_LCLK_ID,
     647             :                                          (uint8_t)SMU11_SYSPLL3_1_ID,
     648             :                                          &smu->smu_table.boot_values.lclk);
     649             : 
     650           0 :         return 0;
     651             : }
     652             : 
     653           0 : int smu_v11_0_notify_memory_pool_location(struct smu_context *smu)
     654             : {
     655           0 :         struct smu_table_context *smu_table = &smu->smu_table;
     656           0 :         struct smu_table *memory_pool = &smu_table->memory_pool;
     657           0 :         int ret = 0;
     658             :         uint64_t address;
     659             :         uint32_t address_low, address_high;
     660             : 
     661           0 :         if (memory_pool->size == 0 || memory_pool->cpu_addr == NULL)
     662             :                 return ret;
     663             : 
     664           0 :         address = (uintptr_t)memory_pool->cpu_addr;
     665           0 :         address_high = (uint32_t)upper_32_bits(address);
     666           0 :         address_low  = (uint32_t)lower_32_bits(address);
     667             : 
     668           0 :         ret = smu_cmn_send_smc_msg_with_param(smu,
     669             :                                           SMU_MSG_SetSystemVirtualDramAddrHigh,
     670             :                                           address_high,
     671             :                                           NULL);
     672           0 :         if (ret)
     673             :                 return ret;
     674           0 :         ret = smu_cmn_send_smc_msg_with_param(smu,
     675             :                                           SMU_MSG_SetSystemVirtualDramAddrLow,
     676             :                                           address_low,
     677             :                                           NULL);
     678           0 :         if (ret)
     679             :                 return ret;
     680             : 
     681           0 :         address = memory_pool->mc_address;
     682           0 :         address_high = (uint32_t)upper_32_bits(address);
     683           0 :         address_low  = (uint32_t)lower_32_bits(address);
     684             : 
     685           0 :         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_DramLogSetDramAddrHigh,
     686             :                                           address_high, NULL);
     687           0 :         if (ret)
     688             :                 return ret;
     689           0 :         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_DramLogSetDramAddrLow,
     690             :                                           address_low, NULL);
     691           0 :         if (ret)
     692             :                 return ret;
     693           0 :         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_DramLogSetDramSize,
     694           0 :                                           (uint32_t)memory_pool->size, NULL);
     695             :         if (ret)
     696             :                 return ret;
     697             : 
     698             :         return ret;
     699             : }
     700             : 
     701           0 : int smu_v11_0_set_min_deep_sleep_dcefclk(struct smu_context *smu, uint32_t clk)
     702             : {
     703             :         int ret;
     704             : 
     705           0 :         ret = smu_cmn_send_smc_msg_with_param(smu,
     706             :                                           SMU_MSG_SetMinDeepSleepDcefclk, clk, NULL);
     707           0 :         if (ret)
     708           0 :                 dev_err(smu->adev->dev, "SMU11 attempt to set divider for DCEFCLK Failed!");
     709             : 
     710           0 :         return ret;
     711             : }
     712             : 
     713           0 : int smu_v11_0_set_driver_table_location(struct smu_context *smu)
     714             : {
     715           0 :         struct smu_table *driver_table = &smu->smu_table.driver_table;
     716           0 :         int ret = 0;
     717             : 
     718           0 :         if (driver_table->mc_address) {
     719           0 :                 ret = smu_cmn_send_smc_msg_with_param(smu,
     720             :                                 SMU_MSG_SetDriverDramAddrHigh,
     721           0 :                                 upper_32_bits(driver_table->mc_address),
     722             :                                 NULL);
     723           0 :                 if (!ret)
     724           0 :                         ret = smu_cmn_send_smc_msg_with_param(smu,
     725             :                                 SMU_MSG_SetDriverDramAddrLow,
     726           0 :                                 lower_32_bits(driver_table->mc_address),
     727             :                                 NULL);
     728             :         }
     729             : 
     730           0 :         return ret;
     731             : }
     732             : 
     733           0 : int smu_v11_0_set_tool_table_location(struct smu_context *smu)
     734             : {
     735           0 :         int ret = 0;
     736           0 :         struct smu_table *tool_table = &smu->smu_table.tables[SMU_TABLE_PMSTATUSLOG];
     737             : 
     738           0 :         if (tool_table->mc_address) {
     739           0 :                 ret = smu_cmn_send_smc_msg_with_param(smu,
     740             :                                 SMU_MSG_SetToolsDramAddrHigh,
     741           0 :                                 upper_32_bits(tool_table->mc_address),
     742             :                                 NULL);
     743           0 :                 if (!ret)
     744           0 :                         ret = smu_cmn_send_smc_msg_with_param(smu,
     745             :                                 SMU_MSG_SetToolsDramAddrLow,
     746           0 :                                 lower_32_bits(tool_table->mc_address),
     747             :                                 NULL);
     748             :         }
     749             : 
     750           0 :         return ret;
     751             : }
     752             : 
     753           0 : int smu_v11_0_init_display_count(struct smu_context *smu, uint32_t count)
     754             : {
     755           0 :         struct amdgpu_device *adev = smu->adev;
     756             : 
     757             :         /* Navy_Flounder/Dimgrey_Cavefish do not support to change
     758             :          * display num currently
     759             :          */
     760           0 :         if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(11, 0, 11) ||
     761           0 :             adev->ip_versions[MP1_HWIP][0] == IP_VERSION(11, 5, 0) ||
     762           0 :             adev->ip_versions[MP1_HWIP][0] == IP_VERSION(11, 0, 12) ||
     763             :             adev->ip_versions[MP1_HWIP][0] == IP_VERSION(11, 0, 13))
     764             :                 return 0;
     765             : 
     766           0 :         return smu_cmn_send_smc_msg_with_param(smu,
     767             :                                                SMU_MSG_NumOfDisplays,
     768             :                                                count,
     769             :                                                NULL);
     770             : }
     771             : 
     772             : 
     773           0 : int smu_v11_0_set_allowed_mask(struct smu_context *smu)
     774             : {
     775           0 :         struct smu_feature *feature = &smu->smu_feature;
     776           0 :         int ret = 0;
     777             :         uint32_t feature_mask[2];
     778             : 
     779           0 :         if (bitmap_empty(feature->allowed, SMU_FEATURE_MAX) || feature->feature_num < 64) {
     780             :                 ret = -EINVAL;
     781             :                 goto failed;
     782             :         }
     783             : 
     784           0 :         bitmap_copy((unsigned long *)feature_mask, feature->allowed, 64);
     785             : 
     786           0 :         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetAllowedFeaturesMaskHigh,
     787             :                                           feature_mask[1], NULL);
     788           0 :         if (ret)
     789             :                 goto failed;
     790             : 
     791           0 :         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetAllowedFeaturesMaskLow,
     792             :                                           feature_mask[0], NULL);
     793             :         if (ret)
     794             :                 goto failed;
     795             : 
     796             : failed:
     797           0 :         return ret;
     798             : }
     799             : 
     800           0 : int smu_v11_0_system_features_control(struct smu_context *smu,
     801             :                                              bool en)
     802             : {
     803           0 :         return smu_cmn_send_smc_msg(smu, (en ? SMU_MSG_EnableAllSmuFeatures :
     804             :                                           SMU_MSG_DisableAllSmuFeatures), NULL);
     805             : }
     806             : 
     807           0 : int smu_v11_0_notify_display_change(struct smu_context *smu)
     808             : {
     809           0 :         int ret = 0;
     810             : 
     811           0 :         if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT) &&
     812           0 :             smu->adev->gmc.vram_type == AMDGPU_VRAM_TYPE_HBM)
     813           0 :                 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetUclkFastSwitch, 1, NULL);
     814             : 
     815           0 :         return ret;
     816             : }
     817             : 
     818             : static int
     819           0 : smu_v11_0_get_max_sustainable_clock(struct smu_context *smu, uint32_t *clock,
     820             :                                     enum smu_clk_type clock_select)
     821             : {
     822           0 :         int ret = 0;
     823             :         int clk_id;
     824             : 
     825           0 :         if ((smu_cmn_to_asic_specific_index(smu, CMN2ASIC_MAPPING_MSG, SMU_MSG_GetDcModeMaxDpmFreq) < 0) ||
     826           0 :             (smu_cmn_to_asic_specific_index(smu, CMN2ASIC_MAPPING_MSG, SMU_MSG_GetMaxDpmFreq) < 0))
     827             :                 return 0;
     828             : 
     829           0 :         clk_id = smu_cmn_to_asic_specific_index(smu,
     830             :                                                 CMN2ASIC_MAPPING_CLK,
     831             :                                                 clock_select);
     832           0 :         if (clk_id < 0)
     833             :                 return -EINVAL;
     834             : 
     835           0 :         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetDcModeMaxDpmFreq,
     836           0 :                                           clk_id << 16, clock);
     837           0 :         if (ret) {
     838           0 :                 dev_err(smu->adev->dev, "[GetMaxSustainableClock] Failed to get max DC clock from SMC!");
     839           0 :                 return ret;
     840             :         }
     841             : 
     842           0 :         if (*clock != 0)
     843             :                 return 0;
     844             : 
     845             :         /* if DC limit is zero, return AC limit */
     846           0 :         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetMaxDpmFreq,
     847             :                                           clk_id << 16, clock);
     848           0 :         if (ret) {
     849           0 :                 dev_err(smu->adev->dev, "[GetMaxSustainableClock] failed to get max AC clock from SMC!");
     850           0 :                 return ret;
     851             :         }
     852             : 
     853             :         return 0;
     854             : }
     855             : 
     856           0 : int smu_v11_0_init_max_sustainable_clocks(struct smu_context *smu)
     857             : {
     858           0 :         struct smu_11_0_max_sustainable_clocks *max_sustainable_clocks =
     859             :                         smu->smu_table.max_sustainable_clocks;
     860           0 :         int ret = 0;
     861             : 
     862           0 :         max_sustainable_clocks->uclock = smu->smu_table.boot_values.uclk / 100;
     863           0 :         max_sustainable_clocks->soc_clock = smu->smu_table.boot_values.socclk / 100;
     864           0 :         max_sustainable_clocks->dcef_clock = smu->smu_table.boot_values.dcefclk / 100;
     865           0 :         max_sustainable_clocks->display_clock = 0xFFFFFFFF;
     866           0 :         max_sustainable_clocks->phy_clock = 0xFFFFFFFF;
     867           0 :         max_sustainable_clocks->pixel_clock = 0xFFFFFFFF;
     868             : 
     869           0 :         if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
     870           0 :                 ret = smu_v11_0_get_max_sustainable_clock(smu,
     871             :                                                           &(max_sustainable_clocks->uclock),
     872             :                                                           SMU_UCLK);
     873           0 :                 if (ret) {
     874           0 :                         dev_err(smu->adev->dev, "[%s] failed to get max UCLK from SMC!",
     875             :                                __func__);
     876           0 :                         return ret;
     877             :                 }
     878             :         }
     879             : 
     880           0 :         if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_SOCCLK_BIT)) {
     881           0 :                 ret = smu_v11_0_get_max_sustainable_clock(smu,
     882             :                                                           &(max_sustainable_clocks->soc_clock),
     883             :                                                           SMU_SOCCLK);
     884           0 :                 if (ret) {
     885           0 :                         dev_err(smu->adev->dev, "[%s] failed to get max SOCCLK from SMC!",
     886             :                                __func__);
     887           0 :                         return ret;
     888             :                 }
     889             :         }
     890             : 
     891           0 :         if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT)) {
     892           0 :                 ret = smu_v11_0_get_max_sustainable_clock(smu,
     893             :                                                           &(max_sustainable_clocks->dcef_clock),
     894             :                                                           SMU_DCEFCLK);
     895           0 :                 if (ret) {
     896           0 :                         dev_err(smu->adev->dev, "[%s] failed to get max DCEFCLK from SMC!",
     897             :                                __func__);
     898           0 :                         return ret;
     899             :                 }
     900             : 
     901           0 :                 ret = smu_v11_0_get_max_sustainable_clock(smu,
     902             :                                                           &(max_sustainable_clocks->display_clock),
     903             :                                                           SMU_DISPCLK);
     904           0 :                 if (ret) {
     905           0 :                         dev_err(smu->adev->dev, "[%s] failed to get max DISPCLK from SMC!",
     906             :                                __func__);
     907           0 :                         return ret;
     908             :                 }
     909           0 :                 ret = smu_v11_0_get_max_sustainable_clock(smu,
     910             :                                                           &(max_sustainable_clocks->phy_clock),
     911             :                                                           SMU_PHYCLK);
     912           0 :                 if (ret) {
     913           0 :                         dev_err(smu->adev->dev, "[%s] failed to get max PHYCLK from SMC!",
     914             :                                __func__);
     915           0 :                         return ret;
     916             :                 }
     917           0 :                 ret = smu_v11_0_get_max_sustainable_clock(smu,
     918             :                                                           &(max_sustainable_clocks->pixel_clock),
     919             :                                                           SMU_PIXCLK);
     920           0 :                 if (ret) {
     921           0 :                         dev_err(smu->adev->dev, "[%s] failed to get max PIXCLK from SMC!",
     922             :                                __func__);
     923           0 :                         return ret;
     924             :                 }
     925             :         }
     926             : 
     927           0 :         if (max_sustainable_clocks->soc_clock < max_sustainable_clocks->uclock)
     928           0 :                 max_sustainable_clocks->uclock = max_sustainable_clocks->soc_clock;
     929             : 
     930             :         return 0;
     931             : }
     932             : 
     933           0 : int smu_v11_0_get_current_power_limit(struct smu_context *smu,
     934             :                                       uint32_t *power_limit)
     935             : {
     936             :         int power_src;
     937           0 :         int ret = 0;
     938             : 
     939           0 :         if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT))
     940             :                 return -EINVAL;
     941             : 
     942           0 :         power_src = smu_cmn_to_asic_specific_index(smu,
     943             :                                         CMN2ASIC_MAPPING_PWR,
     944           0 :                                         smu->adev->pm.ac_power ?
     945           0 :                                         SMU_POWER_SOURCE_AC :
     946             :                                         SMU_POWER_SOURCE_DC);
     947           0 :         if (power_src < 0)
     948             :                 return -EINVAL;
     949             : 
     950             :         /*
     951             :          * BIT 24-31: ControllerId (only PPT0 is supported for now)
     952             :          * BIT 16-23: PowerSource
     953             :          */
     954           0 :         ret = smu_cmn_send_smc_msg_with_param(smu,
     955             :                                           SMU_MSG_GetPptLimit,
     956           0 :                                           (0 << 24) | (power_src << 16),
     957             :                                           power_limit);
     958           0 :         if (ret)
     959           0 :                 dev_err(smu->adev->dev, "[%s] get PPT limit failed!", __func__);
     960             : 
     961             :         return ret;
     962             : }
     963             : 
     964           0 : int smu_v11_0_set_power_limit(struct smu_context *smu,
     965             :                               enum smu_ppt_limit_type limit_type,
     966             :                               uint32_t limit)
     967             : {
     968             :         int power_src;
     969           0 :         int ret = 0;
     970             :         uint32_t limit_param;
     971             : 
     972           0 :         if (limit_type != SMU_DEFAULT_PPT_LIMIT)
     973             :                 return -EINVAL;
     974             : 
     975           0 :         if (!smu_cmn_feature_is_enabled(smu, SMU_FEATURE_PPT_BIT)) {
     976           0 :                 dev_err(smu->adev->dev, "Setting new power limit is not supported!\n");
     977           0 :                 return -EOPNOTSUPP;
     978             :         }
     979             : 
     980           0 :         power_src = smu_cmn_to_asic_specific_index(smu,
     981             :                                         CMN2ASIC_MAPPING_PWR,
     982           0 :                                         smu->adev->pm.ac_power ?
     983           0 :                                         SMU_POWER_SOURCE_AC :
     984             :                                         SMU_POWER_SOURCE_DC);
     985           0 :         if (power_src < 0)
     986             :                 return -EINVAL;
     987             : 
     988             :         /*
     989             :          * BIT 24-31: ControllerId (only PPT0 is supported for now)
     990             :          * BIT 16-23: PowerSource
     991             :          * BIT 0-15: PowerLimit
     992             :          */
     993           0 :         limit_param  = (limit & 0xFFFF);
     994           0 :         limit_param |= 0 << 24;
     995           0 :         limit_param |= (power_src) << 16;
     996           0 :         ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetPptLimit, limit_param, NULL);
     997           0 :         if (ret) {
     998           0 :                 dev_err(smu->adev->dev, "[%s] Set power limit Failed!\n", __func__);
     999           0 :                 return ret;
    1000             :         }
    1001             : 
    1002           0 :         smu->current_power_limit = limit;
    1003             : 
    1004           0 :         return 0;
    1005             : }
    1006             : 
    1007             : static int smu_v11_0_ack_ac_dc_interrupt(struct smu_context *smu)
    1008             : {
    1009           0 :         return smu_cmn_send_smc_msg(smu,
    1010             :                                 SMU_MSG_ReenableAcDcInterrupt,
    1011             :                                 NULL);
    1012             : }
    1013             : 
    1014           0 : static int smu_v11_0_process_pending_interrupt(struct smu_context *smu)
    1015             : {
    1016           0 :         int ret = 0;
    1017             : 
    1018           0 :         if (smu->dc_controlled_by_gpio &&
    1019           0 :             smu_cmn_feature_is_enabled(smu, SMU_FEATURE_ACDC_BIT))
    1020           0 :                 ret = smu_v11_0_ack_ac_dc_interrupt(smu);
    1021             : 
    1022           0 :         return ret;
    1023             : }
    1024             : 
    1025           0 : void smu_v11_0_interrupt_work(struct smu_context *smu)
    1026             : {
    1027           0 :         if (smu_v11_0_ack_ac_dc_interrupt(smu))
    1028           0 :                 dev_err(smu->adev->dev, "Ack AC/DC interrupt Failed!\n");
    1029           0 : }
    1030             : 
    1031           0 : int smu_v11_0_enable_thermal_alert(struct smu_context *smu)
    1032             : {
    1033           0 :         int ret = 0;
    1034             : 
    1035           0 :         if (smu->smu_table.thermal_controller_type) {
    1036           0 :                 ret = amdgpu_irq_get(smu->adev, &smu->irq_source, 0);
    1037           0 :                 if (ret)
    1038             :                         return ret;
    1039             :         }
    1040             : 
    1041             :         /*
    1042             :          * After init there might have been missed interrupts triggered
    1043             :          * before driver registers for interrupt (Ex. AC/DC).
    1044             :          */
    1045           0 :         return smu_v11_0_process_pending_interrupt(smu);
    1046             : }
    1047             : 
    1048           0 : int smu_v11_0_disable_thermal_alert(struct smu_context *smu)
    1049             : {
    1050           0 :         return amdgpu_irq_put(smu->adev, &smu->irq_source, 0);
    1051             : }
    1052             : 
    1053             : static uint16_t convert_to_vddc(uint8_t vid)
    1054             : {
    1055           0 :         return (uint16_t) ((6200 - (vid * 25)) / SMU11_VOLTAGE_SCALE);
    1056             : }
    1057             : 
    1058           0 : int smu_v11_0_get_gfx_vdd(struct smu_context *smu, uint32_t *value)
    1059             : {
    1060           0 :         struct amdgpu_device *adev = smu->adev;
    1061           0 :         uint32_t vdd = 0, val_vid = 0;
    1062             : 
    1063           0 :         if (!value)
    1064             :                 return -EINVAL;
    1065           0 :         val_vid = (RREG32_SOC15(SMUIO, 0, mmSMUSVI0_TEL_PLANE0) &
    1066           0 :                 SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR_MASK) >>
    1067             :                 SMUSVI0_TEL_PLANE0__SVI0_PLANE0_VDDCOR__SHIFT;
    1068             : 
    1069           0 :         vdd = (uint32_t)convert_to_vddc((uint8_t)val_vid);
    1070             : 
    1071           0 :         *value = vdd;
    1072             : 
    1073           0 :         return 0;
    1074             : 
    1075             : }
    1076             : 
    1077             : int
    1078           0 : smu_v11_0_display_clock_voltage_request(struct smu_context *smu,
    1079             :                                         struct pp_display_clock_request
    1080             :                                         *clock_req)
    1081             : {
    1082           0 :         enum amd_pp_clock_type clk_type = clock_req->clock_type;
    1083           0 :         int ret = 0;
    1084           0 :         enum smu_clk_type clk_select = 0;
    1085           0 :         uint32_t clk_freq = clock_req->clock_freq_in_khz / 1000;
    1086             : 
    1087           0 :         if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_DCEFCLK_BIT) ||
    1088           0 :                 smu_cmn_feature_is_enabled(smu, SMU_FEATURE_DPM_UCLK_BIT)) {
    1089           0 :                 switch (clk_type) {
    1090             :                 case amd_pp_dcef_clock:
    1091             :                         clk_select = SMU_DCEFCLK;
    1092             :                         break;
    1093             :                 case amd_pp_disp_clock:
    1094           0 :                         clk_select = SMU_DISPCLK;
    1095           0 :                         break;
    1096             :                 case amd_pp_pixel_clock:
    1097           0 :                         clk_select = SMU_PIXCLK;
    1098           0 :                         break;
    1099             :                 case amd_pp_phy_clock:
    1100           0 :                         clk_select = SMU_PHYCLK;
    1101           0 :                         break;
    1102             :                 case amd_pp_mem_clock:
    1103           0 :                         clk_select = SMU_UCLK;
    1104           0 :                         break;
    1105             :                 default:
    1106           0 :                         dev_info(smu->adev->dev, "[%s] Invalid Clock Type!", __func__);
    1107           0 :                         ret = -EINVAL;
    1108           0 :                         break;
    1109             :                 }
    1110             : 
    1111           0 :                 if (ret)
    1112             :                         goto failed;
    1113             : 
    1114           0 :                 if (clk_select == SMU_UCLK && smu->disable_uclk_switch)
    1115             :                         return 0;
    1116             : 
    1117           0 :                 ret = smu_v11_0_set_hard_freq_limited_range(smu, clk_select, clk_freq, 0);
    1118             : 
    1119           0 :                 if(clk_select == SMU_UCLK)
    1120           0 :                         smu->hard_min_uclk_req_from_dal = clk_freq;
    1121             :         }
    1122             : 
    1123             : failed:
    1124             :         return ret;
    1125             : }
    1126             : 
    1127           0 : int smu_v11_0_gfx_off_control(struct smu_context *smu, bool enable)
    1128             : {
    1129           0 :         int ret = 0;
    1130           0 :         struct amdgpu_device *adev = smu->adev;
    1131             : 
    1132           0 :         switch (adev->ip_versions[MP1_HWIP][0]) {
    1133             :         case IP_VERSION(11, 0, 0):
    1134             :         case IP_VERSION(11, 0, 5):
    1135             :         case IP_VERSION(11, 0, 9):
    1136             :         case IP_VERSION(11, 0, 7):
    1137             :         case IP_VERSION(11, 0, 11):
    1138             :         case IP_VERSION(11, 0, 12):
    1139             :         case IP_VERSION(11, 0, 13):
    1140             :         case IP_VERSION(11, 5, 0):
    1141           0 :                 if (!(adev->pm.pp_feature & PP_GFXOFF_MASK))
    1142             :                         return 0;
    1143           0 :                 if (enable)
    1144           0 :                         ret = smu_cmn_send_smc_msg(smu, SMU_MSG_AllowGfxOff, NULL);
    1145             :                 else
    1146           0 :                         ret = smu_cmn_send_smc_msg(smu, SMU_MSG_DisallowGfxOff, NULL);
    1147             :                 break;
    1148             :         default:
    1149             :                 break;
    1150             :         }
    1151             : 
    1152             :         return ret;
    1153             : }
    1154             : 
    1155             : uint32_t
    1156           0 : smu_v11_0_get_fan_control_mode(struct smu_context *smu)
    1157             : {
    1158           0 :         if (smu_cmn_feature_is_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT))
    1159             :                 return AMD_FAN_CTRL_AUTO;
    1160             :         else
    1161           0 :                 return smu->user_dpm_profile.fan_mode;
    1162             : }
    1163             : 
    1164             : static int
    1165           0 : smu_v11_0_auto_fan_control(struct smu_context *smu, bool auto_fan_control)
    1166             : {
    1167           0 :         int ret = 0;
    1168             : 
    1169           0 :         if (!smu_cmn_feature_is_supported(smu, SMU_FEATURE_FAN_CONTROL_BIT))
    1170             :                 return 0;
    1171             : 
    1172           0 :         ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_FAN_CONTROL_BIT, auto_fan_control);
    1173           0 :         if (ret)
    1174           0 :                 dev_err(smu->adev->dev, "[%s]%s smc FAN CONTROL feature failed!",
    1175             :                        __func__, (auto_fan_control ? "Start" : "Stop"));
    1176             : 
    1177             :         return ret;
    1178             : }
    1179             : 
    1180             : static int
    1181           0 : smu_v11_0_set_fan_static_mode(struct smu_context *smu, uint32_t mode)
    1182             : {
    1183           0 :         struct amdgpu_device *adev = smu->adev;
    1184             : 
    1185           0 :         WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2,
    1186             :                      REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
    1187             :                                    CG_FDO_CTRL2, TMIN, 0));
    1188           0 :         WREG32_SOC15(THM, 0, mmCG_FDO_CTRL2,
    1189             :                      REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL2),
    1190             :                                    CG_FDO_CTRL2, FDO_PWM_MODE, mode));
    1191             : 
    1192           0 :         return 0;
    1193             : }
    1194             : 
    1195             : int
    1196           0 : smu_v11_0_set_fan_speed_pwm(struct smu_context *smu, uint32_t speed)
    1197             : {
    1198           0 :         struct amdgpu_device *adev = smu->adev;
    1199             :         uint32_t duty100, duty;
    1200             :         uint64_t tmp64;
    1201             : 
    1202           0 :         speed = MIN(speed, 255);
    1203             : 
    1204           0 :         duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1),
    1205             :                                 CG_FDO_CTRL1, FMAX_DUTY100);
    1206           0 :         if (!duty100)
    1207             :                 return -EINVAL;
    1208             : 
    1209           0 :         tmp64 = (uint64_t)speed * duty100;
    1210           0 :         do_div(tmp64, 255);
    1211           0 :         duty = (uint32_t)tmp64;
    1212             : 
    1213           0 :         WREG32_SOC15(THM, 0, mmCG_FDO_CTRL0,
    1214             :                      REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL0),
    1215             :                                    CG_FDO_CTRL0, FDO_STATIC_DUTY, duty));
    1216             : 
    1217           0 :         return smu_v11_0_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC);
    1218             : }
    1219             : 
    1220           0 : int smu_v11_0_set_fan_speed_rpm(struct smu_context *smu,
    1221             :                                 uint32_t speed)
    1222             : {
    1223           0 :         struct amdgpu_device *adev = smu->adev;
    1224             :         /*
    1225             :          * crystal_clock_freq used for fan speed rpm calculation is
    1226             :          * always 25Mhz. So, hardcode it as 2500(in 10K unit).
    1227             :          */
    1228           0 :         uint32_t crystal_clock_freq = 2500;
    1229             :         uint32_t tach_period;
    1230             : 
    1231           0 :         if (speed == 0)
    1232             :                 return -EINVAL;
    1233             :         /*
    1234             :          * To prevent from possible overheat, some ASICs may have requirement
    1235             :          * for minimum fan speed:
    1236             :          * - For some NV10 SKU, the fan speed cannot be set lower than
    1237             :          *   700 RPM.
    1238             :          * - For some Sienna Cichlid SKU, the fan speed cannot be set
    1239             :          *   lower than 500 RPM.
    1240             :          */
    1241           0 :         tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed);
    1242           0 :         WREG32_SOC15(THM, 0, mmCG_TACH_CTRL,
    1243             :                      REG_SET_FIELD(RREG32_SOC15(THM, 0, mmCG_TACH_CTRL),
    1244             :                                    CG_TACH_CTRL, TARGET_PERIOD,
    1245             :                                    tach_period));
    1246             : 
    1247           0 :         return smu_v11_0_set_fan_static_mode(smu, FDO_PWM_MODE_STATIC_RPM);
    1248             : }
    1249             : 
    1250           0 : int smu_v11_0_get_fan_speed_pwm(struct smu_context *smu,
    1251             :                                 uint32_t *speed)
    1252             : {
    1253           0 :         struct amdgpu_device *adev = smu->adev;
    1254             :         uint32_t duty100, duty;
    1255             :         uint64_t tmp64;
    1256             : 
    1257             :         /*
    1258             :          * For pre Sienna Cichlid ASICs, the 0 RPM may be not correctly
    1259             :          * detected via register retrieving. To workaround this, we will
    1260             :          * report the fan speed as 0 PWM if user just requested such.
    1261             :          */
    1262           0 :         if ((smu->user_dpm_profile.flags & SMU_CUSTOM_FAN_SPEED_PWM)
    1263           0 :              && !smu->user_dpm_profile.fan_speed_pwm) {
    1264           0 :                 *speed = 0;
    1265           0 :                 return 0;
    1266             :         }
    1267             : 
    1268           0 :         duty100 = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_FDO_CTRL1),
    1269             :                                 CG_FDO_CTRL1, FMAX_DUTY100);
    1270           0 :         duty = REG_GET_FIELD(RREG32_SOC15(THM, 0, mmCG_THERMAL_STATUS),
    1271             :                                 CG_THERMAL_STATUS, FDO_PWM_DUTY);
    1272           0 :         if (!duty100)
    1273             :                 return -EINVAL;
    1274             : 
    1275           0 :         tmp64 = (uint64_t)duty * 255;
    1276           0 :         do_div(tmp64, duty100);
    1277           0 :         *speed = MIN((uint32_t)tmp64, 255);
    1278             : 
    1279           0 :         return 0;
    1280             : }
    1281             : 
    1282           0 : int smu_v11_0_get_fan_speed_rpm(struct smu_context *smu,
    1283             :                                 uint32_t *speed)
    1284             : {
    1285           0 :         struct amdgpu_device *adev = smu->adev;
    1286           0 :         uint32_t crystal_clock_freq = 2500;
    1287             :         uint32_t tach_status;
    1288             :         uint64_t tmp64;
    1289             : 
    1290             :         /*
    1291             :          * For pre Sienna Cichlid ASICs, the 0 RPM may be not correctly
    1292             :          * detected via register retrieving. To workaround this, we will
    1293             :          * report the fan speed as 0 RPM if user just requested such.
    1294             :          */
    1295           0 :         if ((smu->user_dpm_profile.flags & SMU_CUSTOM_FAN_SPEED_RPM)
    1296           0 :              && !smu->user_dpm_profile.fan_speed_rpm) {
    1297           0 :                 *speed = 0;
    1298           0 :                 return 0;
    1299             :         }
    1300             : 
    1301           0 :         tmp64 = (uint64_t)crystal_clock_freq * 60 * 10000;
    1302             : 
    1303           0 :         tach_status = RREG32_SOC15(THM, 0, mmCG_TACH_STATUS);
    1304           0 :         if (tach_status) {
    1305           0 :                 do_div(tmp64, tach_status);
    1306           0 :                 *speed = (uint32_t)tmp64;
    1307             :         } else {
    1308           0 :                 dev_warn_once(adev->dev, "Got zero output on CG_TACH_STATUS reading!\n");
    1309           0 :                 *speed = 0;
    1310             :         }
    1311             : 
    1312             :         return 0;
    1313             : }
    1314             : 
    1315             : int
    1316           0 : smu_v11_0_set_fan_control_mode(struct smu_context *smu,
    1317             :                                uint32_t mode)
    1318             : {
    1319           0 :         int ret = 0;
    1320             : 
    1321           0 :         switch (mode) {
    1322             :         case AMD_FAN_CTRL_NONE:
    1323           0 :                 ret = smu_v11_0_auto_fan_control(smu, 0);
    1324           0 :                 if (!ret)
    1325           0 :                         ret = smu_v11_0_set_fan_speed_pwm(smu, 255);
    1326             :                 break;
    1327             :         case AMD_FAN_CTRL_MANUAL:
    1328           0 :                 ret = smu_v11_0_auto_fan_control(smu, 0);
    1329           0 :                 break;
    1330             :         case AMD_FAN_CTRL_AUTO:
    1331           0 :                 ret = smu_v11_0_auto_fan_control(smu, 1);
    1332           0 :                 break;
    1333             :         default:
    1334             :                 break;
    1335             :         }
    1336             : 
    1337           0 :         if (ret) {
    1338           0 :                 dev_err(smu->adev->dev, "[%s]Set fan control mode failed!", __func__);
    1339           0 :                 return -EINVAL;
    1340             :         }
    1341             : 
    1342             :         return ret;
    1343             : }
    1344             : 
    1345           0 : int smu_v11_0_set_xgmi_pstate(struct smu_context *smu,
    1346             :                                      uint32_t pstate)
    1347             : {
    1348           0 :         return smu_cmn_send_smc_msg_with_param(smu,
    1349             :                                                SMU_MSG_SetXgmiMode,
    1350             :                                                pstate ? XGMI_MODE_PSTATE_D0 : XGMI_MODE_PSTATE_D3,
    1351             :                                           NULL);
    1352             : }
    1353             : 
    1354           0 : static int smu_v11_0_set_irq_state(struct amdgpu_device *adev,
    1355             :                                    struct amdgpu_irq_src *source,
    1356             :                                    unsigned tyep,
    1357             :                                    enum amdgpu_interrupt_state state)
    1358             : {
    1359           0 :         struct smu_context *smu = adev->powerplay.pp_handle;
    1360             :         uint32_t low, high;
    1361           0 :         uint32_t val = 0;
    1362             : 
    1363           0 :         switch (state) {
    1364             :         case AMDGPU_IRQ_STATE_DISABLE:
    1365             :                 /* For THM irqs */
    1366           0 :                 val = RREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL);
    1367           0 :                 val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTH_MASK, 1);
    1368           0 :                 val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTL_MASK, 1);
    1369           0 :                 WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val);
    1370             : 
    1371           0 :                 WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, 0);
    1372             : 
    1373             :                 /* For MP1 SW irqs */
    1374           0 :                 val = RREG32_SOC15(MP1, 0, mmMP1_SMN_IH_SW_INT_CTRL);
    1375           0 :                 val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT_CTRL, INT_MASK, 1);
    1376           0 :                 WREG32_SOC15(MP1, 0, mmMP1_SMN_IH_SW_INT_CTRL, val);
    1377             : 
    1378             :                 break;
    1379             :         case AMDGPU_IRQ_STATE_ENABLE:
    1380             :                 /* For THM irqs */
    1381           0 :                 low = max(SMU_THERMAL_MINIMUM_ALERT_TEMP,
    1382             :                                 smu->thermal_range.min / SMU_TEMPERATURE_UNITS_PER_CENTIGRADES);
    1383           0 :                 high = min(SMU_THERMAL_MAXIMUM_ALERT_TEMP,
    1384             :                                 smu->thermal_range.software_shutdown_temp);
    1385             : 
    1386           0 :                 val = RREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL);
    1387           0 :                 val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, MAX_IH_CREDIT, 5);
    1388           0 :                 val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_IH_HW_ENA, 1);
    1389           0 :                 val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTH_MASK, 0);
    1390           0 :                 val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, THERM_INTL_MASK, 0);
    1391           0 :                 val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTH, (high & 0xff));
    1392           0 :                 val = REG_SET_FIELD(val, THM_THERMAL_INT_CTRL, DIG_THERM_INTL, (low & 0xff));
    1393           0 :                 val = val & (~THM_THERMAL_INT_CTRL__THERM_TRIGGER_MASK_MASK);
    1394           0 :                 WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_CTRL, val);
    1395             : 
    1396           0 :                 val = (1 << THM_THERMAL_INT_ENA__THERM_INTH_CLR__SHIFT);
    1397           0 :                 val |= (1 << THM_THERMAL_INT_ENA__THERM_INTL_CLR__SHIFT);
    1398           0 :                 val |= (1 << THM_THERMAL_INT_ENA__THERM_TRIGGER_CLR__SHIFT);
    1399           0 :                 WREG32_SOC15(THM, 0, mmTHM_THERMAL_INT_ENA, val);
    1400             : 
    1401             :                 /* For MP1 SW irqs */
    1402           0 :                 val = RREG32_SOC15(MP1, 0, mmMP1_SMN_IH_SW_INT);
    1403           0 :                 val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT, ID, 0xFE);
    1404           0 :                 val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT, VALID, 0);
    1405           0 :                 WREG32_SOC15(MP1, 0, mmMP1_SMN_IH_SW_INT, val);
    1406             : 
    1407           0 :                 val = RREG32_SOC15(MP1, 0, mmMP1_SMN_IH_SW_INT_CTRL);
    1408           0 :                 val = REG_SET_FIELD(val, MP1_SMN_IH_SW_INT_CTRL, INT_MASK, 0);
    1409           0 :                 WREG32_SOC15(MP1, 0, mmMP1_SMN_IH_SW_INT_CTRL, val);
    1410             : 
    1411             :                 break;
    1412             :         default:
    1413             :                 break;
    1414             :         }
    1415             : 
    1416           0 :         return 0;
    1417             : }
    1418             : 
    1419             : #define THM_11_0__SRCID__THM_DIG_THERM_L2H              0               /* ASIC_TEMP > CG_THERMAL_INT.DIG_THERM_INTH  */
    1420             : #define THM_11_0__SRCID__THM_DIG_THERM_H2L              1               /* ASIC_TEMP < CG_THERMAL_INT.DIG_THERM_INTL  */
    1421             : 
    1422             : #define SMUIO_11_0__SRCID__SMUIO_GPIO19                 83
    1423             : 
    1424           0 : static int smu_v11_0_irq_process(struct amdgpu_device *adev,
    1425             :                                  struct amdgpu_irq_src *source,
    1426             :                                  struct amdgpu_iv_entry *entry)
    1427             : {
    1428           0 :         struct smu_context *smu = adev->powerplay.pp_handle;
    1429           0 :         uint32_t client_id = entry->client_id;
    1430           0 :         uint32_t src_id = entry->src_id;
    1431             :         /*
    1432             :          * ctxid is used to distinguish different
    1433             :          * events for SMCToHost interrupt.
    1434             :          */
    1435           0 :         uint32_t ctxid = entry->src_data[0];
    1436             :         uint32_t data;
    1437             : 
    1438           0 :         if (client_id == SOC15_IH_CLIENTID_THM) {
    1439           0 :                 switch (src_id) {
    1440             :                 case THM_11_0__SRCID__THM_DIG_THERM_L2H:
    1441           0 :                         dev_emerg(adev->dev, "ERROR: GPU over temperature range(SW CTF) detected!\n");
    1442             :                         /*
    1443             :                          * SW CTF just occurred.
    1444             :                          * Try to do a graceful shutdown to prevent further damage.
    1445             :                          */
    1446           0 :                         dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU SW CTF!\n");
    1447           0 :                         orderly_poweroff(true);
    1448           0 :                 break;
    1449             :                 case THM_11_0__SRCID__THM_DIG_THERM_H2L:
    1450           0 :                         dev_emerg(adev->dev, "ERROR: GPU under temperature range detected\n");
    1451           0 :                 break;
    1452             :                 default:
    1453           0 :                         dev_emerg(adev->dev, "ERROR: GPU under temperature range unknown src id (%d)\n",
    1454             :                                 src_id);
    1455           0 :                 break;
    1456             :                 }
    1457           0 :         } else if (client_id == SOC15_IH_CLIENTID_ROM_SMUIO) {
    1458           0 :                 dev_emerg(adev->dev, "ERROR: GPU HW Critical Temperature Fault(aka CTF) detected!\n");
    1459             :                 /*
    1460             :                  * HW CTF just occurred. Shutdown to prevent further damage.
    1461             :                  */
    1462           0 :                 dev_emerg(adev->dev, "ERROR: System is going to shutdown due to GPU HW CTF!\n");
    1463           0 :                 orderly_poweroff(true);
    1464           0 :         } else if (client_id == SOC15_IH_CLIENTID_MP1) {
    1465           0 :                 if (src_id == 0xfe) {
    1466             :                         /* ACK SMUToHost interrupt */
    1467           0 :                         data = RREG32_SOC15(MP1, 0, mmMP1_SMN_IH_SW_INT_CTRL);
    1468           0 :                         data = REG_SET_FIELD(data, MP1_SMN_IH_SW_INT_CTRL, INT_ACK, 1);
    1469           0 :                         WREG32_SOC15(MP1, 0, mmMP1_SMN_IH_SW_INT_CTRL, data);
    1470             : 
    1471           0 :                         switch (ctxid) {
    1472             :                         case 0x3:
    1473             :                                 dev_dbg(adev->dev, "Switched to AC mode!\n");
    1474           0 :                                 schedule_work(&smu->interrupt_work);
    1475             :                                 break;
    1476             :                         case 0x4:
    1477             :                                 dev_dbg(adev->dev, "Switched to DC mode!\n");
    1478           0 :                                 schedule_work(&smu->interrupt_work);
    1479             :                                 break;
    1480             :                         case 0x7:
    1481             :                                 /*
    1482             :                                  * Increment the throttle interrupt counter
    1483             :                                  */
    1484           0 :                                 atomic64_inc(&smu->throttle_int_counter);
    1485             : 
    1486           0 :                                 if (!atomic_read(&adev->throttling_logging_enabled))
    1487             :                                         return 0;
    1488             : 
    1489           0 :                                 if (__ratelimit(&adev->throttling_logging_rs))
    1490           0 :                                         schedule_work(&smu->throttling_logging_work);
    1491             : 
    1492             :                                 break;
    1493             :                         }
    1494             :                 }
    1495             :         }
    1496             : 
    1497             :         return 0;
    1498             : }
    1499             : 
    1500             : static const struct amdgpu_irq_src_funcs smu_v11_0_irq_funcs =
    1501             : {
    1502             :         .set = smu_v11_0_set_irq_state,
    1503             :         .process = smu_v11_0_irq_process,
    1504             : };
    1505             : 
    1506           0 : int smu_v11_0_register_irq_handler(struct smu_context *smu)
    1507             : {
    1508           0 :         struct amdgpu_device *adev = smu->adev;
    1509           0 :         struct amdgpu_irq_src *irq_src = &smu->irq_source;
    1510           0 :         int ret = 0;
    1511             : 
    1512           0 :         irq_src->num_types = 1;
    1513           0 :         irq_src->funcs = &smu_v11_0_irq_funcs;
    1514             : 
    1515           0 :         ret = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_THM,
    1516             :                                 THM_11_0__SRCID__THM_DIG_THERM_L2H,
    1517             :                                 irq_src);
    1518           0 :         if (ret)
    1519             :                 return ret;
    1520             : 
    1521           0 :         ret = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_THM,
    1522             :                                 THM_11_0__SRCID__THM_DIG_THERM_H2L,
    1523             :                                 irq_src);
    1524           0 :         if (ret)
    1525             :                 return ret;
    1526             : 
    1527             :         /* Register CTF(GPIO_19) interrupt */
    1528           0 :         ret = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_ROM_SMUIO,
    1529             :                                 SMUIO_11_0__SRCID__SMUIO_GPIO19,
    1530             :                                 irq_src);
    1531           0 :         if (ret)
    1532             :                 return ret;
    1533             : 
    1534           0 :         ret = amdgpu_irq_add_id(adev, SOC15_IH_CLIENTID_MP1,
    1535             :                                 0xfe,
    1536             :                                 irq_src);
    1537             :         if (ret)
    1538             :                 return ret;
    1539             : 
    1540             :         return ret;
    1541             : }
    1542             : 
    1543           0 : int smu_v11_0_get_max_sustainable_clocks_by_dc(struct smu_context *smu,
    1544             :                 struct pp_smu_nv_clock_table *max_clocks)
    1545             : {
    1546           0 :         struct smu_table_context *table_context = &smu->smu_table;
    1547           0 :         struct smu_11_0_max_sustainable_clocks *sustainable_clocks = NULL;
    1548             : 
    1549           0 :         if (!max_clocks || !table_context->max_sustainable_clocks)
    1550             :                 return -EINVAL;
    1551             : 
    1552           0 :         sustainable_clocks = table_context->max_sustainable_clocks;
    1553             : 
    1554           0 :         max_clocks->dcfClockInKhz =
    1555           0 :                         (unsigned int) sustainable_clocks->dcef_clock * 1000;
    1556           0 :         max_clocks->displayClockInKhz =
    1557           0 :                         (unsigned int) sustainable_clocks->display_clock * 1000;
    1558           0 :         max_clocks->phyClockInKhz =
    1559           0 :                         (unsigned int) sustainable_clocks->phy_clock * 1000;
    1560           0 :         max_clocks->pixelClockInKhz =
    1561           0 :                         (unsigned int) sustainable_clocks->pixel_clock * 1000;
    1562           0 :         max_clocks->uClockInKhz =
    1563           0 :                         (unsigned int) sustainable_clocks->uclock * 1000;
    1564           0 :         max_clocks->socClockInKhz =
    1565           0 :                         (unsigned int) sustainable_clocks->soc_clock * 1000;
    1566           0 :         max_clocks->dscClockInKhz = 0;
    1567           0 :         max_clocks->dppClockInKhz = 0;
    1568           0 :         max_clocks->fabricClockInKhz = 0;
    1569             : 
    1570           0 :         return 0;
    1571             : }
    1572             : 
    1573           0 : int smu_v11_0_set_azalia_d3_pme(struct smu_context *smu)
    1574             : {
    1575           0 :         return smu_cmn_send_smc_msg(smu, SMU_MSG_BacoAudioD3PME, NULL);
    1576             : }
    1577             : 
    1578           0 : int smu_v11_0_baco_set_armd3_sequence(struct smu_context *smu,
    1579             :                                       enum smu_v11_0_baco_seq baco_seq)
    1580             : {
    1581           0 :         return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ArmD3, baco_seq, NULL);
    1582             : }
    1583             : 
    1584           0 : bool smu_v11_0_baco_is_support(struct smu_context *smu)
    1585             : {
    1586           0 :         struct smu_baco_context *smu_baco = &smu->smu_baco;
    1587             : 
    1588           0 :         if (amdgpu_sriov_vf(smu->adev) || !smu_baco->platform_support)
    1589             :                 return false;
    1590             : 
    1591             :         /* Arcturus does not support this bit mask */
    1592           0 :         if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_BACO_BIT) &&
    1593           0 :            !smu_cmn_feature_is_enabled(smu, SMU_FEATURE_BACO_BIT))
    1594             :                 return false;
    1595             : 
    1596             :         return true;
    1597             : }
    1598             : 
    1599           0 : enum smu_baco_state smu_v11_0_baco_get_state(struct smu_context *smu)
    1600             : {
    1601           0 :         struct smu_baco_context *smu_baco = &smu->smu_baco;
    1602             : 
    1603           0 :         return smu_baco->state;
    1604             : }
    1605             : 
    1606             : #define D3HOT_BACO_SEQUENCE 0
    1607             : #define D3HOT_BAMACO_SEQUENCE 2
    1608             : 
    1609           0 : int smu_v11_0_baco_set_state(struct smu_context *smu, enum smu_baco_state state)
    1610             : {
    1611           0 :         struct smu_baco_context *smu_baco = &smu->smu_baco;
    1612           0 :         struct amdgpu_device *adev = smu->adev;
    1613           0 :         struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
    1614             :         uint32_t data;
    1615           0 :         int ret = 0;
    1616             : 
    1617           0 :         if (smu_v11_0_baco_get_state(smu) == state)
    1618             :                 return 0;
    1619             : 
    1620           0 :         if (state == SMU_BACO_STATE_ENTER) {
    1621           0 :                 switch (adev->ip_versions[MP1_HWIP][0]) {
    1622             :                 case IP_VERSION(11, 0, 7):
    1623             :                 case IP_VERSION(11, 0, 11):
    1624             :                 case IP_VERSION(11, 0, 12):
    1625             :                 case IP_VERSION(11, 0, 13):
    1626           0 :                         if (amdgpu_runtime_pm == 2)
    1627           0 :                                 ret = smu_cmn_send_smc_msg_with_param(smu,
    1628             :                                                                       SMU_MSG_EnterBaco,
    1629             :                                                                       D3HOT_BAMACO_SEQUENCE,
    1630             :                                                                       NULL);
    1631             :                         else
    1632           0 :                                 ret = smu_cmn_send_smc_msg_with_param(smu,
    1633             :                                                                       SMU_MSG_EnterBaco,
    1634             :                                                                       D3HOT_BACO_SEQUENCE,
    1635             :                                                                       NULL);
    1636             :                         break;
    1637             :                 default:
    1638           0 :                         if (!ras || !adev->ras_enabled ||
    1639           0 :                             adev->gmc.xgmi.pending_reset) {
    1640           0 :                                 if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(11, 0, 2)) {
    1641           0 :                                         data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL_ARCT);
    1642           0 :                                         data |= 0x80000000;
    1643           0 :                                         WREG32_SOC15(THM, 0, mmTHM_BACO_CNTL_ARCT, data);
    1644             :                                 } else {
    1645           0 :                                         data = RREG32_SOC15(THM, 0, mmTHM_BACO_CNTL);
    1646           0 :                                         data |= 0x80000000;
    1647           0 :                                         WREG32_SOC15(THM, 0, mmTHM_BACO_CNTL, data);
    1648             :                                 }
    1649             : 
    1650           0 :                                 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 0, NULL);
    1651             :                         } else {
    1652           0 :                                 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnterBaco, 1, NULL);
    1653             :                         }
    1654             :                         break;
    1655             :                 }
    1656             : 
    1657             :         } else {
    1658           0 :                 ret = smu_cmn_send_smc_msg(smu, SMU_MSG_ExitBaco, NULL);
    1659           0 :                 if (ret)
    1660             :                         return ret;
    1661             : 
    1662             :                 /* clear vbios scratch 6 and 7 for coming asic reinit */
    1663           0 :                 WREG32(adev->bios_scratch_reg_offset + 6, 0);
    1664           0 :                 WREG32(adev->bios_scratch_reg_offset + 7, 0);
    1665             :         }
    1666             : 
    1667           0 :         if (!ret)
    1668           0 :                 smu_baco->state = state;
    1669             : 
    1670             :         return ret;
    1671             : }
    1672             : 
    1673           0 : int smu_v11_0_baco_enter(struct smu_context *smu)
    1674             : {
    1675           0 :         int ret = 0;
    1676             : 
    1677           0 :         ret = smu_v11_0_baco_set_state(smu, SMU_BACO_STATE_ENTER);
    1678           0 :         if (ret)
    1679             :                 return ret;
    1680             : 
    1681           0 :         msleep(10);
    1682             : 
    1683           0 :         return ret;
    1684             : }
    1685             : 
    1686           0 : int smu_v11_0_baco_exit(struct smu_context *smu)
    1687             : {
    1688           0 :         return smu_v11_0_baco_set_state(smu, SMU_BACO_STATE_EXIT);
    1689             : }
    1690             : 
    1691           0 : int smu_v11_0_mode1_reset(struct smu_context *smu)
    1692             : {
    1693           0 :         int ret = 0;
    1694             : 
    1695           0 :         ret = smu_cmn_send_smc_msg(smu, SMU_MSG_Mode1Reset, NULL);
    1696           0 :         if (!ret)
    1697           0 :                 msleep(SMU11_MODE1_RESET_WAIT_TIME_IN_MS);
    1698             : 
    1699           0 :         return ret;
    1700             : }
    1701             : 
    1702           0 : int smu_v11_0_handle_passthrough_sbr(struct smu_context *smu, bool enable)
    1703             : {
    1704           0 :         int ret = 0;
    1705             : 
    1706           0 :         ret =  smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_LightSBR, enable ? 1 : 0, NULL);
    1707             : 
    1708           0 :         return ret;
    1709             : }
    1710             : 
    1711             : 
    1712           0 : int smu_v11_0_get_dpm_ultimate_freq(struct smu_context *smu, enum smu_clk_type clk_type,
    1713             :                                                  uint32_t *min, uint32_t *max)
    1714             : {
    1715           0 :         int ret = 0, clk_id = 0;
    1716           0 :         uint32_t param = 0;
    1717             :         uint32_t clock_limit;
    1718             : 
    1719           0 :         if (!smu_cmn_clk_dpm_is_enabled(smu, clk_type)) {
    1720           0 :                 switch (clk_type) {
    1721             :                 case SMU_MCLK:
    1722             :                 case SMU_UCLK:
    1723           0 :                         clock_limit = smu->smu_table.boot_values.uclk;
    1724           0 :                         break;
    1725             :                 case SMU_GFXCLK:
    1726             :                 case SMU_SCLK:
    1727           0 :                         clock_limit = smu->smu_table.boot_values.gfxclk;
    1728           0 :                         break;
    1729             :                 case SMU_SOCCLK:
    1730           0 :                         clock_limit = smu->smu_table.boot_values.socclk;
    1731           0 :                         break;
    1732             :                 default:
    1733             :                         clock_limit = 0;
    1734             :                         break;
    1735             :                 }
    1736             : 
    1737             :                 /* clock in Mhz unit */
    1738           0 :                 if (min)
    1739           0 :                         *min = clock_limit / 100;
    1740           0 :                 if (max)
    1741           0 :                         *max = clock_limit / 100;
    1742             : 
    1743             :                 return 0;
    1744             :         }
    1745             : 
    1746           0 :         clk_id = smu_cmn_to_asic_specific_index(smu,
    1747             :                                                 CMN2ASIC_MAPPING_CLK,
    1748             :                                                 clk_type);
    1749           0 :         if (clk_id < 0) {
    1750             :                 ret = -EINVAL;
    1751             :                 goto failed;
    1752             :         }
    1753           0 :         param = (clk_id & 0xffff) << 16;
    1754             : 
    1755           0 :         if (max) {
    1756           0 :                 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetMaxDpmFreq, param, max);
    1757           0 :                 if (ret)
    1758             :                         goto failed;
    1759             :         }
    1760             : 
    1761           0 :         if (min) {
    1762           0 :                 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_GetMinDpmFreq, param, min);
    1763             :                 if (ret)
    1764             :                         goto failed;
    1765             :         }
    1766             : 
    1767             : failed:
    1768             :         return ret;
    1769             : }
    1770             : 
    1771           0 : int smu_v11_0_set_soft_freq_limited_range(struct smu_context *smu,
    1772             :                                           enum smu_clk_type clk_type,
    1773             :                                           uint32_t min,
    1774             :                                           uint32_t max)
    1775             : {
    1776           0 :         int ret = 0, clk_id = 0;
    1777             :         uint32_t param;
    1778             : 
    1779           0 :         if (!smu_cmn_clk_dpm_is_enabled(smu, clk_type))
    1780             :                 return 0;
    1781             : 
    1782           0 :         clk_id = smu_cmn_to_asic_specific_index(smu,
    1783             :                                                 CMN2ASIC_MAPPING_CLK,
    1784             :                                                 clk_type);
    1785           0 :         if (clk_id < 0)
    1786             :                 return clk_id;
    1787             : 
    1788           0 :         if (max > 0) {
    1789           0 :                 param = (uint32_t)((clk_id << 16) | (max & 0xffff));
    1790           0 :                 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMaxByFreq,
    1791             :                                                   param, NULL);
    1792           0 :                 if (ret)
    1793             :                         goto out;
    1794             :         }
    1795             : 
    1796           0 :         if (min > 0) {
    1797           0 :                 param = (uint32_t)((clk_id << 16) | (min & 0xffff));
    1798           0 :                 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetSoftMinByFreq,
    1799             :                                                   param, NULL);
    1800             :                 if (ret)
    1801             :                         goto out;
    1802             :         }
    1803             : 
    1804             : out:
    1805             :         return ret;
    1806             : }
    1807             : 
    1808           0 : int smu_v11_0_set_hard_freq_limited_range(struct smu_context *smu,
    1809             :                                           enum smu_clk_type clk_type,
    1810             :                                           uint32_t min,
    1811             :                                           uint32_t max)
    1812             : {
    1813           0 :         int ret = 0, clk_id = 0;
    1814             :         uint32_t param;
    1815             : 
    1816           0 :         if (min <= 0 && max <= 0)
    1817             :                 return -EINVAL;
    1818             : 
    1819           0 :         if (!smu_cmn_clk_dpm_is_enabled(smu, clk_type))
    1820             :                 return 0;
    1821             : 
    1822           0 :         clk_id = smu_cmn_to_asic_specific_index(smu,
    1823             :                                                 CMN2ASIC_MAPPING_CLK,
    1824             :                                                 clk_type);
    1825           0 :         if (clk_id < 0)
    1826             :                 return clk_id;
    1827             : 
    1828           0 :         if (max > 0) {
    1829           0 :                 param = (uint32_t)((clk_id << 16) | (max & 0xffff));
    1830           0 :                 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMaxByFreq,
    1831             :                                                   param, NULL);
    1832           0 :                 if (ret)
    1833             :                         return ret;
    1834             :         }
    1835             : 
    1836           0 :         if (min > 0) {
    1837           0 :                 param = (uint32_t)((clk_id << 16) | (min & 0xffff));
    1838           0 :                 ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetHardMinByFreq,
    1839             :                                                   param, NULL);
    1840             :                 if (ret)
    1841             :                         return ret;
    1842             :         }
    1843             : 
    1844             :         return ret;
    1845             : }
    1846             : 
    1847           0 : int smu_v11_0_set_performance_level(struct smu_context *smu,
    1848             :                                     enum amd_dpm_forced_level level)
    1849             : {
    1850           0 :         struct smu_11_0_dpm_context *dpm_context =
    1851             :                                 smu->smu_dpm.dpm_context;
    1852           0 :         struct smu_11_0_dpm_table *gfx_table =
    1853             :                                 &dpm_context->dpm_tables.gfx_table;
    1854           0 :         struct smu_11_0_dpm_table *mem_table =
    1855             :                                 &dpm_context->dpm_tables.uclk_table;
    1856           0 :         struct smu_11_0_dpm_table *soc_table =
    1857             :                                 &dpm_context->dpm_tables.soc_table;
    1858           0 :         struct smu_umd_pstate_table *pstate_table =
    1859             :                                 &smu->pstate_table;
    1860           0 :         struct amdgpu_device *adev = smu->adev;
    1861           0 :         uint32_t sclk_min = 0, sclk_max = 0;
    1862           0 :         uint32_t mclk_min = 0, mclk_max = 0;
    1863           0 :         uint32_t socclk_min = 0, socclk_max = 0;
    1864           0 :         int ret = 0;
    1865             : 
    1866           0 :         switch (level) {
    1867             :         case AMD_DPM_FORCED_LEVEL_HIGH:
    1868           0 :                 sclk_min = sclk_max = gfx_table->max;
    1869           0 :                 mclk_min = mclk_max = mem_table->max;
    1870           0 :                 socclk_min = socclk_max = soc_table->max;
    1871           0 :                 break;
    1872             :         case AMD_DPM_FORCED_LEVEL_LOW:
    1873           0 :                 sclk_min = sclk_max = gfx_table->min;
    1874           0 :                 mclk_min = mclk_max = mem_table->min;
    1875           0 :                 socclk_min = socclk_max = soc_table->min;
    1876           0 :                 break;
    1877             :         case AMD_DPM_FORCED_LEVEL_AUTO:
    1878           0 :                 sclk_min = gfx_table->min;
    1879           0 :                 sclk_max = gfx_table->max;
    1880           0 :                 mclk_min = mem_table->min;
    1881           0 :                 mclk_max = mem_table->max;
    1882           0 :                 socclk_min = soc_table->min;
    1883           0 :                 socclk_max = soc_table->max;
    1884           0 :                 break;
    1885             :         case AMD_DPM_FORCED_LEVEL_PROFILE_STANDARD:
    1886           0 :                 sclk_min = sclk_max = pstate_table->gfxclk_pstate.standard;
    1887           0 :                 mclk_min = mclk_max = pstate_table->uclk_pstate.standard;
    1888           0 :                 socclk_min = socclk_max = pstate_table->socclk_pstate.standard;
    1889           0 :                 break;
    1890             :         case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_SCLK:
    1891           0 :                 sclk_min = sclk_max = pstate_table->gfxclk_pstate.min;
    1892           0 :                 break;
    1893             :         case AMD_DPM_FORCED_LEVEL_PROFILE_MIN_MCLK:
    1894           0 :                 mclk_min = mclk_max = pstate_table->uclk_pstate.min;
    1895           0 :                 break;
    1896             :         case AMD_DPM_FORCED_LEVEL_PROFILE_PEAK:
    1897           0 :                 sclk_min = sclk_max = pstate_table->gfxclk_pstate.peak;
    1898           0 :                 mclk_min = mclk_max = pstate_table->uclk_pstate.peak;
    1899           0 :                 socclk_min = socclk_max = pstate_table->socclk_pstate.peak;
    1900           0 :                 break;
    1901             :         case AMD_DPM_FORCED_LEVEL_MANUAL:
    1902             :         case AMD_DPM_FORCED_LEVEL_PROFILE_EXIT:
    1903             :                 return 0;
    1904             :         default:
    1905           0 :                 dev_err(adev->dev, "Invalid performance level %d\n", level);
    1906           0 :                 return -EINVAL;
    1907             :         }
    1908             : 
    1909             :         /*
    1910             :          * Separate MCLK and SOCCLK soft min/max settings are not allowed
    1911             :          * on Arcturus.
    1912             :          */
    1913           0 :         if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(11, 0, 2)) {
    1914           0 :                 mclk_min = mclk_max = 0;
    1915           0 :                 socclk_min = socclk_max = 0;
    1916             :         }
    1917             : 
    1918           0 :         if (sclk_min && sclk_max) {
    1919           0 :                 ret = smu_v11_0_set_soft_freq_limited_range(smu,
    1920             :                                                             SMU_GFXCLK,
    1921             :                                                             sclk_min,
    1922             :                                                             sclk_max);
    1923           0 :                 if (ret)
    1924             :                         return ret;
    1925             :         }
    1926             : 
    1927           0 :         if (mclk_min && mclk_max) {
    1928           0 :                 ret = smu_v11_0_set_soft_freq_limited_range(smu,
    1929             :                                                             SMU_MCLK,
    1930             :                                                             mclk_min,
    1931             :                                                             mclk_max);
    1932           0 :                 if (ret)
    1933             :                         return ret;
    1934             :         }
    1935             : 
    1936           0 :         if (socclk_min && socclk_max) {
    1937           0 :                 ret = smu_v11_0_set_soft_freq_limited_range(smu,
    1938             :                                                             SMU_SOCCLK,
    1939             :                                                             socclk_min,
    1940             :                                                             socclk_max);
    1941           0 :                 if (ret)
    1942             :                         return ret;
    1943             :         }
    1944             : 
    1945             :         return ret;
    1946             : }
    1947             : 
    1948           0 : int smu_v11_0_set_power_source(struct smu_context *smu,
    1949             :                                enum smu_power_src_type power_src)
    1950             : {
    1951             :         int pwr_source;
    1952             : 
    1953           0 :         pwr_source = smu_cmn_to_asic_specific_index(smu,
    1954             :                                                     CMN2ASIC_MAPPING_PWR,
    1955             :                                                     (uint32_t)power_src);
    1956           0 :         if (pwr_source < 0)
    1957             :                 return -EINVAL;
    1958             : 
    1959           0 :         return smu_cmn_send_smc_msg_with_param(smu,
    1960             :                                         SMU_MSG_NotifyPowerSource,
    1961             :                                         pwr_source,
    1962             :                                         NULL);
    1963             : }
    1964             : 
    1965           0 : int smu_v11_0_get_dpm_freq_by_index(struct smu_context *smu,
    1966             :                                     enum smu_clk_type clk_type,
    1967             :                                     uint16_t level,
    1968             :                                     uint32_t *value)
    1969             : {
    1970           0 :         int ret = 0, clk_id = 0;
    1971             :         uint32_t param;
    1972             : 
    1973           0 :         if (!value)
    1974             :                 return -EINVAL;
    1975             : 
    1976           0 :         if (!smu_cmn_clk_dpm_is_enabled(smu, clk_type))
    1977             :                 return 0;
    1978             : 
    1979           0 :         clk_id = smu_cmn_to_asic_specific_index(smu,
    1980             :                                                 CMN2ASIC_MAPPING_CLK,
    1981             :                                                 clk_type);
    1982           0 :         if (clk_id < 0)
    1983             :                 return clk_id;
    1984             : 
    1985           0 :         param = (uint32_t)(((clk_id & 0xffff) << 16) | (level & 0xffff));
    1986             : 
    1987           0 :         ret = smu_cmn_send_smc_msg_with_param(smu,
    1988             :                                           SMU_MSG_GetDpmFreqByIndex,
    1989             :                                           param,
    1990             :                                           value);
    1991           0 :         if (ret)
    1992             :                 return ret;
    1993             : 
    1994             :         /*
    1995             :          * BIT31:  0 - Fine grained DPM, 1 - Dicrete DPM
    1996             :          * now, we un-support it
    1997             :          */
    1998           0 :         *value = *value & 0x7fffffff;
    1999             : 
    2000           0 :         return ret;
    2001             : }
    2002             : 
    2003           0 : int smu_v11_0_get_dpm_level_count(struct smu_context *smu,
    2004             :                                   enum smu_clk_type clk_type,
    2005             :                                   uint32_t *value)
    2006             : {
    2007           0 :         return smu_v11_0_get_dpm_freq_by_index(smu,
    2008             :                                                clk_type,
    2009             :                                                0xff,
    2010             :                                                value);
    2011             : }
    2012             : 
    2013           0 : int smu_v11_0_set_single_dpm_table(struct smu_context *smu,
    2014             :                                    enum smu_clk_type clk_type,
    2015             :                                    struct smu_11_0_dpm_table *single_dpm_table)
    2016             : {
    2017           0 :         int ret = 0;
    2018             :         uint32_t clk;
    2019             :         int i;
    2020             : 
    2021           0 :         ret = smu_v11_0_get_dpm_level_count(smu,
    2022             :                                             clk_type,
    2023             :                                             &single_dpm_table->count);
    2024           0 :         if (ret) {
    2025           0 :                 dev_err(smu->adev->dev, "[%s] failed to get dpm levels!\n", __func__);
    2026           0 :                 return ret;
    2027             :         }
    2028             : 
    2029           0 :         for (i = 0; i < single_dpm_table->count; i++) {
    2030           0 :                 ret = smu_v11_0_get_dpm_freq_by_index(smu,
    2031             :                                                       clk_type,
    2032             :                                                       i,
    2033             :                                                       &clk);
    2034           0 :                 if (ret) {
    2035           0 :                         dev_err(smu->adev->dev, "[%s] failed to get dpm freq by index!\n", __func__);
    2036           0 :                         return ret;
    2037             :                 }
    2038             : 
    2039           0 :                 single_dpm_table->dpm_levels[i].value = clk;
    2040           0 :                 single_dpm_table->dpm_levels[i].enabled = true;
    2041             : 
    2042           0 :                 if (i == 0)
    2043           0 :                         single_dpm_table->min = clk;
    2044           0 :                 else if (i == single_dpm_table->count - 1)
    2045           0 :                         single_dpm_table->max = clk;
    2046             :         }
    2047             : 
    2048             :         return 0;
    2049             : }
    2050             : 
    2051           0 : int smu_v11_0_get_dpm_level_range(struct smu_context *smu,
    2052             :                                   enum smu_clk_type clk_type,
    2053             :                                   uint32_t *min_value,
    2054             :                                   uint32_t *max_value)
    2055             : {
    2056           0 :         uint32_t level_count = 0;
    2057           0 :         int ret = 0;
    2058             : 
    2059           0 :         if (!min_value && !max_value)
    2060             :                 return -EINVAL;
    2061             : 
    2062           0 :         if (min_value) {
    2063             :                 /* by default, level 0 clock value as min value */
    2064           0 :                 ret = smu_v11_0_get_dpm_freq_by_index(smu,
    2065             :                                                       clk_type,
    2066             :                                                       0,
    2067             :                                                       min_value);
    2068           0 :                 if (ret)
    2069             :                         return ret;
    2070             :         }
    2071             : 
    2072           0 :         if (max_value) {
    2073           0 :                 ret = smu_v11_0_get_dpm_level_count(smu,
    2074             :                                                     clk_type,
    2075             :                                                     &level_count);
    2076           0 :                 if (ret)
    2077             :                         return ret;
    2078             : 
    2079           0 :                 ret = smu_v11_0_get_dpm_freq_by_index(smu,
    2080             :                                                       clk_type,
    2081           0 :                                                       level_count - 1,
    2082             :                                                       max_value);
    2083           0 :                 if (ret)
    2084             :                         return ret;
    2085             :         }
    2086             : 
    2087             :         return ret;
    2088             : }
    2089             : 
    2090           0 : int smu_v11_0_get_current_pcie_link_width_level(struct smu_context *smu)
    2091             : {
    2092           0 :         struct amdgpu_device *adev = smu->adev;
    2093             : 
    2094           0 :         return (RREG32_PCIE(smnPCIE_LC_LINK_WIDTH_CNTL) &
    2095             :                 PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD_MASK)
    2096           0 :                 >> PCIE_LC_LINK_WIDTH_CNTL__LC_LINK_WIDTH_RD__SHIFT;
    2097             : }
    2098             : 
    2099           0 : uint16_t smu_v11_0_get_current_pcie_link_width(struct smu_context *smu)
    2100             : {
    2101             :         uint32_t width_level;
    2102             : 
    2103           0 :         width_level = smu_v11_0_get_current_pcie_link_width_level(smu);
    2104           0 :         if (width_level > LINK_WIDTH_MAX)
    2105           0 :                 width_level = 0;
    2106             : 
    2107           0 :         return link_width[width_level];
    2108             : }
    2109             : 
    2110           0 : int smu_v11_0_get_current_pcie_link_speed_level(struct smu_context *smu)
    2111             : {
    2112           0 :         struct amdgpu_device *adev = smu->adev;
    2113             : 
    2114           0 :         return (RREG32_PCIE(smnPCIE_LC_SPEED_CNTL) &
    2115             :                 PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK)
    2116           0 :                 >> PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT;
    2117             : }
    2118             : 
    2119           0 : uint16_t smu_v11_0_get_current_pcie_link_speed(struct smu_context *smu)
    2120             : {
    2121             :         uint32_t speed_level;
    2122             : 
    2123           0 :         speed_level = smu_v11_0_get_current_pcie_link_speed_level(smu);
    2124           0 :         if (speed_level > LINK_SPEED_MAX)
    2125           0 :                 speed_level = 0;
    2126             : 
    2127           0 :         return link_speed[speed_level];
    2128             : }
    2129             : 
    2130           0 : int smu_v11_0_gfx_ulv_control(struct smu_context *smu,
    2131             :                               bool enablement)
    2132             : {
    2133           0 :         int ret = 0;
    2134             : 
    2135           0 :         if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_GFX_ULV_BIT))
    2136           0 :                 ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_GFX_ULV_BIT, enablement);
    2137             : 
    2138           0 :         return ret;
    2139             : }
    2140             : 
    2141           0 : int smu_v11_0_deep_sleep_control(struct smu_context *smu,
    2142             :                                  bool enablement)
    2143             : {
    2144           0 :         struct amdgpu_device *adev = smu->adev;
    2145           0 :         int ret = 0;
    2146             : 
    2147           0 :         if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_GFXCLK_BIT)) {
    2148           0 :                 ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DS_GFXCLK_BIT, enablement);
    2149           0 :                 if (ret) {
    2150           0 :                         dev_err(adev->dev, "Failed to %s GFXCLK DS!\n", enablement ? "enable" : "disable");
    2151           0 :                         return ret;
    2152             :                 }
    2153             :         }
    2154             : 
    2155           0 :         if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_UCLK_BIT)) {
    2156           0 :                 ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DS_UCLK_BIT, enablement);
    2157           0 :                 if (ret) {
    2158           0 :                         dev_err(adev->dev, "Failed to %s UCLK DS!\n", enablement ? "enable" : "disable");
    2159           0 :                         return ret;
    2160             :                 }
    2161             :         }
    2162             : 
    2163           0 :         if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_FCLK_BIT)) {
    2164           0 :                 ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DS_FCLK_BIT, enablement);
    2165           0 :                 if (ret) {
    2166           0 :                         dev_err(adev->dev, "Failed to %s FCLK DS!\n", enablement ? "enable" : "disable");
    2167           0 :                         return ret;
    2168             :                 }
    2169             :         }
    2170             : 
    2171           0 :         if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_SOCCLK_BIT)) {
    2172           0 :                 ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DS_SOCCLK_BIT, enablement);
    2173           0 :                 if (ret) {
    2174           0 :                         dev_err(adev->dev, "Failed to %s SOCCLK DS!\n", enablement ? "enable" : "disable");
    2175           0 :                         return ret;
    2176             :                 }
    2177             :         }
    2178             : 
    2179           0 :         if (smu_cmn_feature_is_supported(smu, SMU_FEATURE_DS_LCLK_BIT)) {
    2180           0 :                 ret = smu_cmn_feature_set_enabled(smu, SMU_FEATURE_DS_LCLK_BIT, enablement);
    2181           0 :                 if (ret) {
    2182           0 :                         dev_err(adev->dev, "Failed to %s LCLK DS!\n", enablement ? "enable" : "disable");
    2183           0 :                         return ret;
    2184             :                 }
    2185             :         }
    2186             : 
    2187             :         return ret;
    2188             : }
    2189             : 
    2190           0 : int smu_v11_0_restore_user_od_settings(struct smu_context *smu)
    2191             : {
    2192           0 :         struct smu_table_context *table_context = &smu->smu_table;
    2193           0 :         void *user_od_table = table_context->user_overdrive_table;
    2194           0 :         int ret = 0;
    2195             : 
    2196           0 :         ret = smu_cmn_update_table(smu, SMU_TABLE_OVERDRIVE, 0, (void *)user_od_table, true);
    2197           0 :         if (ret)
    2198           0 :                 dev_err(smu->adev->dev, "Failed to import overdrive table!\n");
    2199             : 
    2200           0 :         return ret;
    2201             : }
    2202             : 
    2203           0 : void smu_v11_0_set_smu_mailbox_registers(struct smu_context *smu)
    2204             : {
    2205           0 :         struct amdgpu_device *adev = smu->adev;
    2206             : 
    2207           0 :         smu->param_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_82);
    2208           0 :         smu->msg_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_66);
    2209           0 :         smu->resp_reg = SOC15_REG_OFFSET(MP1, 0, mmMP1_SMN_C2PMSG_90);
    2210           0 : }

Generated by: LCOV version 1.14