drm/amdgpu: support rom clockgating related function for NV family
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / amdgpu / nv.c
index 6bee367..efacf5f 100644 (file)
@@ -38,9 +38,6 @@
 
 #include "gc/gc_10_1_0_offset.h"
 #include "gc/gc_10_1_0_sh_mask.h"
-#include "hdp/hdp_5_0_0_offset.h"
-#include "hdp/hdp_5_0_0_sh_mask.h"
-#include "smuio/smuio_11_0_0_offset.h"
 #include "mp/mp_11_0_offset.h"
 
 #include "soc15.h"
@@ -50,6 +47,7 @@
 #include "mmhub_v2_0.h"
 #include "nbio_v2_3.h"
 #include "nbio_v7_2.h"
+#include "hdp_v5_0.h"
 #include "nv.h"
 #include "navi10_ih.h"
 #include "gfx_v10_0.h"
@@ -62,6 +60,8 @@
 #include "dce_virtual.h"
 #include "mes_v10_1.h"
 #include "mxgpu_nv.h"
+#include "smuio_v11_0.h"
+#include "smuio_v11_0_6.h"
 
 static const struct amd_ip_funcs nv_common_ip_funcs;
 
@@ -203,6 +203,7 @@ static bool nv_read_bios_from_rom(struct amdgpu_device *adev,
 {
        u32 *dw_ptr;
        u32 i, length_dw;
+       u32 rom_index_offset, rom_data_offset;
 
        if (bios == NULL)
                return false;
@@ -215,11 +216,16 @@ static bool nv_read_bios_from_rom(struct amdgpu_device *adev,
        dw_ptr = (u32 *)bios;
        length_dw = ALIGN(length_bytes, 4) / 4;
 
+       rom_index_offset =
+               adev->smuio.funcs->get_rom_index_offset(adev);
+       rom_data_offset =
+               adev->smuio.funcs->get_rom_data_offset(adev);
+
        /* set rom index to 0 */
-       WREG32(SOC15_REG_OFFSET(SMUIO, 0, mmROM_INDEX), 0);
+       WREG32(rom_index_offset, 0);
        /* read out the rom data */
        for (i = 0; i < length_dw; i++)
-               dw_ptr[i] = RREG32(SOC15_REG_OFFSET(SMUIO, 0, mmROM_DATA));
+               dw_ptr[i] = RREG32(rom_data_offset);
 
        return true;
 }
@@ -336,6 +342,38 @@ static int nv_asic_mode1_reset(struct amdgpu_device *adev)
        return ret;
 }
 
+static int nv_asic_mode2_reset(struct amdgpu_device *adev)
+{
+       u32 i;
+       int ret = 0;
+
+       amdgpu_atombios_scratch_regs_engine_hung(adev, true);
+
+       /* disable BM */
+       pci_clear_master(adev->pdev);
+
+       amdgpu_device_cache_pci_state(adev->pdev);
+
+       ret = amdgpu_dpm_mode2_reset(adev);
+       if (ret)
+               dev_err(adev->dev, "GPU mode2 reset failed\n");
+
+       amdgpu_device_load_pci_state(adev->pdev);
+
+       /* wait for asic to come out of reset */
+       for (i = 0; i < adev->usec_timeout; i++) {
+               u32 memsize = adev->nbio.funcs->get_memsize(adev);
+
+               if (memsize != 0xffffffff)
+                       break;
+               udelay(1);
+       }
+
+       amdgpu_atombios_scratch_regs_engine_hung(adev, false);
+
+       return ret;
+}
+
 static bool nv_asic_supports_baco(struct amdgpu_device *adev)
 {
        struct smu_context *smu = &adev->smu;
@@ -352,6 +390,7 @@ nv_asic_reset_method(struct amdgpu_device *adev)
        struct smu_context *smu = &adev->smu;
 
        if (amdgpu_reset_method == AMD_RESET_METHOD_MODE1 ||
+           amdgpu_reset_method == AMD_RESET_METHOD_MODE2 ||
            amdgpu_reset_method == AMD_RESET_METHOD_BACO)
                return amdgpu_reset_method;
 
@@ -360,6 +399,8 @@ nv_asic_reset_method(struct amdgpu_device *adev)
                                  amdgpu_reset_method);
 
        switch (adev->asic_type) {
+       case CHIP_VANGOGH:
+               return AMD_RESET_METHOD_MODE2;
        case CHIP_SIENNA_CICHLID:
        case CHIP_NAVY_FLOUNDER:
        case CHIP_DIMGREY_CAVEFISH:
@@ -377,7 +418,12 @@ static int nv_asic_reset(struct amdgpu_device *adev)
        int ret = 0;
        struct smu_context *smu = &adev->smu;
 
-       if (nv_asic_reset_method(adev) == AMD_RESET_METHOD_BACO) {
+       /* skip reset on vangogh for now */
+       if (adev->asic_type == CHIP_VANGOGH)
+               return 0;
+
+       switch (nv_asic_reset_method(adev)) {
+       case AMD_RESET_METHOD_BACO:
                dev_info(adev->dev, "BACO reset\n");
 
                ret = smu_baco_enter(smu);
@@ -386,9 +432,15 @@ static int nv_asic_reset(struct amdgpu_device *adev)
                ret = smu_baco_exit(smu);
                if (ret)
                        return ret;
-       } else {
+               break;
+       case AMD_RESET_METHOD_MODE2:
+               dev_info(adev->dev, "MODE2 reset\n");
+               ret = nv_asic_mode2_reset(adev);
+               break;
+       default:
                dev_info(adev->dev, "MODE1 reset\n");
                ret = nv_asic_mode1_reset(adev);
+               break;
        }
 
        return ret;
@@ -423,11 +475,14 @@ static void nv_pcie_gen3_enable(struct amdgpu_device *adev)
 
 static void nv_program_aspm(struct amdgpu_device *adev)
 {
-
-       if (amdgpu_aspm == 0)
+       if (amdgpu_aspm != 1)
                return;
 
-       /* todo */
+       if ((adev->asic_type >= CHIP_SIENNA_CICHLID) &&
+           !(adev->flags & AMD_IS_APU) &&
+           (adev->nbio.funcs->program_aspm))
+               adev->nbio.funcs->program_aspm(adev);
+
 }
 
 static void nv_enable_doorbell_aperture(struct amdgpu_device *adev,
@@ -514,6 +569,12 @@ int nv_set_ip_blocks(struct amdgpu_device *adev)
                adev->nbio.funcs = &nbio_v2_3_funcs;
                adev->nbio.hdp_flush_reg = &nbio_v2_3_hdp_flush_reg;
        }
+       adev->hdp.funcs = &hdp_v5_0_funcs;
+
+       if (adev->asic_type >= CHIP_SIENNA_CICHLID)
+               adev->smuio.funcs = &smuio_v11_0_6_funcs;
+       else
+               adev->smuio.funcs = &smuio_v11_0_funcs;
 
        if (adev->asic_type == CHIP_SIENNA_CICHLID)
                adev->gmc.xgmi.supported = true;
@@ -669,22 +730,6 @@ static uint32_t nv_get_rev_id(struct amdgpu_device *adev)
        return adev->nbio.funcs->get_rev_id(adev);
 }
 
-static void nv_flush_hdp(struct amdgpu_device *adev, struct amdgpu_ring *ring)
-{
-       adev->nbio.funcs->hdp_flush(adev, ring);
-}
-
-static void nv_invalidate_hdp(struct amdgpu_device *adev,
-                               struct amdgpu_ring *ring)
-{
-       if (!ring || !ring->funcs->emit_wreg) {
-               WREG32_SOC15_NO_KIQ(HDP, 0, mmHDP_READ_CACHE_INVALIDATE, 1);
-       } else {
-               amdgpu_ring_emit_wreg(ring, SOC15_REG_OFFSET(
-                                       HDP, 0, mmHDP_READ_CACHE_INVALIDATE), 1);
-       }
-}
-
 static bool nv_need_full_reset(struct amdgpu_device *adev)
 {
        return true;
@@ -768,10 +813,10 @@ static int nv_update_umd_stable_pstate(struct amdgpu_device *adev,
         * The ASPM function is not fully enabled and verified on
         * Navi yet. Temporarily skip this until ASPM enabled.
         */
-#if 0
-       if (adev->nbio.funcs->enable_aspm)
+       if ((adev->asic_type >= CHIP_SIENNA_CICHLID) &&
+           !(adev->flags & AMD_IS_APU) &&
+           (adev->nbio.funcs->enable_aspm))
                adev->nbio.funcs->enable_aspm(adev, !enter);
-#endif
 
        return 0;
 }
@@ -788,8 +833,6 @@ static const struct amdgpu_asic_funcs nv_asic_funcs =
        .set_uvd_clocks = &nv_set_uvd_clocks,
        .set_vce_clocks = &nv_set_vce_clocks,
        .get_config_memsize = &nv_get_config_memsize,
-       .flush_hdp = &nv_flush_hdp,
-       .invalidate_hdp = &nv_invalidate_hdp,
        .init_doorbell_index = &nv_init_doorbell_index,
        .need_full_reset = &nv_need_full_reset,
        .need_reset_on_init = &nv_need_reset_on_init,
@@ -1080,120 +1123,6 @@ static int nv_common_soft_reset(void *handle)
        return 0;
 }
 
-static void nv_update_hdp_mem_power_gating(struct amdgpu_device *adev,
-                                          bool enable)
-{
-       uint32_t hdp_clk_cntl, hdp_clk_cntl1;
-       uint32_t hdp_mem_pwr_cntl;
-
-       if (!(adev->cg_flags & (AMD_CG_SUPPORT_HDP_LS |
-                               AMD_CG_SUPPORT_HDP_DS |
-                               AMD_CG_SUPPORT_HDP_SD)))
-               return;
-
-       hdp_clk_cntl = hdp_clk_cntl1 = RREG32_SOC15(HDP, 0, mmHDP_CLK_CNTL);
-       hdp_mem_pwr_cntl = RREG32_SOC15(HDP, 0, mmHDP_MEM_POWER_CTRL);
-
-       /* Before doing clock/power mode switch,
-        * forced on IPH & RC clock */
-       hdp_clk_cntl = REG_SET_FIELD(hdp_clk_cntl, HDP_CLK_CNTL,
-                                    IPH_MEM_CLK_SOFT_OVERRIDE, 1);
-       hdp_clk_cntl = REG_SET_FIELD(hdp_clk_cntl, HDP_CLK_CNTL,
-                                    RC_MEM_CLK_SOFT_OVERRIDE, 1);
-       WREG32_SOC15(HDP, 0, mmHDP_CLK_CNTL, hdp_clk_cntl);
-
-       /* HDP 5.0 doesn't support dynamic power mode switch,
-        * disable clock and power gating before any changing */
-       hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
-                                        IPH_MEM_POWER_CTRL_EN, 0);
-       hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
-                                        IPH_MEM_POWER_LS_EN, 0);
-       hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
-                                        IPH_MEM_POWER_DS_EN, 0);
-       hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
-                                        IPH_MEM_POWER_SD_EN, 0);
-       hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
-                                        RC_MEM_POWER_CTRL_EN, 0);
-       hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
-                                        RC_MEM_POWER_LS_EN, 0);
-       hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
-                                        RC_MEM_POWER_DS_EN, 0);
-       hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
-                                        RC_MEM_POWER_SD_EN, 0);
-       WREG32_SOC15(HDP, 0, mmHDP_MEM_POWER_CTRL, hdp_mem_pwr_cntl);
-
-       /* only one clock gating mode (LS/DS/SD) can be enabled */
-       if (adev->cg_flags & AMD_CG_SUPPORT_HDP_LS) {
-               hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
-                                                HDP_MEM_POWER_CTRL,
-                                                IPH_MEM_POWER_LS_EN, enable);
-               hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
-                                                HDP_MEM_POWER_CTRL,
-                                                RC_MEM_POWER_LS_EN, enable);
-       } else if (adev->cg_flags & AMD_CG_SUPPORT_HDP_DS) {
-               hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
-                                                HDP_MEM_POWER_CTRL,
-                                                IPH_MEM_POWER_DS_EN, enable);
-               hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
-                                                HDP_MEM_POWER_CTRL,
-                                                RC_MEM_POWER_DS_EN, enable);
-       } else if (adev->cg_flags & AMD_CG_SUPPORT_HDP_SD) {
-               hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
-                                                HDP_MEM_POWER_CTRL,
-                                                IPH_MEM_POWER_SD_EN, enable);
-               /* RC should not use shut down mode, fallback to ds */
-               hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl,
-                                                HDP_MEM_POWER_CTRL,
-                                                RC_MEM_POWER_DS_EN, enable);
-       }
-
-       /* confirmed that IPH_MEM_POWER_CTRL_EN and RC_MEM_POWER_CTRL_EN have to
-        * be set for SRAM LS/DS/SD */
-       if (adev->cg_flags & (AMD_CG_SUPPORT_HDP_LS | AMD_CG_SUPPORT_HDP_DS |
-                                                       AMD_CG_SUPPORT_HDP_SD)) {
-               hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
-                                               IPH_MEM_POWER_CTRL_EN, 1);
-               hdp_mem_pwr_cntl = REG_SET_FIELD(hdp_mem_pwr_cntl, HDP_MEM_POWER_CTRL,
-                                               RC_MEM_POWER_CTRL_EN, 1);
-       }
-
-       WREG32_SOC15(HDP, 0, mmHDP_MEM_POWER_CTRL, hdp_mem_pwr_cntl);
-
-       /* restore IPH & RC clock override after clock/power mode changing */
-       WREG32_SOC15(HDP, 0, mmHDP_CLK_CNTL, hdp_clk_cntl1);
-}
-
-static void nv_update_hdp_clock_gating(struct amdgpu_device *adev,
-                                      bool enable)
-{
-       uint32_t hdp_clk_cntl;
-
-       if (!(adev->cg_flags & AMD_CG_SUPPORT_HDP_MGCG))
-               return;
-
-       hdp_clk_cntl = RREG32_SOC15(HDP, 0, mmHDP_CLK_CNTL);
-
-       if (enable) {
-               hdp_clk_cntl &=
-                       ~(uint32_t)
-                         (HDP_CLK_CNTL__IPH_MEM_CLK_SOFT_OVERRIDE_MASK |
-                          HDP_CLK_CNTL__RC_MEM_CLK_SOFT_OVERRIDE_MASK |
-                          HDP_CLK_CNTL__DBUS_CLK_SOFT_OVERRIDE_MASK |
-                          HDP_CLK_CNTL__DYN_CLK_SOFT_OVERRIDE_MASK |
-                          HDP_CLK_CNTL__XDP_REG_CLK_SOFT_OVERRIDE_MASK |
-                          HDP_CLK_CNTL__HDP_REG_CLK_SOFT_OVERRIDE_MASK);
-       } else {
-               hdp_clk_cntl |= HDP_CLK_CNTL__IPH_MEM_CLK_SOFT_OVERRIDE_MASK |
-                       HDP_CLK_CNTL__RC_MEM_CLK_SOFT_OVERRIDE_MASK |
-                       HDP_CLK_CNTL__DBUS_CLK_SOFT_OVERRIDE_MASK |
-                       HDP_CLK_CNTL__DYN_CLK_SOFT_OVERRIDE_MASK |
-                       HDP_CLK_CNTL__XDP_REG_CLK_SOFT_OVERRIDE_MASK |
-                       HDP_CLK_CNTL__HDP_REG_CLK_SOFT_OVERRIDE_MASK;
-       }
-
-       WREG32_SOC15(HDP, 0, mmHDP_CLK_CNTL, hdp_clk_cntl);
-}
-
 static int nv_common_set_clockgating_state(void *handle,
                                           enum amd_clockgating_state state)
 {
@@ -1213,9 +1142,9 @@ static int nv_common_set_clockgating_state(void *handle,
                                state == AMD_CG_STATE_GATE);
                adev->nbio.funcs->update_medium_grain_light_sleep(adev,
                                state == AMD_CG_STATE_GATE);
-               nv_update_hdp_mem_power_gating(adev,
-                                  state == AMD_CG_STATE_GATE);
-               nv_update_hdp_clock_gating(adev,
+               adev->hdp.funcs->update_clock_gating(adev,
+                               state == AMD_CG_STATE_GATE);
+               adev->smuio.funcs->update_rom_clock_gating(adev,
                                state == AMD_CG_STATE_GATE);
                break;
        default:
@@ -1234,31 +1163,15 @@ static int nv_common_set_powergating_state(void *handle,
 static void nv_common_get_clockgating_state(void *handle, u32 *flags)
 {
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
-       uint32_t tmp;
 
        if (amdgpu_sriov_vf(adev))
                *flags = 0;
 
        adev->nbio.funcs->get_clockgating_state(adev, flags);
 
-       /* AMD_CG_SUPPORT_HDP_MGCG */
-       tmp = RREG32_SOC15(HDP, 0, mmHDP_CLK_CNTL);
-       if (!(tmp & (HDP_CLK_CNTL__IPH_MEM_CLK_SOFT_OVERRIDE_MASK |
-                    HDP_CLK_CNTL__RC_MEM_CLK_SOFT_OVERRIDE_MASK |
-                    HDP_CLK_CNTL__DBUS_CLK_SOFT_OVERRIDE_MASK |
-                    HDP_CLK_CNTL__DYN_CLK_SOFT_OVERRIDE_MASK |
-                    HDP_CLK_CNTL__XDP_REG_CLK_SOFT_OVERRIDE_MASK |
-                    HDP_CLK_CNTL__HDP_REG_CLK_SOFT_OVERRIDE_MASK)))
-               *flags |= AMD_CG_SUPPORT_HDP_MGCG;
-
-       /* AMD_CG_SUPPORT_HDP_LS/DS/SD */
-       tmp = RREG32_SOC15(HDP, 0, mmHDP_MEM_POWER_CTRL);
-       if (tmp & HDP_MEM_POWER_CTRL__IPH_MEM_POWER_LS_EN_MASK)
-               *flags |= AMD_CG_SUPPORT_HDP_LS;
-       else if (tmp & HDP_MEM_POWER_CTRL__IPH_MEM_POWER_DS_EN_MASK)
-               *flags |= AMD_CG_SUPPORT_HDP_DS;
-       else if (tmp & HDP_MEM_POWER_CTRL__IPH_MEM_POWER_SD_EN_MASK)
-               *flags |= AMD_CG_SUPPORT_HDP_SD;
+       adev->hdp.funcs->get_clock_gating_state(adev, flags);
+
+       adev->smuio.funcs->get_clock_gating_state(adev, flags);
 
        return;
 }