Commit ccdfbfec authored by Luben Tuikov's avatar Luben Tuikov Committed by Alex Deucher
Browse files

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: default avatarLuben Tuikov <luben.tuikov@amd.com>
Acked-by: default avatarAlexander Deucher <Alexander.Deucher@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 025a64a5
Loading
Loading
Loading
Loading
+9 −10
Original line number Diff line number Diff line
@@ -29,7 +29,7 @@
#include "amdgpu_fru_eeprom.h"
#include "amdgpu_eeprom.h"

#define I2C_PRODUCT_INFO_ADDR		0x56
#define FRU_EEPROM_MADDR        0x60000
#define I2C_PRODUCT_INFO_OFFSET 0xC0

static bool is_fru_eeprom_supported(struct amdgpu_device *adev)
@@ -66,8 +66,7 @@ static int amdgpu_fru_read_eeprom(struct amdgpu_device *adev, uint32_t addrptr,
{
	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);
+29 −53
Original line number Diff line number Diff line
@@ -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)
@@ -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;
}

@@ -453,15 +438,13 @@ 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)
				     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;
@@ -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) {
+1 −1
Original line number Diff line number Diff line
@@ -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
};

/*