Merge tag 'v5.3-rc3' into drm-next-5.4
[sfrench/cifs-2.6.git] / drivers / gpu / drm / amd / amdgpu / soc15.c
index 23265414d44867b81c36d85f1ef87e67013ca95f..5116d0bf9e4a653f7ab20f8eec9b3c2c2f386945 100644 (file)
@@ -63,6 +63,7 @@
 #include "uvd_v7_0.h"
 #include "vce_v4_0.h"
 #include "vcn_v1_0.h"
+#include "vcn_v2_5.h"
 #include "dce_virtual.h"
 #include "mxgpu_ai.h"
 #include "amdgpu_smu.h"
@@ -115,6 +116,49 @@ static void soc15_pcie_wreg(struct amdgpu_device *adev, u32 reg, u32 v)
        spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
 }
 
+static u64 soc15_pcie_rreg64(struct amdgpu_device *adev, u32 reg)
+{
+       unsigned long flags, address, data;
+       u64 r;
+       address = adev->nbio_funcs->get_pcie_index_offset(adev);
+       data = adev->nbio_funcs->get_pcie_data_offset(adev);
+
+       spin_lock_irqsave(&adev->pcie_idx_lock, flags);
+       /* read low 32 bit */
+       WREG32(address, reg);
+       (void)RREG32(address);
+       r = RREG32(data);
+
+       /* read high 32 bit*/
+       WREG32(address, reg + 4);
+       (void)RREG32(address);
+       r |= ((u64)RREG32(data) << 32);
+       spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
+       return r;
+}
+
+static void soc15_pcie_wreg64(struct amdgpu_device *adev, u32 reg, u64 v)
+{
+       unsigned long flags, address, data;
+
+       address = adev->nbio_funcs->get_pcie_index_offset(adev);
+       data = adev->nbio_funcs->get_pcie_data_offset(adev);
+
+       spin_lock_irqsave(&adev->pcie_idx_lock, flags);
+       /* write low 32 bit */
+       WREG32(address, reg);
+       (void)RREG32(address);
+       WREG32(data, (u32)(v & 0xffffffffULL));
+       (void)RREG32(data);
+
+       /* write high 32 bit */
+       WREG32(address, reg + 4);
+       (void)RREG32(address);
+       WREG32(data, (u32)(v >> 32));
+       (void)RREG32(data);
+       spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
+}
+
 static u32 soc15_uvd_ctx_rreg(struct amdgpu_device *adev, u32 reg)
 {
        unsigned long flags, address, data;
@@ -464,12 +508,14 @@ static int soc15_asic_baco_reset(struct amdgpu_device *adev)
        return 0;
 }
 
-static int soc15_asic_reset(struct amdgpu_device *adev)
+static enum amd_reset_method
+soc15_asic_reset_method(struct amdgpu_device *adev)
 {
-       int ret;
        bool baco_reset;
 
        switch (adev->asic_type) {
+       case CHIP_RAVEN:
+               return AMD_RESET_METHOD_MODE2;
        case CHIP_VEGA10:
        case CHIP_VEGA12:
                soc15_asic_get_baco_capability(adev, &baco_reset);
@@ -493,6 +539,16 @@ static int soc15_asic_reset(struct amdgpu_device *adev)
        }
 
        if (baco_reset)
+               return AMD_RESET_METHOD_BACO;
+       else
+               return AMD_RESET_METHOD_MODE1;
+}
+
+static int soc15_asic_reset(struct amdgpu_device *adev)
+{
+       int ret;
+
+       if (soc15_asic_reset_method(adev) == AMD_RESET_METHOD_BACO)
                ret = soc15_asic_baco_reset(adev);
        else
                ret = soc15_asic_mode1_reset(adev);
@@ -586,21 +642,25 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
        case CHIP_VEGA20:
                vega20_reg_base_init(adev);
                break;
+       case CHIP_ARCTURUS:
+               arct_reg_base_init(adev);
+               break;
        default:
                return -EINVAL;
        }
 
-       if (adev->asic_type == CHIP_VEGA20)
+       if (adev->asic_type == CHIP_VEGA20 || adev->asic_type == CHIP_ARCTURUS)
                adev->gmc.xgmi.supported = true;
 
        if (adev->flags & AMD_IS_APU)
                adev->nbio_funcs = &nbio_v7_0_funcs;
