drm/amdgpu: RAS and FRU now use 19-bit I2C address
Convert RAS and FRU code to use the 19-bit I2C memory address and remove all "slave_addr", as this is now absolved into the 19-bit address. Cc: Jean Delvare <jdelvare@suse.de> Cc: John Clements <john.clements@amd.com> Cc: Alexander Deucher <Alexander.Deucher@amd.com> Cc: Andrey Grodzovsky <Andrey.Grodzovsky@amd.com> Cc: Lijo Lazar <Lijo.Lazar@amd.com> Cc: Stanley Yang <Stanley.Yang@amd.com> Cc: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Luben Tuikov <luben.tuikov@amd.com> Acked-by: Alexander Deucher <Alexander.Deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
025a64a587
commit
ccdfbfec9e
@ -29,8 +29,8 @@
|
||||
#include "amdgpu_fru_eeprom.h"
|
||||
#include "amdgpu_eeprom.h"
|
||||
|
||||
#define I2C_PRODUCT_INFO_ADDR 0x56
|
||||
#define I2C_PRODUCT_INFO_OFFSET 0xC0
|
||||
#define FRU_EEPROM_MADDR 0x60000
|
||||
#define I2C_PRODUCT_INFO_OFFSET 0xC0
|
||||
|
||||
static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
|
||||
{
|
||||
@ -62,12 +62,11 @@ static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
|
||||
}
|
||||
|
||||
static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
|
||||
unsigned char *buff)
|
||||
unsigned char *buff)
|
||||
{
|
||||
int ret, size;
|
||||
|
||||
ret = amdgpu_eeprom_xfer(&adev->pm.smu_i2c, I2C_PRODUCT_INFO_ADDR,
|
||||
addrptr, buff, 1, true);
|
||||
ret = amdgpu_eeprom_xfer(&adev->pm.smu_i2c, addrptr, buff, 1, true);
|
||||
if (ret < 1) {
|
||||
DRM_WARN("FRU: Failed to get size field");
|
||||
return ret;
|
||||
@ -78,8 +77,8 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
|
||||
*/
|
||||
size = buff[0] - I2C_PRODUCT_INFO_OFFSET;
|
||||
|
||||
ret = amdgpu_eeprom_xfer(&adev->pm.smu_i2c, I2C_PRODUCT_INFO_ADDR,
|
||||
addrptr + 1, buff, size, true);
|
||||
ret = amdgpu_eeprom_xfer(&adev->pm.smu_i2c, addrptr + 1, buff, size,
|
||||
true);
|
||||
if (ret < 1) {
|
||||
DRM_WARN("FRU: Failed to get data field");
|
||||
return ret;
|
||||
@ -91,8 +90,8 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
|
||||
int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
|
||||
{
|
||||
unsigned char buff[34];
|
||||
int addrptr, size;
|
||||
int len;
|
||||
u32 addrptr;
|
||||
int size, len;
|
||||
|
||||
if (!is_fru_eeprom_supported(adev))
|
||||
return 0;
|
||||
@ -115,7 +114,7 @@ int amdgpu_fru_get_product_info(struct amdgpu_device *adev)
|
||||
* Bytes 8-a are all 1-byte and refer to the size of the entire struct,
|
||||
* and the language field, so just start from 0xb, manufacturer size
|
||||
*/
|
||||
addrptr = 0xb;
|
||||
addrptr = FRU_EEPROM_MADDR + 0xb;
|
||||
size = amdgpu_fru_read_eeprom(adev, addrptr, buff);
|
||||
if (size < 1) {
|
||||
DRM_ERROR("Failed to read FRU Manufacturer, ret:%d", size);
|
||||
|
@ -28,11 +28,11 @@
|
||||
#include "atom.h"
|
||||
#include "amdgpu_eeprom.h"
|
||||
|
||||
#define EEPROM_I2C_TARGET_ADDR_VEGA20 0x50
|
||||
#define EEPROM_I2C_TARGET_ADDR_ARCTURUS 0x54
|
||||
#define EEPROM_I2C_TARGET_ADDR_ARCTURUS_D342 0x50
|
||||
#define EEPROM_I2C_TARGET_ADDR_SIENNA_CICHLID 0x50
|
||||
#define EEPROM_I2C_TARGET_ADDR_ALDEBARAN 0x50
|
||||
#define EEPROM_I2C_MADDR_VEGA20 0x0
|
||||
#define EEPROM_I2C_MADDR_ARCTURUS 0x40000
|
||||
#define EEPROM_I2C_MADDR_ARCTURUS_D342 0x0
|
||||
#define EEPROM_I2C_MADDR_SIENNA_CICHLID 0x0
|
||||
#define EEPROM_I2C_MADDR_ALDEBARAN 0x0
|
||||
|
||||
/*
|
||||
* The 2 macros bellow represent the actual size in bytes that
|
||||
@ -58,7 +58,6 @@
|
||||
#define EEPROM_HDR_START 0
|
||||
#define EEPROM_RECORD_START (EEPROM_HDR_START + EEPROM_TABLE_HEADER_SIZE)
|
||||
#define EEPROM_MAX_RECORD_NUM ((EEPROM_SIZE_BYTES - EEPROM_TABLE_HEADER_SIZE) / EEPROM_TABLE_RECORD_SIZE)
|
||||
#define EEPROM_ADDR_MSB_MASK GENMASK(17, 8)
|
||||
|
||||
#define to_amdgpu_device(x) (container_of(x, struct amdgpu_ras, eeprom_control))->adev
|
||||
|
||||
@ -74,43 +73,43 @@ static bool __is_ras_eeprom_supported(struct amdgpu_device *adev)
|
||||
}
|
||||
|
||||
static bool __get_eeprom_i2c_addr_arct(struct amdgpu_device *adev,
|
||||
uint16_t *i2c_addr)
|
||||
struct amdgpu_ras_eeprom_control *control)
|
||||
{
|
||||
struct atom_context *atom_ctx = adev->mode_info.atom_context;
|
||||
|
||||
if (!i2c_addr || !atom_ctx)
|
||||
if (!control || !atom_ctx)
|
||||
return false;
|
||||
|
||||
if (strnstr(atom_ctx->vbios_version,
|
||||
"D342",
|
||||
sizeof(atom_ctx->vbios_version)))
|
||||
*i2c_addr = EEPROM_I2C_TARGET_ADDR_ARCTURUS_D342;
|
||||
control->i2c_address = EEPROM_I2C_MADDR_ARCTURUS_D342;
|
||||
else
|
||||
*i2c_addr = EEPROM_I2C_TARGET_ADDR_ARCTURUS;
|
||||
control->i2c_address = EEPROM_I2C_MADDR_ARCTURUS;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool __get_eeprom_i2c_addr(struct amdgpu_device *adev,
|
||||
uint16_t *i2c_addr)
|
||||
struct amdgpu_ras_eeprom_control *control)
|
||||
{
|
||||
if (!i2c_addr)
|
||||
if (!control)
|
||||
return false;
|
||||
|
||||
switch (adev->asic_type) {
|
||||
case CHIP_VEGA20:
|
||||
*i2c_addr = EEPROM_I2C_TARGET_ADDR_VEGA20;
|
||||
control->i2c_address = EEPROM_I2C_MADDR_VEGA20;
|
||||
break;
|
||||
|
||||
case CHIP_ARCTURUS:
|
||||
return __get_eeprom_i2c_addr_arct(adev, i2c_addr);
|
||||
return __get_eeprom_i2c_addr_arct(adev, control);
|
||||
|
||||
case CHIP_SIENNA_CICHLID:
|
||||
*i2c_addr = EEPROM_I2C_TARGET_ADDR_SIENNA_CICHLID;
|
||||
control->i2c_address = EEPROM_I2C_MADDR_SIENNA_CICHLID;
|
||||
break;
|
||||
|
||||
case CHIP_ALDEBARAN:
|
||||
*i2c_addr = EEPROM_I2C_TARGET_ADDR_ALDEBARAN;
|
||||
control->i2c_address = EEPROM_I2C_MADDR_ALDEBARAN;
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -154,8 +153,9 @@ static int __update_table_header(struct amdgpu_ras_eeprom_control *control,
|
||||
|
||||
/* i2c may be unstable in gpu reset */
|
||||
down_read(&adev->reset_sem);
|
||||
ret = amdgpu_eeprom_xfer(&adev->pm.smu_i2c, control->i2c_address,
|
||||
EEPROM_HDR_START, buff, EEPROM_TABLE_HEADER_SIZE, false);
|
||||
ret = amdgpu_eeprom_xfer(&adev->pm.smu_i2c,
|
||||
control->i2c_address + EEPROM_HDR_START,
|
||||
buff, EEPROM_TABLE_HEADER_SIZE, false);
|
||||
up_read(&adev->reset_sem);
|
||||
|
||||
if (ret < 1)
|
||||
@ -277,7 +277,7 @@ int amdgpu_ras_eeprom_reset_table(struct amdgpu_ras_eeprom_control *control)
|
||||
}
|
||||
|
||||
int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control,
|
||||
bool *exceed_err_limit)
|
||||
bool *exceed_err_limit)
|
||||
{
|
||||
int ret = 0;
|
||||
struct amdgpu_device *adev = to_amdgpu_device(control);
|
||||
@ -294,14 +294,15 @@ int amdgpu_ras_eeprom_init(struct amdgpu_ras_eeprom_control *control,
|
||||
if (!adev->pm.smu_i2c.algo)
|
||||
return -ENOENT;
|
||||
|
||||
if (!__get_eeprom_i2c_addr(adev, &control->i2c_address))
|
||||
if (!__get_eeprom_i2c_addr(adev, control))
|
||||
return -EINVAL;
|
||||
|
||||
mutex_init(&control->tbl_mutex);
|
||||
|
||||
/* Read/Create table header from EEPROM address 0 */
|
||||
ret = amdgpu_eeprom_xfer(&adev->pm.smu_i2c, control->i2c_address,
|
||||
EEPROM_HDR_START, buff, EEPROM_TABLE_HEADER_SIZE, true);
|
||||
ret = amdgpu_eeprom_xfer(&adev->pm.smu_i2c,
|
||||
control->i2c_address + EEPROM_HDR_START,
|
||||
buff, EEPROM_TABLE_HEADER_SIZE, true);
|
||||
if (ret < 1) {
|
||||
DRM_ERROR("Failed to read EEPROM table header, ret:%d", ret);
|
||||
return ret;
|
||||
@ -395,8 +396,6 @@ static void __decode_table_record_from_buff(struct amdgpu_ras_eeprom_control *co
|
||||
|
||||
/*
|
||||
* When reaching end of EEPROM memory jump back to 0 record address
|
||||
* When next record access will go beyond EEPROM page boundary modify bits A17/A8
|
||||
* in I2C selector to go to next page
|
||||
*/
|
||||
static uint32_t __correct_eeprom_dest_address(uint32_t curr_address)
|
||||
{
|
||||
@ -409,20 +408,6 @@ static uint32_t __correct_eeprom_dest_address(uint32_t curr_address)
|
||||
return EEPROM_RECORD_START;
|
||||
}
|
||||
|
||||
/*
|
||||
* To check if we overflow page boundary compare next address with
|
||||
* current and see if bits 17/8 of the EEPROM address will change
|
||||
* If they do start from the next 256b page
|
||||
*
|
||||
* https://www.st.com/resource/en/datasheet/m24m02-dr.pdf sec. 5.1.2
|
||||
*/
|
||||
if ((curr_address & EEPROM_ADDR_MSB_MASK) != (next_address & EEPROM_ADDR_MSB_MASK)) {
|
||||
DRM_DEBUG_DRIVER("Reached end of EEPROM memory page, jumping to next: %lx",
|
||||
(next_address & EEPROM_ADDR_MSB_MASK));
|
||||
|
||||
return (next_address & EEPROM_ADDR_MSB_MASK);
|
||||
}
|
||||
|
||||
return curr_address;
|
||||
}
|
||||
|
||||
@ -452,22 +437,20 @@ bool amdgpu_ras_eeprom_check_err_threshold(struct amdgpu_device *adev)
|
||||
}
|
||||
|
||||
int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control,
|
||||
struct eeprom_table_record *records,
|
||||
bool write,
|
||||
int num)
|
||||
struct eeprom_table_record *records,
|
||||
bool write, int num)
|
||||
{
|
||||
int i, ret = 0;
|
||||
unsigned char *buffs, *buff;
|
||||
struct eeprom_table_record *record;
|
||||
struct amdgpu_device *adev = to_amdgpu_device(control);
|
||||
struct amdgpu_ras *ras = amdgpu_ras_get_context(adev);
|
||||
u16 slave_addr;
|
||||
|
||||
if (!__is_ras_eeprom_supported(adev))
|
||||
return 0;
|
||||
|
||||
buffs = kcalloc(num, EEPROM_ADDRESS_SIZE + EEPROM_TABLE_RECORD_SIZE,
|
||||
GFP_KERNEL);
|
||||
GFP_KERNEL);
|
||||
if (!buffs)
|
||||
return -ENOMEM;
|
||||
|
||||
@ -507,22 +490,15 @@ int amdgpu_ras_eeprom_process_recods(struct amdgpu_ras_eeprom_control *control,
|
||||
|
||||
control->next_addr = __correct_eeprom_dest_address(control->next_addr);
|
||||
|
||||
/*
|
||||
* Update bits 16,17 of EEPROM address in I2C address by setting them
|
||||
* to bits 1,2 of Device address byte
|
||||
*/
|
||||
slave_addr = control->i2c_address |
|
||||
((control->next_addr & EEPROM_ADDR_MSB_MASK) >> 15);
|
||||
|
||||
/* EEPROM table content is stored in LE format */
|
||||
if (write)
|
||||
__encode_table_record_to_buff(control, record, buff);
|
||||
|
||||
/* i2c may be unstable in gpu reset */
|
||||
down_read(&adev->reset_sem);
|
||||
ret = amdgpu_eeprom_xfer(&adev->pm.smu_i2c, slave_addr,
|
||||
control->next_addr, buff,
|
||||
EEPROM_TABLE_RECORD_SIZE, write ? false : true);
|
||||
ret = amdgpu_eeprom_xfer(&adev->pm.smu_i2c,
|
||||
control->i2c_address + control->next_addr,
|
||||
buff, EEPROM_TABLE_RECORD_SIZE, !write);
|
||||
up_read(&adev->reset_sem);
|
||||
|
||||
if (ret < 1) {
|
||||
|
@ -44,11 +44,11 @@ struct amdgpu_ras_eeprom_table_header {
|
||||
|
||||
struct amdgpu_ras_eeprom_control {
|
||||
struct amdgpu_ras_eeprom_table_header tbl_hdr;
|
||||
u32 i2c_address; /* Base I2C 19-bit memory address */
|
||||
uint32_t next_addr;
|
||||
unsigned int num_recs;
|
||||
struct mutex tbl_mutex;
|
||||
uint32_t tbl_byte_sum;
|
||||
uint16_t i2c_address; // 8-bit represented address
|
||||
};
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user