Skip to content

Commit

Permalink
Enable reading FRU chip via I2C
Browse files Browse the repository at this point in the history
Change-Id: I9dd43a579f74bb2d6bf6470be2ad42453d592ba8
Signed-off-by: Kent Russell <kent.russell@amd.com>
  • Loading branch information
kentrussell committed Feb 3, 2020
1 parent f3fb038 commit bb41241
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 1 deletion.
2 changes: 2 additions & 0 deletions drivers/gpu/drm/amd/amdgpu/amdgpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -1027,6 +1027,8 @@ struct amdgpu_device {

bool pm_sysfs_en;
bool ucode_sysfs_en;

char serial[16];
};

static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev)
Expand Down
28 changes: 28 additions & 0 deletions drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,28 @@ static DEVICE_ATTR(pcie_replay_count, S_IRUGO,

static void amdgpu_device_get_pcie_info(struct amdgpu_device *adev);

/**
* DOC: serial_number
*
* The amdgpu driver provides a sysfs API for reporting the serial number
* for the device
* The file serial_number is used for this and returns the serial number
* as returned from the FRU.
* NOTE: This is only available for certain server cards
*/

static ssize_t amdgpu_device_get_serial_number(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct drm_device *ddev = dev_get_drvdata(dev);
struct amdgpu_device *adev = ddev->dev_private;

return snprintf(buf, PAGE_SIZE, "%s\n", adev->serial);
}

static DEVICE_ATTR(serial_number, S_IRUGO,
amdgpu_device_get_serial_number, NULL);

/**
* amdgpu_device_supports_boco - Is the device a dGPU with HG/PX power control
*
Expand Down Expand Up @@ -3158,6 +3180,11 @@ int amdgpu_device_init(struct amdgpu_device *adev,
return r;
}

r = device_create_file(adev->dev, &dev_attr_serial_number);
if (r) {
dev_err(adev->dev, "Could not create serial_number");
return r;
}
if (IS_ENABLED(CONFIG_PERF_EVENTS))
r = amdgpu_pmu_init(adev);
if (r)
Expand Down Expand Up @@ -3237,6 +3264,7 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
device_remove_file(adev->dev, &dev_attr_pcie_replay_count);
if (adev->ucode_sysfs_en)
amdgpu_ucode_sysfs_fini(adev);
device_remove_file(adev->dev, &dev_attr_serial_number);
if (IS_ENABLED(CONFIG_PERF_EVENTS))
amdgpu_pmu_fini(adev);
amdgpu_debugfs_preempt_cleanup(adev);
Expand Down
42 changes: 41 additions & 1 deletion drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

#define EEPROM_I2C_TARGET_ADDR_ARCTURUS 0xA8
#define EEPROM_I2C_TARGET_ADDR_VEGA20 0xA0

#define EEPROM_I2C_PI_ADDR 0xAC
/*
* The 2 macros bellow represent the actual size in bytes that
* those entities occupy in the EEPROM memory.
Expand Down Expand Up @@ -79,6 +79,44 @@ static void __decode_table_header_from_buff(struct amdgpu_ras_eeprom_table_heade
hdr->checksum = le32_to_cpu(pp[4]);
}

static int amdgpu_ras_eeprom_get_product_info(struct amdgpu_ras_eeprom_control *control)
{
int ret = 0, i;
struct amdgpu_device *adev = to_amdgpu_device(control);
unsigned char buff[18], sn[16];
//TODO: Get length of entire product info segment
struct i2c_msg msg = {
.addr = EEPROM_I2C_PI_ADDR,
.flags = I2C_M_RD,
.len = EEPROM_ADDRESS_SIZE + 16,
.buf = buff,
};

/* Not supported before VG20 */
if (adev->asic_type < CHIP_VEGA20)
return 0;

/* Read from address 0x3d, which is a hard-coded value for serial
* number for Vega20. This won't make it to upstream
*/
buff[0] = 0;
buff[1] = 0x31;

/* No need to lock the mutex, since the data is ummutable */
ret = i2c_transfer(&control->eeprom_accessor, &msg, 1);

// Convert to ASCII from hex
for (i = 2; i < 16; i++) {
sprintf(&sn[i-2], "%c", buff[i]);
}
if (ret < 1) {
DRM_ERROR("Failed to read EEPROM product info, ret:%d", ret);
return ret;
}
strcpy(adev->serial, sn);
return 0;
}

static int __update_table_header(struct amdgpu_ras_eeprom_control *control,
unsigned char *buff)
{
Expand Down Expand Up @@ -260,6 +298,8 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control)
ret = amdgpu_ras_eeprom_reset_table(control);
}

amdgpu_ras_eeprom_get_product_info(control);

return ret == 1 ? 0 : -EIO;
}

Expand Down

0 comments on commit bb41241

Please sign in to comment.