drm/amdgpu: Read aquavanjaram PCIE register state
authorLijo Lazar <lijo.lazar@amd.com>
Fri, 6 Oct 2023 08:50:45 +0000 (14:20 +0530)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 29 Nov 2023 21:49:35 +0000 (16:49 -0500)
Add support to read aqua vanjaram PCIE register state

Signed-off-by: Lijo Lazar <lijo.lazar@amd.com>
Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/aqua_vanjaram.c
drivers/gpu/drm/amd/amdgpu/soc15.c
drivers/gpu/drm/amd/amdgpu/soc15.h

index 3f715e7fe1a959ccabcc9da0c35633efa387eb06..0a4598480dd552fbe1fbf7b06a9c66460e57c79d 100644 (file)
@@ -24,6 +24,7 @@
 #include "soc15.h"
 
 #include "soc15_common.h"
+#include "amdgpu_reg_state.h"
 #include "amdgpu_xcp.h"
 #include "gfx_v9_4_3.h"
 #include "gfxhub_v1_2.h"
@@ -656,3 +657,117 @@ int aqua_vanjaram_init_soc_config(struct amdgpu_device *adev)
 
        return 0;
 }
+
+static void aqua_read_smn(struct amdgpu_device *adev,
+                         struct amdgpu_smn_reg_data *regdata,
+                         uint64_t smn_addr)
+{
+       regdata->addr = smn_addr;
+       regdata->value = RREG32_PCIE(smn_addr);
+}
+
+struct aqua_reg_list {
+       uint64_t start_addr;
+       uint32_t num_regs;
+       uint32_t incrx;
+};
+
+#define DW_ADDR_INCR   4
+
+#define smnreg_0x1A340218      0x1A340218
+#define smnreg_0x1A3402E4      0x1A3402E4
+#define smnreg_0x1A340294      0x1A340294
+#define smreg_0x1A380088       0x1A380088
+
+#define NUM_PCIE_SMN_REGS      14
+
+static struct aqua_reg_list pcie_reg_addrs[] = {
+       { smnreg_0x1A340218, 1, 0 },
+       { smnreg_0x1A3402E4, 1, 0 },
+       { smnreg_0x1A340294, 6, DW_ADDR_INCR },
+       { smreg_0x1A380088, 6, DW_ADDR_INCR },
+};
+
+static ssize_t aqua_vanjaram_read_pcie_state(struct amdgpu_device *adev,
+                                            void *buf, size_t max_size)
+{
+       struct amdgpu_reg_state_pcie_v1_0 *pcie_reg_state;
+       uint32_t start_addr, incrx, num_regs, szbuf;
+       struct amdgpu_regs_pcie_v1_0 *pcie_regs;
+       struct amdgpu_smn_reg_data *reg_data;
+       struct pci_dev *us_pdev, *ds_pdev;
+       int aer_cap, r, n;
+
+       if (!buf || !max_size)
+               return -EINVAL;
+
+       pcie_reg_state = (struct amdgpu_reg_state_pcie_v1_0 *)buf;
+
+       szbuf = sizeof(*pcie_reg_state) +
+               amdgpu_reginst_size(1, sizeof(*pcie_regs), NUM_PCIE_SMN_REGS);
+       /* Only one instance of pcie regs */
+       if (max_size < szbuf)
+               return -EOVERFLOW;
+
+       pcie_regs = (struct amdgpu_regs_pcie_v1_0 *)((uint8_t *)buf +
+                                                    sizeof(*pcie_reg_state));
+       pcie_regs->inst_header.instance = 0;
+       pcie_regs->inst_header.state = AMDGPU_INST_S_OK;
+       pcie_regs->inst_header.num_smn_regs = NUM_PCIE_SMN_REGS;
+
+       reg_data = pcie_regs->smn_reg_values;
+
+       for (r = 0; r < ARRAY_SIZE(pcie_reg_addrs); r++) {
+               start_addr = pcie_reg_addrs[r].start_addr;
+               incrx = pcie_reg_addrs[r].incrx;
+               num_regs = pcie_reg_addrs[r].num_regs;
+               for (n = 0; n < num_regs; n++) {
+                       aqua_read_smn(adev, reg_data, start_addr + n * incrx);
+                       ++reg_data;
+               }
+       }
+
+       ds_pdev = pci_upstream_bridge(adev->pdev);
+       us_pdev = pci_upstream_bridge(ds_pdev);
+
+       pcie_capability_read_word(us_pdev, PCI_EXP_DEVSTA,
+                                 &pcie_regs->device_status);
+       pcie_capability_read_word(us_pdev, PCI_EXP_LNKSTA,
+                                 &pcie_regs->link_status);
+
+       aer_cap = pci_find_ext_capability(us_pdev, PCI_EXT_CAP_ID_ERR);
+       if (aer_cap) {
+               pci_read_config_dword(us_pdev, aer_cap + PCI_ERR_COR_STATUS,
+                                     &pcie_regs->pcie_corr_err_status);
+               pci_read_config_dword(us_pdev, aer_cap + PCI_ERR_UNCOR_STATUS,
+                                     &pcie_regs->pcie_uncorr_err_status);
+       }
+
+       pci_read_config_dword(us_pdev, PCI_PRIMARY_BUS,
+                             &pcie_regs->sub_bus_number_latency);
+
+       pcie_reg_state->common_header.structure_size = szbuf;
+       pcie_reg_state->common_header.format_revision = 1;
+       pcie_reg_state->common_header.content_revision = 0;
+       pcie_reg_state->common_header.state_type = AMDGPU_REG_STATE_TYPE_PCIE;
+       pcie_reg_state->common_header.num_instances = 1;
+
+       return pcie_reg_state->common_header.structure_size;
+}
+
+ssize_t aqua_vanjaram_get_reg_state(struct amdgpu_device *adev,
+                                   enum amdgpu_reg_state reg_state, void *buf,
+                                   size_t max_size)
+{
+       ssize_t size;
+
+       switch (reg_state) {
+       case AMDGPU_REG_STATE_TYPE_PCIE:
+               size = aqua_vanjaram_read_pcie_state(adev, buf, max_size);
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return size;
+}
index d4b8d62f42943f7913d16b00ee6eac6dfbc13315..e3d41e8aac9d9020e42cddc63ae7cf1472ffbb8c 100644 (file)
@@ -902,6 +902,7 @@ static const struct amdgpu_asic_funcs aqua_vanjaram_asic_funcs =
        .pre_asic_init = &soc15_pre_asic_init,
        .query_video_codecs = &soc15_query_video_codecs,
        .encode_ext_smn_addressing = &aqua_vanjaram_encode_ext_smn_addressing,
+       .get_reg_state = &aqua_vanjaram_get_reg_state,
 };
 
 static int soc15_common_early_init(void *handle)
index eac54042c6c0e424629cf6c2c3cbbe8824ad3246..1444b7765e4bea6a5cc8fe77a3d6ec9d20d32865 100644 (file)
@@ -27,6 +27,7 @@
 #include "nbio_v6_1.h"
 #include "nbio_v7_0.h"
 #include "nbio_v7_4.h"
+#include "amdgpu_reg_state.h"
 
 extern const struct amdgpu_ip_block_version vega10_common_ip_block;
 
@@ -114,6 +115,9 @@ int aldebaran_reg_base_init(struct amdgpu_device *adev);
 void aqua_vanjaram_ip_map_init(struct amdgpu_device *adev);
 u64 aqua_vanjaram_encode_ext_smn_addressing(int ext_id);
 int aqua_vanjaram_init_soc_config(struct amdgpu_device *adev);
+ssize_t aqua_vanjaram_get_reg_state(struct amdgpu_device *adev,
+                                   enum amdgpu_reg_state reg_state, void *buf,
+                                   size_t max_size);
 
 void vega10_doorbell_index_init(struct amdgpu_device *adev);
 void vega20_doorbell_index_init(struct amdgpu_device *adev);