drm/amdgpu: add indirect r/w interface for smn address greater than 32bits
authorLe Ma <le.ma@amd.com>
Sat, 2 Apr 2022 11:39:59 +0000 (19:39 +0800)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 9 Jun 2023 13:45:29 +0000 (09:45 -0400)
On multiple AIDs platform, bit[34:32] in SMD address is leveraged to access
nonAID0 register smn address and new PCI_INDEX_HI register is introduced
to access the higher bits.

v2: rebase on latest register accessors (Alex)

Signed-off-by: Le Ma <le.ma@amd.com>
Acked-by: Felix Kuehling <Felix.Kuehling@amd.com>
Reviewed-by: Lijo Lazar <lijo.lazar@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu.h
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
drivers/gpu/drm/amd/amdgpu/amdgpu_nbio.h
drivers/gpu/drm/amd/amdgpu/nbio_v7_9.c
drivers/gpu/drm/amd/amdgpu/soc15.c

index 5f4396185a2e656ac70a290a46557bedd517e0ea..729d5eedae49f83f6a9d9e05da22f0845555d385 100644 (file)
@@ -608,6 +608,9 @@ void amdgpu_cgs_destroy_device(struct cgs_device *cgs_device);
 typedef uint32_t (*amdgpu_rreg_t)(struct amdgpu_device*, uint32_t);
 typedef void (*amdgpu_wreg_t)(struct amdgpu_device*, uint32_t, uint32_t);
 
+typedef uint32_t (*amdgpu_rreg_ext_t)(struct amdgpu_device*, uint64_t);
+typedef void (*amdgpu_wreg_ext_t)(struct amdgpu_device*, uint64_t, uint32_t);
+
 typedef uint64_t (*amdgpu_rreg64_t)(struct amdgpu_device*, uint32_t);
 typedef void (*amdgpu_wreg64_t)(struct amdgpu_device*, uint32_t, uint64_t);
 
