Skip to content

Commit bb41241

Browse files
committed
Enable reading FRU chip via I2C
Change-Id: I9dd43a579f74bb2d6bf6470be2ad42453d592ba8 Signed-off-by: Kent Russell <[email protected]>
1 parent f3fb038 commit bb41241

File tree

3 files changed

+71
-1
lines changed

3 files changed

+71
-1
lines changed

drivers/gpu/drm/amd/amdgpu/amdgpu.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,8 @@ struct amdgpu_device {
10271027

10281028
bool pm_sysfs_en;
10291029
bool ucode_sysfs_en;
1030+
1031+
char serial[16];
10301032
};
10311033

10321034
static inline struct amdgpu_device *amdgpu_ttm_adev(struct ttm_bo_device *bdev)

drivers/gpu/drm/amd/amdgpu/amdgpu_device.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,28 @@ static DEVICE_ATTR(pcie_replay_count, S_IRUGO,
139139

140140
static void amdgpu_device_get_pcie_info(struct amdgpu_device *adev);
141141

142+
/**
143+
* DOC: serial_number
144+
*
145+
* The amdgpu driver provides a sysfs API for reporting the serial number
146+
* for the device
147+
* The file serial_number is used for this and returns the serial number
148+
* as returned from the FRU.
149+
* NOTE: This is only available for certain server cards
150+
*/
151+
152+
static ssize_t amdgpu_device_get_serial_number(struct device *dev,
153+
struct device_attribute *attr, char *buf)
154+
{
155+
struct drm_device *ddev = dev_get_drvdata(dev);
156+
struct amdgpu_device *adev = ddev->dev_private;
157+
158+
return snprintf(buf, PAGE_SIZE, "%s\n", adev->serial);
159+
}
160+
161+
static DEVICE_ATTR(serial_number, S_IRUGO,
162+
amdgpu_device_get_serial_number, NULL);
163+
142164
/**
143165
* amdgpu_device_supports_boco - Is the device a dGPU with HG/PX power control
144166
*
@@ -3158,6 +3180,11 @@ int amdgpu_device_init(struct amdgpu_device *adev,
31583180
return r;
31593181
}
31603182

3183+
r = device_create_file(adev->dev, &dev_attr_serial_number);
3184+
if (r) {
3185+
dev_err(adev->dev, "Could not create serial_number");
3186+
return r;
3187+
}
31613188
if (IS_ENABLED(CONFIG_PERF_EVENTS))
31623189
r = amdgpu_pmu_init(adev);
31633190
if (r)
@@ -3237,6 +3264,7 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
32373264
device_remove_file(adev->dev, &dev_attr_pcie_replay_count);
32383265
if (adev->ucode_sysfs_en)
32393266
amdgpu_ucode_sysfs_fini(adev);
3267+
device_remove_file(adev->dev, &dev_attr_serial_number);
32403268
if (IS_ENABLED(CONFIG_PERF_EVENTS))
32413269
amdgpu_pmu_fini(adev);
32423270
amdgpu_debugfs_preempt_cleanup(adev);

drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.c

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929

3030
#define EEPROM_I2C_TARGET_ADDR_ARCTURUS 0xA8
3131
#define EEPROM_I2C_TARGET_ADDR_VEGA20 0xA0
32-
32+
#define EEPROM_I2C_PI_ADDR 0xAC
3333
/*
3434
* The 2 macros bellow represent the actual size in bytes that
3535
* those entities occupy in the EEPROM memory.
@@ -79,6 +79,44 @@ static void __decode_table_header_from_buff(struct amdgpu_ras_eeprom_table_heade
7979
hdr->checksum = le32_to_cpu(pp[4]);
8080
}
8181

82+
static int amdgpu_ras_eeprom_get_product_info(struct amdgpu_ras_eeprom_control *control)
83+
{
84+
int ret = 0, i;
85+
struct amdgpu_device *adev = to_amdgpu_device(control);
86+
unsigned char buff[18], sn[16];
87+
//TODO: Get length of entire product info segment
88+
struct i2c_msg msg = {
89+
.addr = EEPROM_I2C_PI_ADDR,
90+
.flags = I2C_M_RD,
91+
.len = EEPROM_ADDRESS_SIZE + 16,
92+
.buf = buff,
93+
};
94+
95+
/* Not supported before VG20 */
96+
if (adev->asic_type < CHIP_VEGA20)
97+
return 0;
98+
99+
/* Read from address 0x3d, which is a hard-coded value for serial
100+
* number for Vega20. This won't make it to upstream
101+
*/
102+
buff[0] = 0;
103+
buff[1] = 0x31;
104+
105+
/* No need to lock the mutex, since the data is ummutable */
106+
ret = i2c_transfer(&control->eeprom_accessor, &msg, 1);
107+
108+
// Convert to ASCII from hex
109+
for (i = 2; i < 16; i++) {
110+
sprintf(&sn[i-2], "%c", buff[i]);
111+
}
112+
if (ret < 1) {
113+
DRM_ERROR("Failed to read EEPROM product info, ret:%d", ret);
114+
return ret;
115+
}
116+
strcpy(adev->serial, sn);
117+
return 0;
118+
}
119+
82120
static int __update_table_header(struct amdgpu_ras_eeprom_control *control,
83121
unsigned char *buff)
84122
{
@@ -260,6 +298,8 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control)
260298
ret = amdgpu_ras_eeprom_reset_table(control);
261299
}
262300

301+
amdgpu_ras_eeprom_get_product_info(control);
302+
263303
return ret == 1 ? 0 : -EIO;
264304
}
265305

0 commit comments

Comments
 (0)