-       else if (adev->asic_type == CHIP_VEGA20)
+       else if (adev->asic_type == CHIP_VEGA20 ||
+               adev->asic_type == CHIP_ARCTURUS)
                adev->nbio_funcs = &nbio_v7_4_funcs;
        else
                adev->nbio_funcs = &nbio_v6_1_funcs;
 
-       if (adev->asic_type == CHIP_VEGA20)
+       if (adev->asic_type == CHIP_VEGA20 || adev->asic_type == CHIP_ARCTURUS)
                adev->df_funcs = &df_v3_6_funcs;
        else
                adev->df_funcs = &df_v1_7_funcs;
@@ -672,6 +732,17 @@ int soc15_set_ip_blocks(struct amdgpu_device *adev)
 #endif
                amdgpu_device_ip_block_add(adev, &vcn_v1_0_ip_block);
                break;
+       case CHIP_ARCTURUS:
+               amdgpu_device_ip_block_add(adev, &vega10_common_ip_block);
+               amdgpu_device_ip_block_add(adev, &gmc_v9_0_ip_block);
+               amdgpu_device_ip_block_add(adev, &vega10_ih_ip_block);
+               if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
+                       amdgpu_device_ip_block_add(adev, &dce_virtual_ip_block);
+               amdgpu_device_ip_block_add(adev, &gfx_v9_0_ip_block);
+               amdgpu_device_ip_block_add(adev, &sdma_v4_0_ip_block);
+               amdgpu_device_ip_block_add(adev, &smu_v11_0_ip_block);
+               amdgpu_device_ip_block_add(adev, &vcn_v2_5_ip_block);
+               break;
        default:
                return -EINVAL;
        }
@@ -688,7 +759,7 @@ static void soc15_invalidate_hdp(struct amdgpu_device *adev,
                                 struct amdgpu_ring *ring)
 {
        if (!ring || !ring->funcs->emit_wreg)
-               WREG32_SOC15_NO_KIQ(NBIO, 0, mmHDP_READ_CACHE_INVALIDATE, 1);
+               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);
@@ -714,14 +785,9 @@ static void soc15_get_pcie_usage(struct amdgpu_device *adev, uint64_t *count0,
 
        /* Set the 2 events that we wish to watch, defined above */
        /* Reg 40 is # received msgs */
+       /* Reg 104 is # of posted requests sent */
        perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT0_SEL, 40);
-       /* Pre-VG20, Reg 104 is # of posted requests sent. On VG20 it's 108 */
-       if (adev->asic_type == CHIP_VEGA20)
-               perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK,
-                                       EVENT1_SEL, 108);
-       else
-               perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK,
-                                       EVENT1_SEL, 104);
+       perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK, EVENT1_SEL, 104);
 
        /* Write to enable desired perf counters */
        WREG32_PCIE(smnPCIE_PERF_CNTL_TXCLK, perfctr);
@@ -751,6 +817,55 @@ static void soc15_get_pcie_usage(struct amdgpu_device *adev, uint64_t *count0,
        *count1 = RREG32_PCIE(smnPCIE_PERF_COUNT1_TXCLK) | (cnt1_of << 32);
 }
 