@@ -798,6 +801,8 @@ struct amdgpu_device {
        amdgpu_wreg_t                   pcie_wreg;
        amdgpu_rreg_t                   pciep_rreg;
        amdgpu_wreg_t                   pciep_wreg;
+       amdgpu_rreg_ext_t               pcie_rreg_ext;
+       amdgpu_wreg_ext_t               pcie_wreg_ext;
        amdgpu_rreg64_t                 pcie_rreg64;
        amdgpu_wreg64_t                 pcie_wreg64;
        /* protects concurrent UVD register access */
@@ -1088,9 +1093,13 @@ uint32_t amdgpu_device_wait_on_rreg(struct amdgpu_device *adev,
                            uint32_t expected_value, uint32_t mask);
 uint32_t amdgpu_device_rreg(struct amdgpu_device *adev,
                            uint32_t reg, uint32_t acc_flags);
+u32 amdgpu_device_indirect_rreg_ext(struct amdgpu_device *adev,
+                                   u64 reg_addr);
 void amdgpu_device_wreg(struct amdgpu_device *adev,
                        uint32_t reg, uint32_t v,
                        uint32_t acc_flags);
+void amdgpu_device_indirect_wreg_ext(struct amdgpu_device *adev,
+                                    u64 reg_addr, u32 reg_data);
 void amdgpu_mm_wreg_mmio_rlc(struct amdgpu_device *adev,
                             uint32_t reg, uint32_t v);
 void amdgpu_mm_wreg8(struct amdgpu_device *adev, uint32_t offset, uint8_t value);
@@ -1142,6 +1151,8 @@ int emu_soc_asic_init(struct amdgpu_device *adev);
 #define WREG32_PCIE(reg, v) adev->pcie_wreg(adev, (reg), (v))
 #define RREG32_PCIE_PORT(reg) adev->pciep_rreg(adev, (reg))
 #define WREG32_PCIE_PORT(reg, v) adev->pciep_wreg(adev, (reg), (v))
+#define RREG32_PCIE_EXT(reg) adev->pcie_rreg_ext(adev, (reg))
+#define WREG32_PCIE_EXT(reg, v) adev->pcie_wreg_ext(adev, (reg), (v))
 #define RREG64_PCIE(reg) adev->pcie_rreg64(adev, (reg))
 #define WREG64_PCIE(reg, v) adev->pcie_wreg64(adev, (reg), (v))
 #define RREG32_SMC(reg) adev->smc_rreg(adev, (reg))
index 38b6bbcaf186f0450fdba257650ee44ec90d3d0e..c190365d67e27ac59a0bbe3aa9f3b35097964206 100644 (file)
@@ -707,6 +707,48 @@ u32 amdgpu_device_indirect_rreg(struct amdgpu_device *adev,
        return r;
 }
 
+u32 amdgpu_device_indirect_rreg_ext(struct amdgpu_device *adev,
+                                   u64 reg_addr)
+{
+       unsigned long flags, pcie_index, pcie_index_hi, pcie_data;
+       u32 r;
+       void __iomem *pcie_index_offset;
+       void __iomem *pcie_index_hi_offset;
+       void __iomem *pcie_data_offset;
+
+       pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
+       pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
+       if (adev->nbio.funcs->get_pcie_index_hi_offset)
+               pcie_index_hi = adev->nbio.funcs->get_pcie_index_hi_offset(adev);
+       else
+               pcie_index_hi = 0;
+
+       spin_lock_irqsave(&adev->pcie_idx_lock, flags);
+       pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4;
+       pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4;
+       if (pcie_index_hi != 0)
+               pcie_index_hi_offset = (void __iomem *)adev->rmmio +
+                               pcie_index_hi * 4;
+
+       writel(reg_addr, pcie_index_offset);
+       readl(pcie_index_offset);
+       if (pcie_index_hi != 0) {
+               writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset);
+               readl(pcie_index_hi_offset);
+       }
+       r = readl(pcie_data_offset);
+
+       /* clear the high bits */
+       if (pcie_index_hi != 0) {
+               writel(0, pcie_index_hi_offset);
+               readl(pcie_index_hi_offset);
+       }
+
+       spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
+
+       return r;
+}
+
 /**
  * amdgpu_device_indirect_rreg64 - read a 64bits indirect register
  *
@@ -774,6 +816,46 @@ void amdgpu_device_indirect_wreg(struct amdgpu_device *adev,
        spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
 }
 
+void amdgpu_device_indirect_wreg_ext(struct amdgpu_device *adev,
+                                    u64 reg_addr, u32 reg_data)
+{
+       unsigned long flags, pcie_index, pcie_index_hi, pcie_data;
+       void __iomem *pcie_index_offset;
+       void __iomem *pcie_index_hi_offset;
+       void __iomem *pcie_data_offset;
+
+       pcie_index = adev->nbio.funcs->get_pcie_index_offset(adev);
+       pcie_data = adev->nbio.funcs->get_pcie_data_offset(adev);
+       if (adev->nbio.funcs->get_pcie_index_hi_offset)
+               pcie_index_hi = adev->nbio.funcs->get_pcie_index_hi_offset(adev);
+       else
+               pcie_index_hi = 0;
+
+       spin_lock_irqsave(&adev->pcie_idx_lock, flags);
+       pcie_index_offset = (void __iomem *)adev->rmmio + pcie_index * 4;
+       pcie_data_offset = (void __iomem *)adev->rmmio + pcie_data * 4;
+       if (pcie_index_hi != 0)
+               pcie_index_hi_offset = (void __iomem *)adev->rmmio +
+                               pcie_index_hi * 4;
+
+       writel(reg_addr, pcie_index_offset);
+       readl(pcie_index_offset);
+       if (pcie_index_hi != 0) {
+               writel((reg_addr >> 32) & 0xff, pcie_index_hi_offset);
+               readl(pcie_index_hi_offset);
+       }
+       writel(reg_data, pcie_data_offset);
+       readl(pcie_data_offset);
+
+       /* clear the high bits */
+       if (pcie_index_hi != 0) {
+               writel(0, pcie_index_hi_offset);
+               readl(pcie_index_hi_offset);
+       }
+
+       spin_unlock_irqrestore(&adev->pcie_idx_lock, flags);
+}
+
 /**
  * amdgpu_device_indirect_wreg64 - write a 64bits indirect register address
  *
@@ -840,6 +922,13 @@ static uint32_t amdgpu_invalid_rreg(struct amdgpu_device *adev, uint32_t reg)
        return 0;
 }
 
+static uint32_t amdgpu_invalid_rreg_ext(struct amdgpu_device *adev, uint64_t reg)
+{
+       DRM_ERROR("Invalid callback to read register 0x%llX\n", reg);
+       BUG();
+       return 0;
+}
+
 /**
  * amdgpu_invalid_wreg - dummy reg write function
  *
@@ -857,6 +946,13 @@ static void amdgpu_invalid_wreg(struct amdgpu_device *adev, uint32_t reg, uint32
        BUG();
 }
 
+static void amdgpu_invalid_wreg_ext(struct amdgpu_device *adev, uint64_t reg, uint32_t v)
+{
+       DRM_ERROR("Invalid callback to write register 0x%llX with 0x%08X\n",
+                 reg, v);
+       BUG();
+}
+
 /**
  * amdgpu_invalid_rreg64 - dummy 64 bit reg read function
  *
@@ -3611,6 +3707,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
        adev->smc_wreg = &amdgpu_invalid_wreg;
        adev->pcie_rreg = &amdgpu_invalid_rreg;
        adev->pcie_wreg = &amdgpu_invalid_wreg;
+       adev->pcie_rreg_ext = &amdgpu_invalid_rreg_ext;
+       adev->pcie_wreg_ext = &amdgpu_invalid_wreg_ext;
        adev->pciep_rreg = &amdgpu_invalid_rreg;
        adev->pciep_wreg = &amdgpu_invalid_wreg;
        adev->pcie_rreg64 = &amdgpu_invalid_rreg64;
index 6a636c34b7178b8e92b684619eaa2237bde0d4ae..8fa3a1f3b1812696232a727fc6d49e6c392dfdd4 100644 (file)
@@ -61,6 +61,7 @@ struct amdgpu_nbio_funcs {
        u32 (*get_hdp_flush_done_offset)(struct amdgpu_device *adev);
        u32 (*get_pcie_index_offset)(struct amdgpu_device *adev);
        u32 (*get_pcie_data_offset)(struct amdgpu_device *adev);
+       u32 (*get_pcie_index_hi_offset)(struct amdgpu_device *adev);
        u32 (*get_pcie_port_index_offset)(struct amdgpu_device *adev);
        u32 (*get_pcie_port_data_offset)(struct amdgpu_device *adev);
        u32 (*get_rev_id)(struct amdgpu_device *adev);
index 9626270059619ee2fba6c22adb9c5162a9cdf861..92e9c5ed95df8736f5f678c29fa5b2b20aa872eb 100644 (file)
@@ -319,6 +319,11 @@ static u32 nbio_v7_9_get_pcie_data_offset(struct amdgpu_device *adev)
        return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX0_PCIE_DATA2);
 }
 
+static u32 nbio_v7_9_get_pcie_index_hi_offset(struct amdgpu_device *adev)
+{
+       return SOC15_REG_OFFSET(NBIO, 0, regBIF_BX0_PCIE_INDEX2_HI);
+}
+
 const struct nbio_hdp_flush_reg nbio_v7_9_hdp_flush_reg = {
        .ref_and_mask_cp0 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP0_MASK,
        .ref_and_mask_cp1 = BIF_BX_PF0_GPU_HDP_FLUSH_DONE__CP1_MASK,
@@ -382,6 +387,7 @@ const struct amdgpu_nbio_funcs nbio_v7_9_funcs = {
        .get_hdp_flush_done_offset = nbio_v7_9_get_hdp_flush_done_offset,
        .get_pcie_index_offset = nbio_v7_9_get_pcie_index_offset,
        .get_pcie_data_offset = nbio_v7_9_get_pcie_data_offset,
+       .get_pcie_index_hi_offset = nbio_v7_9_get_pcie_index_hi_offset,
        .get_rev_id = nbio_v7_9_get_rev_id,
        .mc_access_enable = nbio_v7_9_mc_access_enable,
        .get_memsize = nbio_v7_9_get_memsize,
index b7e8af56df84628549f4af2ccd92767751a4d449..b9bcb12bff91ea7f935f32de11e9fcfd619016b9 100644 (file)
@@ -866,6 +866,8 @@ static int soc15_common_early_init(void *handle)
        adev->smc_wreg = NULL;
        adev->pcie_rreg = &amdgpu_device_indirect_rreg;
        adev->pcie_wreg = &amdgpu_device_indirect_wreg;
+       adev->pcie_rreg_ext = &amdgpu_device_indirect_rreg_ext;
+       adev->pcie_wreg_ext = &amdgpu_device_indirect_wreg_ext;
        adev->pcie_rreg64 = &amdgpu_device_indirect_rreg64;
        adev->pcie_wreg64 = &amdgpu_device_indirect_wreg64;
        adev->uvd_ctx_rreg = &soc15_uvd_ctx_rreg;