mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-03 18:20:25 +02:00 
			
		
		
		
	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
					
				
					 3 changed files with 39 additions and 64 deletions
				
			
		| 
						 | 
				
			
			@ -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…
	
		Reference in a new issue