+static void vega20_get_pcie_usage(struct amdgpu_device *adev, uint64_t *count0,
+                                uint64_t *count1)
+{
+       uint32_t perfctr = 0;
+       uint64_t cnt0_of, cnt1_of;
+       int tmp;
+
+       /* This reports 0 on APUs, so return to avoid writing/reading registers
+        * that may or may not be different from their GPU counterparts
+        */
+       if (adev->flags & AMD_IS_APU)
+               return;
+
+       /* Set the 2 events that we wish to watch, defined above */
+       /* Reg 40 is # received msgs */
+       /* Reg 108 is # of posted requests sent on VG20 */
+       perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK3,
+                               EVENT0_SEL, 40);
+       perfctr = REG_SET_FIELD(perfctr, PCIE_PERF_CNTL_TXCLK3,
+                               EVENT1_SEL, 108);
+
+       /* Write to enable desired perf counters */
+       WREG32_PCIE(smnPCIE_PERF_CNTL_TXCLK3, perfctr);
+       /* Zero out and enable the perf counters
+        * Write 0x5:
+        * Bit 0 = Start all counters(1)
+        * Bit 2 = Global counter reset enable(1)
+        */
+       WREG32_PCIE(smnPCIE_PERF_COUNT_CNTL, 0x00000005);
+
+       msleep(1000);
+
+       /* Load the shadow and disable the perf counters
+        * Write 0x2:
+        * Bit 0 = Stop counters(0)
+        * Bit 1 = Load the shadow counters(1)
+        */
+       WREG32_PCIE(smnPCIE_PERF_COUNT_CNTL, 0x00000002);
+
+       /* Read register values to get any >32bit overflow */
+       tmp = RREG32_PCIE(smnPCIE_PERF_CNTL_TXCLK3);
+       cnt0_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK3, COUNTER0_UPPER);
+       cnt1_of = REG_GET_FIELD(tmp, PCIE_PERF_CNTL_TXCLK3, COUNTER1_UPPER);
+
+       /* Get the values and add the overflow */
+       *count0 = RREG32_PCIE(smnPCIE_PERF_COUNT0_TXCLK3) | (cnt0_of << 32);
+       *count1 = RREG32_PCIE(smnPCIE_PERF_COUNT1_TXCLK3) | (cnt1_of << 32);
+}
+
 static bool soc15_need_reset_on_init(struct amdgpu_device *adev)
 {
        u32 sol_reg;
@@ -792,6 +907,7 @@ static const struct amdgpu_asic_funcs soc15_asic_funcs =
        .read_bios_from_rom = &soc15_read_bios_from_rom,
        .read_register = &soc15_read_register,
        .reset = &soc15_asic_reset,
+       .reset_method = &soc15_asic_reset_method,
        .set_vga_state = &soc15_vga_set_state,
        .get_xclk = &soc15_get_xclk,
        .set_uvd_clocks = &soc15_set_uvd_clocks,
@@ -821,9 +937,10 @@ static const struct amdgpu_asic_funcs vega20_asic_funcs =
        .invalidate_hdp = &soc15_invalidate_hdp,
        .need_full_reset = &soc15_need_full_reset,
        .init_doorbell_index = &vega20_doorbell_index_init,
-       .get_pcie_usage = &soc15_get_pcie_usage,
+       .get_pcie_usage = &vega20_get_pcie_usage,
        .need_reset_on_init = &soc15_need_reset_on_init,
        .get_pcie_replay_count = &soc15_get_pcie_replay_count,
+       .reset_method = &soc15_asic_reset_method
 };
 
 static int soc15_common_early_init(void *handle)
@@ -837,6 +954,8 @@ static int soc15_common_early_init(void *handle)
        adev->smc_wreg = NULL;
        adev->pcie_rreg = &soc15_pcie_rreg;
        adev->pcie_wreg = &soc15_pcie_wreg;
+       adev->pcie_rreg64 = &soc15_pcie_rreg64;
+       adev->pcie_wreg64 = &soc15_pcie_wreg64;
        adev->uvd_ctx_rreg = &soc15_uvd_ctx_rreg;
        adev->uvd_ctx_wreg = &soc15_uvd_ctx_wreg;
        adev->didt_rreg = &soc15_didt_rreg;
@@ -998,6 +1117,12 @@ static int soc15_common_early_init(void *handle)
                                AMD_PG_SUPPORT_CP |
                                AMD_PG_SUPPORT_RLC_SMU_HS;
                break;
+       case CHIP_ARCTURUS:
+               adev->asic_funcs = &vega20_asic_funcs;
+               adev->cg_flags = 0;
+               adev->pg_flags = 0;
+               adev->external_rev_id = adev->rev_id + 0x32;
+               break;
        default:
                /* FIXME: not supported yet */
                return -EINVAL;
@@ -1043,21 +1168,18 @@ static void soc15_doorbell_range_init(struct amdgpu_device *adev)
        int i;
        struct amdgpu_ring *ring;
 
-       /*  Two reasons to skip
-       *               1, Host driver already programmed them
-       *               2, To avoid registers program violations in SR-IOV
-       */
-       if (!amdgpu_virt_support_skip_setting(adev)) {
+       /* sdma/ih doorbell range are programed by hypervisor */
+       if (!amdgpu_sriov_vf(adev)) {
                for (i = 0; i < adev->sdma.num_instances; i++) {
                        ring = &adev->sdma.instance[i].ring;
                        adev->nbio_funcs->sdma_doorbell_range(adev, i,
                                ring->use_doorbell, ring->doorbell_index,
                                adev->doorbell_index.sdma_doorbell_range);
                }
-       }
 
-       adev->nbio_funcs->ih_doorbell_range(adev, adev->irq.ih.use_doorbell,
+               adev->nbio_funcs->ih_doorbell_range(adev, adev->irq.ih.use_doorbell,
                                                adev->irq.ih.doorbell_index);
+       }
 }
 
 static int soc15_common_hw_init(void *handle)