Commit 02bab923 authored by David Panariti's avatar David Panariti Committed by Alex Deucher

drm/amdgpu: Add ability to determine and report if board supports ECC.

Make initialization code check the ECC related registers, which are initialized
by the VBIOS, to see if ECC is present and initialized and DRM_INFO() the
result.
Signed-off-by: default avatarDavid Panariti <David.Panariti@amd.com>
Reviewed-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 26f11085
......@@ -36,6 +36,7 @@
#include "vega10/ATHUB/athub_1_0_offset.h"
#include "soc15_common.h"
#include "vega10/UMC/umc_6_0_sh_mask.h"
#include "nbio_v6_1.h"
#include "nbio_v7_0.h"
......@@ -85,6 +86,121 @@ static const u32 golden_settings_athub_1_0_0[] =
SOC15_REG_OFFSET(ATHUB, 0, mmRPB_ARB_CNTL2), 0x00ff00ff, 0x00080008
};
/* Ecc related register addresses, (BASE + reg offset) */
/* Universal Memory Controller caps (may be fused). */
/* UMCCH:UmcLocalCap */
#define UMCLOCALCAPS_ADDR0 (0x00014306 + 0x00000000)
#define UMCLOCALCAPS_ADDR1 (0x00014306 + 0x00000800)
#define UMCLOCALCAPS_ADDR2 (0x00014306 + 0x00001000)
#define UMCLOCALCAPS_ADDR3 (0x00014306 + 0x00001800)
#define UMCLOCALCAPS_ADDR4 (0x00054306 + 0x00000000)
#define UMCLOCALCAPS_ADDR5 (0x00054306 + 0x00000800)
#define UMCLOCALCAPS_ADDR6 (0x00054306 + 0x00001000)
#define UMCLOCALCAPS_ADDR7 (0x00054306 + 0x00001800)
#define UMCLOCALCAPS_ADDR8 (0x00094306 + 0x00000000)
#define UMCLOCALCAPS_ADDR9 (0x00094306 + 0x00000800)
#define UMCLOCALCAPS_ADDR10 (0x00094306 + 0x00001000)
#define UMCLOCALCAPS_ADDR11 (0x00094306 + 0x00001800)
#define UMCLOCALCAPS_ADDR12 (0x000d4306 + 0x00000000)
#define UMCLOCALCAPS_ADDR13 (0x000d4306 + 0x00000800)
#define UMCLOCALCAPS_ADDR14 (0x000d4306 + 0x00001000)
#define UMCLOCALCAPS_ADDR15 (0x000d4306 + 0x00001800)
/* Universal Memory Controller Channel config. */
/* UMCCH:UMC_CONFIG */
#define UMCCH_UMC_CONFIG_ADDR0 (0x00014040 + 0x00000000)
#define UMCCH_UMC_CONFIG_ADDR1 (0x00014040 + 0x00000800)
#define UMCCH_UMC_CONFIG_ADDR2 (0x00014040 + 0x00001000)
#define UMCCH_UMC_CONFIG_ADDR3 (0x00014040 + 0x00001800)
#define UMCCH_UMC_CONFIG_ADDR4 (0x00054040 + 0x00000000)
#define UMCCH_UMC_CONFIG_ADDR5 (0x00054040 + 0x00000800)
#define UMCCH_UMC_CONFIG_ADDR6 (0x00054040 + 0x00001000)
#define UMCCH_UMC_CONFIG_ADDR7 (0x00054040 + 0x00001800)
#define UMCCH_UMC_CONFIG_ADDR8 (0x00094040 + 0x00000000)
#define UMCCH_UMC_CONFIG_ADDR9 (0x00094040 + 0x00000800)
#define UMCCH_UMC_CONFIG_ADDR10 (0x00094040 + 0x00001000)
#define UMCCH_UMC_CONFIG_ADDR11 (0x00094040 + 0x00001800)
#define UMCCH_UMC_CONFIG_ADDR12 (0x000d4040 + 0x00000000)
#define UMCCH_UMC_CONFIG_ADDR13 (0x000d4040 + 0x00000800)
#define UMCCH_UMC_CONFIG_ADDR14 (0x000d4040 + 0x00001000)
#define UMCCH_UMC_CONFIG_ADDR15 (0x000d4040 + 0x00001800)
/* Universal Memory Controller Channel Ecc config. */
/* UMCCH:EccCtrl */
#define UMCCH_ECCCTRL_ADDR0 (0x00014053 + 0x00000000)
#define UMCCH_ECCCTRL_ADDR1 (0x00014053 + 0x00000800)
#define UMCCH_ECCCTRL_ADDR2 (0x00014053 + 0x00001000)
#define UMCCH_ECCCTRL_ADDR3 (0x00014053 + 0x00001800)
#define UMCCH_ECCCTRL_ADDR4 (0x00054053 + 0x00000000)
#define UMCCH_ECCCTRL_ADDR5 (0x00054053 + 0x00000800)
#define UMCCH_ECCCTRL_ADDR6 (0x00054053 + 0x00001000)
#define UMCCH_ECCCTRL_ADDR7 (0x00054053 + 0x00001800)
#define UMCCH_ECCCTRL_ADDR8 (0x00094053 + 0x00000000)
#define UMCCH_ECCCTRL_ADDR9 (0x00094053 + 0x00000800)
#define UMCCH_ECCCTRL_ADDR10 (0x00094053 + 0x00001000)
#define UMCCH_ECCCTRL_ADDR11 (0x00094053 + 0x00001800)
#define UMCCH_ECCCTRL_ADDR12 (0x000d4053 + 0x00000000)
#define UMCCH_ECCCTRL_ADDR13 (0x000d4053 + 0x00000800)
#define UMCCH_ECCCTRL_ADDR14 (0x000d4053 + 0x00001000)
#define UMCCH_ECCCTRL_ADDR15 (0x000d4053 + 0x00001800)
static const uint32_t ecc_umclocalcap_addrs[] = {
UMCLOCALCAPS_ADDR0,
UMCLOCALCAPS_ADDR1,
UMCLOCALCAPS_ADDR2,
UMCLOCALCAPS_ADDR3,
UMCLOCALCAPS_ADDR4,
UMCLOCALCAPS_ADDR5,
UMCLOCALCAPS_ADDR6,
UMCLOCALCAPS_ADDR7,
UMCLOCALCAPS_ADDR8,
UMCLOCALCAPS_ADDR9,
UMCLOCALCAPS_ADDR10,
UMCLOCALCAPS_ADDR11,
UMCLOCALCAPS_ADDR12,
UMCLOCALCAPS_ADDR13,
UMCLOCALCAPS_ADDR14,
UMCLOCALCAPS_ADDR15,
};
static const uint32_t ecc_umcch_umc_config_addrs[] = {
UMCCH_UMC_CONFIG_ADDR0,
UMCCH_UMC_CONFIG_ADDR1,
UMCCH_UMC_CONFIG_ADDR2,
UMCCH_UMC_CONFIG_ADDR3,
UMCCH_UMC_CONFIG_ADDR4,
UMCCH_UMC_CONFIG_ADDR5,
UMCCH_UMC_CONFIG_ADDR6,
UMCCH_UMC_CONFIG_ADDR7,
UMCCH_UMC_CONFIG_ADDR8,
UMCCH_UMC_CONFIG_ADDR9,
UMCCH_UMC_CONFIG_ADDR10,
UMCCH_UMC_CONFIG_ADDR11,
UMCCH_UMC_CONFIG_ADDR12,
UMCCH_UMC_CONFIG_ADDR13,
UMCCH_UMC_CONFIG_ADDR14,
UMCCH_UMC_CONFIG_ADDR15,
};
static const uint32_t ecc_umcch_eccctrl_addrs[] = {
UMCCH_ECCCTRL_ADDR0,
UMCCH_ECCCTRL_ADDR1,
UMCCH_ECCCTRL_ADDR2,
UMCCH_ECCCTRL_ADDR3,
UMCCH_ECCCTRL_ADDR4,
UMCCH_ECCCTRL_ADDR5,
UMCCH_ECCCTRL_ADDR6,
UMCCH_ECCCTRL_ADDR7,
UMCCH_ECCCTRL_ADDR8,
UMCCH_ECCCTRL_ADDR9,
UMCCH_ECCCTRL_ADDR10,
UMCCH_ECCCTRL_ADDR11,
UMCCH_ECCCTRL_ADDR12,
UMCCH_ECCCTRL_ADDR13,
UMCCH_ECCCTRL_ADDR14,
UMCCH_ECCCTRL_ADDR15,
};
static int gmc_v9_0_vm_fault_interrupt_state(struct amdgpu_device *adev,
struct amdgpu_irq_src *src,
unsigned type,
......@@ -389,6 +505,85 @@ static int gmc_v9_0_early_init(void *handle)
return 0;
}
static int gmc_v9_0_ecc_available(struct amdgpu_device *adev)
{
uint32_t reg_val;
uint32_t reg_addr;
uint32_t field_val;
size_t i;
uint32_t fv2;
size_t lost_sheep;
DRM_DEBUG("ecc: gmc_v9_0_ecc_available()\n");
lost_sheep = 0;
for (i = 0; i < ARRAY_SIZE(ecc_umclocalcap_addrs); ++i) {
reg_addr = ecc_umclocalcap_addrs[i];
DRM_DEBUG("ecc: "
"UMCCH_UmcLocalCap[%zu]: reg_addr: 0x%08x\n",
i, reg_addr);
reg_val = RREG32(reg_addr);
field_val = REG_GET_FIELD(reg_val, UMCCH0_0_UmcLocalCap,
EccDis);
DRM_DEBUG("ecc: "
"reg_val: 0x%08x, "
"EccDis: 0x%08x, ",
reg_val, field_val);
if (field_val) {
DRM_ERROR("ecc: UmcLocalCap:EccDis is set.\n");
++lost_sheep;
}
}
for (i = 0; i < ARRAY_SIZE(ecc_umcch_umc_config_addrs); ++i) {
reg_addr = ecc_umcch_umc_config_addrs[i];
DRM_DEBUG("ecc: "
"UMCCH0_0_UMC_CONFIG[%zu]: reg_addr: 0x%08x",
i, reg_addr);
reg_val = RREG32(reg_addr);
field_val = REG_GET_FIELD(reg_val, UMCCH0_0_UMC_CONFIG,
DramReady);
DRM_DEBUG("ecc: "
"reg_val: 0x%08x, "
"DramReady: 0x%08x\n",
reg_val, field_val);
if (!field_val) {
DRM_ERROR("ecc: UMC_CONFIG:DramReady is not set.\n");
++lost_sheep;
}
}
for (i = 0; i < ARRAY_SIZE(ecc_umcch_eccctrl_addrs); ++i) {
reg_addr = ecc_umcch_eccctrl_addrs[i];
DRM_DEBUG("ecc: "
"UMCCH_EccCtrl[%zu]: reg_addr: 0x%08x, ",
i, reg_addr);
reg_val = RREG32(reg_addr);
field_val = REG_GET_FIELD(reg_val, UMCCH0_0_EccCtrl,
WrEccEn);
fv2 = REG_GET_FIELD(reg_val, UMCCH0_0_EccCtrl,
RdEccEn);
DRM_DEBUG("ecc: "
"reg_val: 0x%08x, "
"WrEccEn: 0x%08x, "
"RdEccEn: 0x%08x\n",
reg_val, field_val, fv2);
if (!field_val) {
DRM_ERROR("ecc: WrEccEn is not set\n");
++lost_sheep;
}
if (!fv2) {
DRM_ERROR("ecc: RdEccEn is not set\n");
++lost_sheep;
}
}
DRM_DEBUG("ecc: lost_sheep: %zu\n", lost_sheep);
return lost_sheep == 0;
}
static int gmc_v9_0_late_init(void *handle)
{
struct amdgpu_device *adev = (struct amdgpu_device *)handle;
......@@ -403,6 +598,7 @@ static int gmc_v9_0_late_init(void *handle)
*/
unsigned vm_inv_eng[AMDGPU_MAX_VMHUBS] = { 4, 4 };
unsigned i;
int r;
for(i = 0; i < adev->num_rings; ++i) {
struct amdgpu_ring *ring = adev->rings[i];
......@@ -418,6 +614,16 @@ static int gmc_v9_0_late_init(void *handle)
for(i = 0; i < AMDGPU_MAX_VMHUBS; ++i)
BUG_ON(vm_inv_eng[i] > 16);
r = gmc_v9_0_ecc_available(adev);
if (r == 1) {
DRM_INFO("ECC is active.\n");
} else if (r == 0) {
DRM_INFO("ECC is not present.\n");
} else {
DRM_ERROR("gmc_v9_0_ecc_available() failed. r: %d\n", r);
return r;
}
return amdgpu_irq_get(adev, &adev->mc.vm_fault, 0);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment