All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 1/6] drm/amdgpu: move i2c bus lock out of ras structure
@ 2020-07-21 16:52 Alex Deucher
  2020-07-21 16:52 ` [PATCH 2/6] drm/amdgpu: remove eeprom from the smu i2c handlers Alex Deucher
                   ` (4 more replies)
  0 siblings, 5 replies; 11+ messages in thread
From: Alex Deucher @ 2020-07-21 16:52 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

It's not really ras related.  It's just a lock for the
bus in general.  This removes the ras dependency from
the smu i2c bus.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h        |  1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h |  1 -
 drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c     | 10 +++-------
 3 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
index 7f3cd7185650..aa27fe65cdfa 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
@@ -425,6 +425,7 @@ struct amdgpu_pm {
 	u32                     default_sclk;
 	u32                     default_mclk;
 	struct amdgpu_i2c_chan *i2c_bus;
+	bool                    bus_locked;
 	/* internal thermal controller on rv6xx+ */
 	enum amdgpu_int_thermal_type int_thermal_type;
 	struct device	        *int_hwmon_dev;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
index 7e8647a05df7..9e7d640920fb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
@@ -47,7 +47,6 @@ struct amdgpu_ras_eeprom_control {
 	uint32_t next_addr;
 	unsigned int num_recs;
 	struct mutex tbl_mutex;
-	bool bus_locked;
 	uint32_t tbl_byte_sum;
 	uint16_t i2c_address; // 8-bit represented address
 };
diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
index 9bffbab35041..f3d0324c4a7f 100644
--- a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
+++ b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
@@ -32,7 +32,6 @@
 #include "amdgpu_amdkfd.h"
 #include <linux/i2c.h>
 #include <linux/pci.h>
-#include "amdgpu_ras.h"
 
 /* error codes */
 #define I2C_OK                0
@@ -592,14 +591,13 @@ static uint32_t smu_v11_0_i2c_eeprom_write_data(struct i2c_adapter *control,
 static void lock_bus(struct i2c_adapter *i2c, unsigned int flags)
 {
 	struct amdgpu_device *adev = to_amdgpu_device(i2c);
-	struct amdgpu_ras_eeprom_control *control = &adev->psp.ras.ras->eeprom_control;
 
 	if (!smu_v11_0_i2c_bus_lock(i2c)) {
 		DRM_ERROR("Failed to lock the bus from SMU");
 		return;
 	}
 
-	control->bus_locked = true;
+	adev->pm.bus_locked = true;
 }
 
 static int trylock_bus(struct i2c_adapter *i2c, unsigned int flags)
@@ -611,14 +609,13 @@ static int trylock_bus(struct i2c_adapter *i2c, unsigned int flags)
 static void unlock_bus(struct i2c_adapter *i2c, unsigned int flags)
 {
 	struct amdgpu_device *adev = to_amdgpu_device(i2c);
-	struct amdgpu_ras_eeprom_control *control = &adev->psp.ras.ras->eeprom_control;
 
 	if (!smu_v11_0_i2c_bus_unlock(i2c)) {
 		DRM_ERROR("Failed to unlock the bus from SMU");
 		return;
 	}
 
-	control->bus_locked = false;
+	adev->pm.bus_locked = false;
 }
 
 static const struct i2c_lock_operations smu_v11_0_i2c_i2c_lock_ops = {
@@ -632,9 +629,8 @@ static int smu_v11_0_i2c_eeprom_i2c_xfer(struct i2c_adapter *i2c_adap,
 {
 	int i, ret;
 	struct amdgpu_device *adev = to_amdgpu_device(i2c_adap);
-	struct amdgpu_ras_eeprom_control *control = &adev->psp.ras.ras->eeprom_control;
 
-	if (!control->bus_locked) {
+	if (!adev->pm.bus_locked) {
 		DRM_ERROR("I2C bus unlocked, stopping transaction!");
 		return -EIO;
 	}
-- 
2.25.4

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 2/6] drm/amdgpu: remove eeprom from the smu i2c handlers
  2020-07-21 16:52 [PATCH 1/6] drm/amdgpu: move i2c bus lock out of ras structure Alex Deucher
@ 2020-07-21 16:52 ` Alex Deucher
  2020-07-21 16:52 ` [PATCH 3/6] drm/amdgpu/vega20: enable the smu i2c bus for all boards Alex Deucher
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 11+ messages in thread
From: Alex Deucher @ 2020-07-21 16:52 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

The driver uses it for EEPROM access, but it's just an i2c bus.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c    | 52 +++++++++----------
 drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.h    |  4 +-
 .../drm/amd/powerplay/smumgr/vega20_smumgr.c  |  4 +-
 3 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
index f3d0324c4a7f..d55bf64770c4 100644
--- a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
+++ b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
@@ -536,12 +536,12 @@ static bool smu_v11_0_i2c_bus_unlock(struct i2c_adapter *control)
 	return false;
 }
 
-/***************************** EEPROM I2C GLUE ****************************/
+/***************************** I2C GLUE ****************************/
 
-static uint32_t smu_v11_0_i2c_eeprom_read_data(struct i2c_adapter *control,
-					       uint8_t address,
-					       uint8_t *data,
-					       uint32_t numbytes)
+static uint32_t smu_v11_0_i2c_read_data(struct i2c_adapter *control,
+					uint8_t address,
+					uint8_t *data,
+					uint32_t numbytes)
 {
 	uint32_t  ret = 0;
 
@@ -561,10 +561,10 @@ static uint32_t smu_v11_0_i2c_eeprom_read_data(struct i2c_adapter *control,
 	return ret;
 }
 
-static uint32_t smu_v11_0_i2c_eeprom_write_data(struct i2c_adapter *control,
-						uint8_t address,
-						uint8_t *data,
-						uint32_t numbytes)
+static uint32_t smu_v11_0_i2c_write_data(struct i2c_adapter *control,
+					 uint8_t address,
+					 uint8_t *data,
+					 uint32_t numbytes)
 {
 	uint32_t  ret;
 
@@ -624,7 +624,7 @@ static const struct i2c_lock_operations smu_v11_0_i2c_i2c_lock_ops = {
 	.unlock_bus = unlock_bus,
 };
 
-static int smu_v11_0_i2c_eeprom_i2c_xfer(struct i2c_adapter *i2c_adap,
+static int smu_v11_0_i2c_xfer(struct i2c_adapter *i2c_adap,
 			      struct i2c_msg *msgs, int num)
 {
 	int i, ret;
@@ -639,13 +639,13 @@ static int smu_v11_0_i2c_eeprom_i2c_xfer(struct i2c_adapter *i2c_adap,
 
 	for (i = 0; i < num; i++) {
 		if (msgs[i].flags & I2C_M_RD)
-			ret = smu_v11_0_i2c_eeprom_read_data(i2c_adap,
-							(uint8_t)msgs[i].addr,
-							msgs[i].buf, msgs[i].len);
+			ret = smu_v11_0_i2c_read_data(i2c_adap,
+						      (uint8_t)msgs[i].addr,
+						      msgs[i].buf, msgs[i].len);
 		else
-			ret = smu_v11_0_i2c_eeprom_write_data(i2c_adap,
-							 (uint8_t)msgs[i].addr,
-							 msgs[i].buf, msgs[i].len);
+			ret = smu_v11_0_i2c_write_data(i2c_adap,
+						       (uint8_t)msgs[i].addr,
+						       msgs[i].buf, msgs[i].len);
 
 		if (ret != I2C_OK) {
 			num = -EIO;
@@ -657,18 +657,18 @@ static int smu_v11_0_i2c_eeprom_i2c_xfer(struct i2c_adapter *i2c_adap,
 	return num;
 }
 
-static u32 smu_v11_0_i2c_eeprom_i2c_func(struct i2c_adapter *adap)
+static u32 smu_v11_0_i2c_func(struct i2c_adapter *adap)
 {
 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
 
-static const struct i2c_algorithm smu_v11_0_i2c_eeprom_i2c_algo = {
-	.master_xfer = smu_v11_0_i2c_eeprom_i2c_xfer,
-	.functionality = smu_v11_0_i2c_eeprom_i2c_func,
+static const struct i2c_algorithm smu_v11_0_i2c_algo = {
+	.master_xfer = smu_v11_0_i2c_xfer,
+	.functionality = smu_v11_0_i2c_func,
 };
 
-int smu_v11_0_i2c_eeprom_control_init(struct i2c_adapter *control)
+int smu_v11_0_i2c_control_init(struct i2c_adapter *control)
 {
 	struct amdgpu_device *adev = to_amdgpu_device(control);
 	int res;
@@ -676,8 +676,8 @@ int smu_v11_0_i2c_eeprom_control_init(struct i2c_adapter *control)
 	control->owner = THIS_MODULE;
 	control->class = I2C_CLASS_SPD;
 	control->dev.parent = &adev->pdev->dev;
-	control->algo = &smu_v11_0_i2c_eeprom_i2c_algo;
-	snprintf(control->name, sizeof(control->name), "AMDGPU EEPROM");
+	control->algo = &smu_v11_0_i2c_algo;
+	snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
 	control->lock_ops = &smu_v11_0_i2c_i2c_lock_ops;
 
 	res = i2c_add_adapter(control);
@@ -687,7 +687,7 @@ int smu_v11_0_i2c_eeprom_control_init(struct i2c_adapter *control)
 	return res;
 }
 
-void smu_v11_0_i2c_eeprom_control_fini(struct i2c_adapter *control)
+void smu_v11_0_i2c_control_fini(struct i2c_adapter *control)
 {
 	i2c_del_adapter(control);
 }
@@ -715,9 +715,9 @@ bool smu_v11_0_i2c_test_bus(struct i2c_adapter *control)
 	smu_v11_0_i2c_init(control);
 
 	/* Write 0xde to address 0x0000 on the EEPROM */
-	ret = smu_v11_0_i2c_eeprom_write_data(control, I2C_TARGET_ADDR, data, 6);
+	ret = smu_v11_0_i2c_write_data(control, I2C_TARGET_ADDR, data, 6);
 
-	ret = smu_v11_0_i2c_eeprom_read_data(control, I2C_TARGET_ADDR, data, 6);
+	ret = smu_v11_0_i2c_read_data(control, I2C_TARGET_ADDR, data, 6);
 
 	smu_v11_0_i2c_fini(control);
 
diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.h b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.h
index 973f28d68e70..44467c05f642 100644
--- a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.h
+++ b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.h
@@ -28,7 +28,7 @@
 
 struct i2c_adapter;
 
-int smu_v11_0_i2c_eeprom_control_init(struct i2c_adapter *control);
-void smu_v11_0_i2c_eeprom_control_fini(struct i2c_adapter *control);
+int smu_v11_0_i2c_control_init(struct i2c_adapter *control);
+void smu_v11_0_i2c_control_fini(struct i2c_adapter *control);
 
 #endif
diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.c
index c2e0fbbccf56..d1b7955bb4c7 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.c
@@ -523,7 +523,7 @@ static int vega20_smu_init(struct pp_hwmgr *hwmgr)
 	priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].size = sizeof(DpmActivityMonitorCoeffInt_t);
 
 	if (adev->psp.ras.ras) {
-		ret = smu_v11_0_i2c_eeprom_control_init(&adev->pm.smu_i2c);
+		ret = smu_v11_0_i2c_control_init(&adev->pm.smu_i2c);
 		if (ret)
 			goto err4;
 	}
@@ -563,7 +563,7 @@ static int vega20_smu_fini(struct pp_hwmgr *hwmgr)
 	struct amdgpu_device *adev = hwmgr->adev;
 
 	if (adev->psp.ras.ras)
-		smu_v11_0_i2c_eeprom_control_fini(&adev->pm.smu_i2c);
+		smu_v11_0_i2c_control_fini(&adev->pm.smu_i2c);
 
 	if (priv) {
 		amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle,
-- 
2.25.4

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 3/6] drm/amdgpu/vega20: enable the smu i2c bus for all boards
  2020-07-21 16:52 [PATCH 1/6] drm/amdgpu: move i2c bus lock out of ras structure Alex Deucher
  2020-07-21 16:52 ` [PATCH 2/6] drm/amdgpu: remove eeprom from the smu i2c handlers Alex Deucher
@ 2020-07-21 16:52 ` Alex Deucher
  2020-07-21 16:52 ` [PATCH 4/6] drm/amdgpu/swSMU: remove eeprom from the smu i2c handlers Alex Deucher
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 11+ messages in thread
From: Alex Deucher @ 2020-07-21 16:52 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

There is no longer a ras dependency so it's safe to expose
on all boards.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.c | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.c
index d1b7955bb4c7..cf43629d29d2 100644
--- a/drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.c
+++ b/drivers/gpu/drm/amd/powerplay/smumgr/vega20_smumgr.c
@@ -522,11 +522,9 @@ static int vega20_smu_init(struct pp_hwmgr *hwmgr)
 	priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].version = 0x01;
 	priv->smu_tables.entry[TABLE_ACTIVITY_MONITOR_COEFF].size = sizeof(DpmActivityMonitorCoeffInt_t);
 
-	if (adev->psp.ras.ras) {
-		ret = smu_v11_0_i2c_control_init(&adev->pm.smu_i2c);
-		if (ret)
-			goto err4;
-	}
+	ret = smu_v11_0_i2c_control_init(&adev->pm.smu_i2c);
+	if (ret)
+		goto err4;
 
 	return 0;
 
@@ -562,8 +560,7 @@ static int vega20_smu_fini(struct pp_hwmgr *hwmgr)
 			(struct vega20_smumgr *)(hwmgr->smu_backend);
 	struct amdgpu_device *adev = hwmgr->adev;
 
-	if (adev->psp.ras.ras)
-		smu_v11_0_i2c_control_fini(&adev->pm.smu_i2c);
+	smu_v11_0_i2c_control_fini(&adev->pm.smu_i2c);
 
 	if (priv) {
 		amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle,
-- 
2.25.4

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 4/6] drm/amdgpu/swSMU: remove eeprom from the smu i2c handlers
  2020-07-21 16:52 [PATCH 1/6] drm/amdgpu: move i2c bus lock out of ras structure Alex Deucher
  2020-07-21 16:52 ` [PATCH 2/6] drm/amdgpu: remove eeprom from the smu i2c handlers Alex Deucher
  2020-07-21 16:52 ` [PATCH 3/6] drm/amdgpu/vega20: enable the smu i2c bus for all boards Alex Deucher
@ 2020-07-21 16:52 ` Alex Deucher
  2020-07-21 16:52 ` [PATCH 5/6] drm/amdgpu/navi1x: add SMU i2c support Alex Deucher
  2020-07-21 16:52 ` [PATCH 6/6] drm/amdgpu/sienna_cichlid: " Alex Deucher
  4 siblings, 0 replies; 11+ messages in thread
From: Alex Deucher @ 2020-07-21 16:52 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

The driver uses it for EEPROM access, but it's just an i2c bus.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/powerplay/arcturus_ppt.c | 60 ++++++++++----------
 1 file changed, 30 insertions(+), 30 deletions(-)

diff --git a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c
index 56dc20a617fd..7ab606734dcf 100644
--- a/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/powerplay/arcturus_ppt.c
@@ -1947,7 +1947,7 @@ static int arcturus_dpm_set_vcn_enable(struct smu_context *smu, bool enable)
 	return ret;
 }
 
-static void arcturus_fill_eeprom_i2c_req(SwI2cRequest_t  *req, bool write,
+static void arcturus_fill_i2c_req(SwI2cRequest_t  *req, bool write,
 				  uint8_t address, uint32_t numbytes,
 				  uint8_t *data)
 {
@@ -1981,7 +1981,7 @@ static void arcturus_fill_eeprom_i2c_req(SwI2cRequest_t  *req, bool write,
 	}
 }
 
-static int arcturus_i2c_eeprom_read_data(struct i2c_adapter *control,
+static int arcturus_i2c_read_data(struct i2c_adapter *control,
 					       uint8_t address,
 					       uint8_t *data,
 					       uint32_t numbytes)
@@ -1993,7 +1993,7 @@ static int arcturus_i2c_eeprom_read_data(struct i2c_adapter *control,
 	struct smu_table *table = &smu_table->driver_table;
 
 	memset(&req, 0, sizeof(req));
-	arcturus_fill_eeprom_i2c_req(&req, false, address, numbytes, data);
+	arcturus_fill_i2c_req(&req, false, address, numbytes, data);
 
 	mutex_lock(&adev->smu.mutex);
 	/* Now read data starting with that address */
@@ -2008,18 +2008,18 @@ static int arcturus_i2c_eeprom_read_data(struct i2c_adapter *control,
 		for (i = 0; i < numbytes; i++)
 			data[i] = res->SwI2cCmds[i].Data;
 
-		dev_dbg(adev->dev, "arcturus_i2c_eeprom_read_data, address = %x, bytes = %d, data :",
+		dev_dbg(adev->dev, "arcturus_i2c_read_data, address = %x, bytes = %d, data :",
 				  (uint16_t)address, numbytes);
 
 		print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
 			       8, 1, data, numbytes, false);
 	} else
-		dev_err(adev->dev, "arcturus_i2c_eeprom_read_data - error occurred :%x", ret);
+		dev_err(adev->dev, "arcturus_i2c_read_data - error occurred :%x", ret);
 
 	return ret;
 }
 
-static int arcturus_i2c_eeprom_write_data(struct i2c_adapter *control,
+static int arcturus_i2c_write_data(struct i2c_adapter *control,
 						uint8_t address,
 						uint8_t *data,
 						uint32_t numbytes)
@@ -2029,7 +2029,7 @@ static int arcturus_i2c_eeprom_write_data(struct i2c_adapter *control,
 	struct amdgpu_device *adev = to_amdgpu_device(control);
 
 	memset(&req, 0, sizeof(req));
-	arcturus_fill_eeprom_i2c_req(&req, true, address, numbytes, data);
+	arcturus_fill_i2c_req(&req, true, address, numbytes, data);
 
 	mutex_lock(&adev->smu.mutex);
 	ret = smu_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, true);
@@ -2055,7 +2055,7 @@ static int arcturus_i2c_eeprom_write_data(struct i2c_adapter *control,
 	return ret;
 }
 
-static int arcturus_i2c_eeprom_i2c_xfer(struct i2c_adapter *i2c_adap,
+static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap,
 			      struct i2c_msg *msgs, int num)
 {
 	uint32_t  i, j, ret, data_size, data_chunk_size, next_eeprom_addr = 0;
@@ -2078,18 +2078,18 @@ static int arcturus_i2c_eeprom_i2c_xfer(struct i2c_adapter *i2c_adap,
 			data_chunk[1] = (next_eeprom_addr & 0xff);
 
 			if (msgs[i].flags & I2C_M_RD) {
-				ret = arcturus_i2c_eeprom_read_data(i2c_adap,
-								(uint8_t)msgs[i].addr,
-								data_chunk, MAX_SW_I2C_COMMANDS);
+				ret = arcturus_i2c_read_data(i2c_adap,
+							     (uint8_t)msgs[i].addr,
+							     data_chunk, MAX_SW_I2C_COMMANDS);
 
 				memcpy(data_ptr, data_chunk + 2, data_chunk_size);
 			} else {
 
 				memcpy(data_chunk + 2, data_ptr, data_chunk_size);
 
-				ret = arcturus_i2c_eeprom_write_data(i2c_adap,
-								 (uint8_t)msgs[i].addr,
-								 data_chunk, MAX_SW_I2C_COMMANDS);
+				ret = arcturus_i2c_write_data(i2c_adap,
+							      (uint8_t)msgs[i].addr,
+							      data_chunk, MAX_SW_I2C_COMMANDS);
 			}
 
 			if (ret) {
@@ -2106,17 +2106,17 @@ static int arcturus_i2c_eeprom_i2c_xfer(struct i2c_adapter *i2c_adap,
 			data_chunk[1] = (next_eeprom_addr & 0xff);
 
 			if (msgs[i].flags & I2C_M_RD) {
-				ret = arcturus_i2c_eeprom_read_data(i2c_adap,
-								(uint8_t)msgs[i].addr,
-								data_chunk, (data_size % data_chunk_size) + 2);
+				ret = arcturus_i2c_read_data(i2c_adap,
+							     (uint8_t)msgs[i].addr,
+							     data_chunk, (data_size % data_chunk_size) + 2);
 
 				memcpy(data_ptr, data_chunk + 2, data_size % data_chunk_size);
 			} else {
 				memcpy(data_chunk + 2, data_ptr, data_size % data_chunk_size);
 
-				ret = arcturus_i2c_eeprom_write_data(i2c_adap,
-								 (uint8_t)msgs[i].addr,
-								 data_chunk, (data_size % data_chunk_size) + 2);
+				ret = arcturus_i2c_write_data(i2c_adap,
+							      (uint8_t)msgs[i].addr,
+							      data_chunk, (data_size % data_chunk_size) + 2);
 			}
 
 			if (ret) {
@@ -2130,15 +2130,15 @@ static int arcturus_i2c_eeprom_i2c_xfer(struct i2c_adapter *i2c_adap,
 	return num;
 }
 
-static u32 arcturus_i2c_eeprom_i2c_func(struct i2c_adapter *adap)
+static u32 arcturus_i2c_func(struct i2c_adapter *adap)
 {
 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
 
-static const struct i2c_algorithm arcturus_i2c_eeprom_i2c_algo = {
-	.master_xfer = arcturus_i2c_eeprom_i2c_xfer,
-	.functionality = arcturus_i2c_eeprom_i2c_func,
+static const struct i2c_algorithm arcturus_i2c_algo = {
+	.master_xfer = arcturus_i2c_xfer,
+	.functionality = arcturus_i2c_func,
 };
 
 static bool arcturus_i2c_adapter_is_added(struct i2c_adapter *control)
@@ -2148,7 +2148,7 @@ static bool arcturus_i2c_adapter_is_added(struct i2c_adapter *control)
 	return control->dev.parent == &adev->pdev->dev;
 }
 
-static int arcturus_i2c_eeprom_control_init(struct smu_context *smu, struct i2c_adapter *control)
+static int arcturus_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control)
 {
 	struct amdgpu_device *adev = to_amdgpu_device(control);
 	int res;
@@ -2160,8 +2160,8 @@ static int arcturus_i2c_eeprom_control_init(struct smu_context *smu, struct i2c_
 	control->owner = THIS_MODULE;
 	control->class = I2C_CLASS_SPD;
 	control->dev.parent = &adev->pdev->dev;
-	control->algo = &arcturus_i2c_eeprom_i2c_algo;
-	snprintf(control->name, sizeof(control->name), "AMDGPU EEPROM");
+	control->algo = &arcturus_i2c_algo;
+	snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
 
 	res = i2c_add_adapter(control);
 	if (res)
@@ -2170,7 +2170,7 @@ static int arcturus_i2c_eeprom_control_init(struct smu_context *smu, struct i2c_
 	return res;
 }
 
-static void arcturus_i2c_eeprom_control_fini(struct smu_context *smu, struct i2c_adapter *control)
+static void arcturus_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control)
 {
 	if (!arcturus_i2c_adapter_is_added(control))
 		return;
@@ -2346,8 +2346,8 @@ static const struct pptable_funcs arcturus_ppt_funcs = {
 	.get_power_limit = arcturus_get_power_limit,
 	.is_dpm_running = arcturus_is_dpm_running,
 	.dpm_set_vcn_enable = arcturus_dpm_set_vcn_enable,
-	.i2c_eeprom_init = arcturus_i2c_eeprom_control_init,
-	.i2c_eeprom_fini = arcturus_i2c_eeprom_control_fini,
+	.i2c_eeprom_init = arcturus_i2c_control_init,
+	.i2c_eeprom_fini = arcturus_i2c_control_fini,
 	.get_unique_id = arcturus_get_unique_id,
 	.init_microcode = smu_v11_0_init_microcode,
 	.load_microcode = smu_v11_0_load_microcode,
-- 
2.25.4

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 5/6] drm/amdgpu/navi1x: add SMU i2c support
  2020-07-21 16:52 [PATCH 1/6] drm/amdgpu: move i2c bus lock out of ras structure Alex Deucher
                   ` (2 preceding siblings ...)
  2020-07-21 16:52 ` [PATCH 4/6] drm/amdgpu/swSMU: remove eeprom from the smu i2c handlers Alex Deucher
@ 2020-07-21 16:52 ` Alex Deucher
  2020-07-21 16:56   ` Deucher, Alexander
  2020-07-21 16:52 ` [PATCH 6/6] drm/amdgpu/sienna_cichlid: " Alex Deucher
  4 siblings, 1 reply; 11+ messages in thread
From: Alex Deucher @ 2020-07-21 16:52 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Enable SMU i2c bus access for navi1x asics.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
index ead135f39c7e..56267e6c600e 100644
--- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
@@ -23,6 +23,7 @@
 
 #include <linux/firmware.h>
 #include <linux/pci.h>
+#include <linux/i2c.h>
 #include "amdgpu.h"
 #include "amdgpu_smu.h"
 #include "smu_internal.h"
@@ -52,6 +53,8 @@
 #undef pr_info
 #undef pr_debug
 
+#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
+
 #define FEATURE_MASK(feature) (1ULL << feature)
 #define SMC_DPM_FEATURE ( \
 	FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) | \
-- 
2.25.4

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 6/6] drm/amdgpu/sienna_cichlid: add SMU i2c support
  2020-07-21 16:52 [PATCH 1/6] drm/amdgpu: move i2c bus lock out of ras structure Alex Deucher
                   ` (3 preceding siblings ...)
  2020-07-21 16:52 ` [PATCH 5/6] drm/amdgpu/navi1x: add SMU i2c support Alex Deucher
@ 2020-07-21 16:52 ` Alex Deucher
  2020-07-21 17:01   ` Andrey Grodzovsky
  2020-07-21 18:01   ` Andrey Grodzovsky
  4 siblings, 2 replies; 11+ messages in thread
From: Alex Deucher @ 2020-07-21 16:52 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher

Enable SMU i2c bus access for sienna_cichlid asics.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 .../drm/amd/powerplay/sienna_cichlid_ppt.c    | 239 ++++++++++++++++++
 1 file changed, 239 insertions(+)

diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c
index 5faef41b63a3..e1857fbb0a6f 100644
--- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c
+++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c
@@ -23,6 +23,7 @@
 
 #include <linux/firmware.h>
 #include <linux/pci.h>
+#include <linux/i2c.h>
 #include "amdgpu.h"
 #include "amdgpu_smu.h"
 #include "smu_internal.h"
@@ -52,6 +53,8 @@
 #undef pr_info
 #undef pr_debug
 
+#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
+
 #define FEATURE_MASK(feature) (1ULL << feature)
 #define SMC_DPM_FEATURE ( \
 	FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) | \
@@ -455,6 +458,8 @@ static int sienna_cichlid_tables_init(struct smu_context *smu, struct smu_table
 		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 	SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
 		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
+	SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t),
+		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 	SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t),
 		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
 	SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE,
@@ -2487,6 +2492,238 @@ static void sienna_cichlid_dump_pptable(struct smu_context *smu)
 	dev_info(smu->adev->dev, "MmHubPadding[7] = 0x%x\n", pptable->MmHubPadding[7]);
 }
 
+static void sienna_cichlid_fill_i2c_req(SwI2cRequest_t  *req, bool write,
+				  uint8_t address, uint32_t numbytes,
+				  uint8_t *data)
+{
+	int i;
+
+	BUG_ON(numbytes > MAX_SW_I2C_COMMANDS);
+
+	req->I2CcontrollerPort = 0;
+	req->I2CSpeed = 2;
+	req->SlaveAddress = address;
+	req->NumCmds = numbytes;
+
+	for (i = 0; i < numbytes; i++) {
+		SwI2cCmd_t *cmd =  &req->SwI2cCmds[i];
+
+		/* First 2 bytes are always write for lower 2b EEPROM address */
+		if (i < 2)
+			cmd->CmdConfig = CMDCONFIG_READWRITE_MASK;
+		else
+			cmd->CmdConfig = write ? CMDCONFIG_READWRITE_MASK : 0;
+
+
+		/* Add RESTART for read  after address filled */
+		cmd->CmdConfig |= (i == 2 && !write) ? CMDCONFIG_RESTART_MASK : 0;
+
+		/* Add STOP in the end */
+		cmd->CmdConfig |= (i == (numbytes - 1)) ? CMDCONFIG_STOP_MASK : 0;
+
+		/* Fill with data regardless if read or write to simplify code */
+		cmd->ReadWriteData = data[i];
+	}
+}
+
+static int sienna_cichlid_i2c_read_data(struct i2c_adapter *control,
+					       uint8_t address,
+					       uint8_t *data,
+					       uint32_t numbytes)
+{
+	uint32_t  i, ret = 0;
+	SwI2cRequest_t req;
+	struct amdgpu_device *adev = to_amdgpu_device(control);
+	struct smu_table_context *smu_table = &adev->smu.smu_table;
+	struct smu_table *table = &smu_table->driver_table;
+
+	memset(&req, 0, sizeof(req));
+	sienna_cichlid_fill_i2c_req(&req, false, address, numbytes, data);
+
+	mutex_lock(&adev->smu.mutex);
+	/* Now read data starting with that address */
+	ret = smu_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req,
+					true);
+	mutex_unlock(&adev->smu.mutex);
+
+	if (!ret) {
+		SwI2cRequest_t *res = (SwI2cRequest_t *)table->cpu_addr;
+
+		/* Assume SMU  fills res.SwI2cCmds[i].Data with read bytes */
+		for (i = 0; i < numbytes; i++)
+			data[i] = res->SwI2cCmds[i].ReadWriteData;
+
+		dev_dbg(adev->dev, "sienna_cichlid_i2c_read_data, address = %x, bytes = %d, data :",
+				  (uint16_t)address, numbytes);
+
+		print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
+			       8, 1, data, numbytes, false);
+	} else
+		dev_err(adev->dev, "sienna_cichlid_i2c_read_data - error occurred :%x", ret);
+
+	return ret;
+}
+
+static int sienna_cichlid_i2c_write_data(struct i2c_adapter *control,
+						uint8_t address,
+						uint8_t *data,
+						uint32_t numbytes)
+{
+	uint32_t ret;
+	SwI2cRequest_t req;
+	struct amdgpu_device *adev = to_amdgpu_device(control);
+
+	memset(&req, 0, sizeof(req));
+	sienna_cichlid_fill_i2c_req(&req, true, address, numbytes, data);
+
+	mutex_lock(&adev->smu.mutex);
+	ret = smu_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, true);
+	mutex_unlock(&adev->smu.mutex);
+
+	if (!ret) {
+		dev_dbg(adev->dev, "sienna_cichlid_i2c_write(), address = %x, bytes = %d , data: ",
+					 (uint16_t)address, numbytes);
+
+		print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
+			       8, 1, data, numbytes, false);
+		/*
+		 * According to EEPROM spec there is a MAX of 10 ms required for
+		 * EEPROM to flush internal RX buffer after STOP was issued at the
+		 * end of write transaction. During this time the EEPROM will not be
+		 * responsive to any more commands - so wait a bit more.
+		 */
+		msleep(10);
+
+	} else
+		dev_err(adev->dev, "sienna_cichlid_i2c_write- error occurred :%x", ret);
+
+	return ret;
+}
+
+static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap,
+			      struct i2c_msg *msgs, int num)
+{
+	uint32_t  i, j, ret, data_size, data_chunk_size, next_eeprom_addr = 0;
+	uint8_t *data_ptr, data_chunk[MAX_SW_I2C_COMMANDS] = { 0 };
+
+	for (i = 0; i < num; i++) {
+		/*
+		 * SMU interface allows at most MAX_SW_I2C_COMMANDS bytes of data at
+		 * once and hence the data needs to be spliced into chunks and sent each
+		 * chunk separately
+		 */
+		data_size = msgs[i].len - 2;
+		data_chunk_size = MAX_SW_I2C_COMMANDS - 2;
+		next_eeprom_addr = (msgs[i].buf[0] << 8 & 0xff00) | (msgs[i].buf[1] & 0xff);
+		data_ptr = msgs[i].buf + 2;
+
+		for (j = 0; j < data_size / data_chunk_size; j++) {
+			/* Insert the EEPROM dest addess, bits 0-15 */
+			data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
+			data_chunk[1] = (next_eeprom_addr & 0xff);
+
+			if (msgs[i].flags & I2C_M_RD) {
+				ret = sienna_cichlid_i2c_read_data(i2c_adap,
+							     (uint8_t)msgs[i].addr,
+							     data_chunk, MAX_SW_I2C_COMMANDS);
+
+				memcpy(data_ptr, data_chunk + 2, data_chunk_size);
+			} else {
+
+				memcpy(data_chunk + 2, data_ptr, data_chunk_size);
+
+				ret = sienna_cichlid_i2c_write_data(i2c_adap,
+							      (uint8_t)msgs[i].addr,
+							      data_chunk, MAX_SW_I2C_COMMANDS);
+			}
+
+			if (ret) {
+				num = -EIO;
+				goto fail;
+			}
+
+			next_eeprom_addr += data_chunk_size;
+			data_ptr += data_chunk_size;
+		}
+
+		if (data_size % data_chunk_size) {
+			data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
+			data_chunk[1] = (next_eeprom_addr & 0xff);
+
+			if (msgs[i].flags & I2C_M_RD) {
+				ret = sienna_cichlid_i2c_read_data(i2c_adap,
+							     (uint8_t)msgs[i].addr,
+							     data_chunk, (data_size % data_chunk_size) + 2);
+
+				memcpy(data_ptr, data_chunk + 2, data_size % data_chunk_size);
+			} else {
+				memcpy(data_chunk + 2, data_ptr, data_size % data_chunk_size);
+
+				ret = sienna_cichlid_i2c_write_data(i2c_adap,
+							      (uint8_t)msgs[i].addr,
+							      data_chunk, (data_size % data_chunk_size) + 2);
+			}
+
+			if (ret) {
+				num = -EIO;
+				goto fail;
+			}
+		}
+	}
+
+fail:
+	return num;
+}
+
+static u32 sienna_cichlid_i2c_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+
+static const struct i2c_algorithm sienna_cichlid_i2c_algo = {
+	.master_xfer = sienna_cichlid_i2c_xfer,
+	.functionality = sienna_cichlid_i2c_func,
+};
+
+static bool sienna_cichlid_i2c_adapter_is_added(struct i2c_adapter *control)
+{
+	struct amdgpu_device *adev = to_amdgpu_device(control);
+
+	return control->dev.parent == &adev->pdev->dev;
+}
+
+static int sienna_cichlid_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control)
+{
+	struct amdgpu_device *adev = to_amdgpu_device(control);
+	int res;
+
+	/* smu_i2c_eeprom_init may be called twice in sriov */
+	if (sienna_cichlid_i2c_adapter_is_added(control))
+		return 0;
+
+	control->owner = THIS_MODULE;
+	control->class = I2C_CLASS_SPD;
+	control->dev.parent = &adev->pdev->dev;
+	control->algo = &sienna_cichlid_i2c_algo;
+	snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
+
+	res = i2c_add_adapter(control);
+	if (res)
+		DRM_ERROR("Failed to register hw i2c, err: %d\n", res);
+
+	return res;
+}
+
+static void sienna_cichlid_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control)
+{
+	if (!sienna_cichlid_i2c_adapter_is_added(control))
+		return;
+
+	i2c_del_adapter(control);
+}
+
+
 static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
 	.tables_init = sienna_cichlid_tables_init,
 	.alloc_dpm_context = sienna_cichlid_allocate_dpm_context,
@@ -2500,6 +2737,8 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
 	.set_default_dpm_table = sienna_cichlid_set_default_dpm_table,
 	.dpm_set_vcn_enable = sienna_cichlid_dpm_set_vcn_enable,
 	.dpm_set_jpeg_enable = sienna_cichlid_dpm_set_jpeg_enable,
+	.i2c_eeprom_init = sienna_cichlid_i2c_control_init,
+	.i2c_eeprom_fini = sienna_cichlid_i2c_control_fini,
 	.print_clk_levels = sienna_cichlid_print_clk_levels,
 	.force_clk_levels = sienna_cichlid_force_clk_levels,
 	.populate_umd_state_clk = sienna_cichlid_populate_umd_state_clk,
-- 
2.25.4

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH 5/6] drm/amdgpu/navi1x: add SMU i2c support
  2020-07-21 16:52 ` [PATCH 5/6] drm/amdgpu/navi1x: add SMU i2c support Alex Deucher
@ 2020-07-21 16:56   ` Deucher, Alexander
  0 siblings, 0 replies; 11+ messages in thread
From: Deucher, Alexander @ 2020-07-21 16:56 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx


[-- Attachment #1.1: Type: text/plain, Size: 1314 bytes --]

[AMD Official Use Only - Internal Distribution Only]

Ignore this.  Sent out the wrong version.

Alex
________________________________
From: Alex Deucher <alexdeucher@gmail.com>
Sent: Tuesday, July 21, 2020 12:52 PM
To: amd-gfx@lists.freedesktop.org <amd-gfx@lists.freedesktop.org>
Cc: Deucher, Alexander <Alexander.Deucher@amd.com>
Subject: [PATCH 5/6] drm/amdgpu/navi1x: add SMU i2c support

Enable SMU i2c bus access for navi1x asics.

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/powerplay/navi10_ppt.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
index ead135f39c7e..56267e6c600e 100644
--- a/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/powerplay/navi10_ppt.c
@@ -23,6 +23,7 @@

 #include <linux/firmware.h>
 #include <linux/pci.h>
+#include <linux/i2c.h>
 #include "amdgpu.h"
 #include "amdgpu_smu.h"
 #include "smu_internal.h"
@@ -52,6 +53,8 @@
 #undef pr_info
 #undef pr_debug

+#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
+
 #define FEATURE_MASK(feature) (1ULL << feature)
 #define SMC_DPM_FEATURE ( \
         FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) | \
--
2.25.4


[-- Attachment #1.2: Type: text/html, Size: 2731 bytes --]

[-- Attachment #2: Type: text/plain, Size: 154 bytes --]

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH 6/6] drm/amdgpu/sienna_cichlid: add SMU i2c support
  2020-07-21 16:52 ` [PATCH 6/6] drm/amdgpu/sienna_cichlid: " Alex Deucher
@ 2020-07-21 17:01   ` Andrey Grodzovsky
  2020-07-21 17:02     ` Deucher, Alexander
  2020-07-21 18:01   ` Andrey Grodzovsky
  1 sibling, 1 reply; 11+ messages in thread
From: Andrey Grodzovsky @ 2020-07-21 17:01 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx; +Cc: Alex Deucher

Looks like same code as arcturus - should we make it common helper code and 
reuse in both ?

Andrey

On 7/21/20 12:52 PM, Alex Deucher wrote:
> Enable SMU i2c bus access for sienna_cichlid asics.
>
> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
> ---
>   .../drm/amd/powerplay/sienna_cichlid_ppt.c    | 239 ++++++++++++++++++
>   1 file changed, 239 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c
> index 5faef41b63a3..e1857fbb0a6f 100644
> --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c
> +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c
> @@ -23,6 +23,7 @@
>   
>   #include <linux/firmware.h>
>   #include <linux/pci.h>
> +#include <linux/i2c.h>
>   #include "amdgpu.h"
>   #include "amdgpu_smu.h"
>   #include "smu_internal.h"
> @@ -52,6 +53,8 @@
>   #undef pr_info
>   #undef pr_debug
>   
> +#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
> +
>   #define FEATURE_MASK(feature) (1ULL << feature)
>   #define SMC_DPM_FEATURE ( \
>   	FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) | \
> @@ -455,6 +458,8 @@ static int sienna_cichlid_tables_init(struct smu_context *smu, struct smu_table
>   		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
>   	SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
>   		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
> +	SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t),
> +		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
>   	SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t),
>   		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
>   	SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE,
> @@ -2487,6 +2492,238 @@ static void sienna_cichlid_dump_pptable(struct smu_context *smu)
>   	dev_info(smu->adev->dev, "MmHubPadding[7] = 0x%x\n", pptable->MmHubPadding[7]);
>   }
>   
> +static void sienna_cichlid_fill_i2c_req(SwI2cRequest_t  *req, bool write,
> +				  uint8_t address, uint32_t numbytes,
> +				  uint8_t *data)
> +{
> +	int i;
> +
> +	BUG_ON(numbytes > MAX_SW_I2C_COMMANDS);
> +
> +	req->I2CcontrollerPort = 0;
> +	req->I2CSpeed = 2;
> +	req->SlaveAddress = address;
> +	req->NumCmds = numbytes;
> +
> +	for (i = 0; i < numbytes; i++) {
> +		SwI2cCmd_t *cmd =  &req->SwI2cCmds[i];
> +
> +		/* First 2 bytes are always write for lower 2b EEPROM address */
> +		if (i < 2)
> +			cmd->CmdConfig = CMDCONFIG_READWRITE_MASK;
> +		else
> +			cmd->CmdConfig = write ? CMDCONFIG_READWRITE_MASK : 0;
> +
> +
> +		/* Add RESTART for read  after address filled */
> +		cmd->CmdConfig |= (i == 2 && !write) ? CMDCONFIG_RESTART_MASK : 0;
> +
> +		/* Add STOP in the end */172.31.4.187
> +		cmd->CmdConfig |= (i == (numbytes - 1)) ? CMDCONFIG_STOP_MASK : 0;
> +
> +		/* Fill with data regardless if read or write to simplify code */
> +		cmd->ReadWriteData = data[i];
> +	}
> +}
> +
> +static int sienna_cichlid_i2c_read_data(struct i2c_adapter *control,
> +					       uint8_t address,
> +					       uint8_t *data,
> +					       uint32_t numbytes)
> +{
> +	uint32_t  i, ret = 0;
> +	SwI2cRequest_t req;
> +	struct amdgpu_device *adev = to_amdgpu_device(control);
> +	struct smu_table_context *smu_table = &adev->smu.smu_table;
> +	struct smu_table *table = &smu_table->driver_table;
> +
> +	memset(&req, 0, sizeof(req));
> +	sienna_cichlid_fill_i2c_req(&req, false, address, numbytes, data);
> +
> +	mutex_lock(&adev->smu.mutex);
> +	/* Now read data starting with that address */
> +	ret = smu_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req,
> +					true);
> +	mutex_unlock(&adev->smu.mutex);
> +
> +	if (!ret) {
> +		SwI2cRequest_t *res = (SwI2cRequest_t *)table->cpu_addr;
> +
> +		/* Assume SMU  fills res.SwI2cCmds[i].Data with read bytes */
> +		for (i = 0; i < numbytes; i++)
> +			data[i] = res->SwI2cCmds[i].ReadWriteData;
> +
> +		dev_dbg(adev->dev, "sienna_cichlid_i2c_read_data, address = %x, bytes = %d, data :",
> +				  (uint16_t)address, numbytes);
> +
> +		print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
> +			       8, 1, data, numbytes, false);
> +	} else
> +		dev_err(adev->dev, "sienna_cichlid_i2c_read_data - error occurred :%x", ret);
> +
> +	return ret;
> +}
> +
> +static int sienna_cichlid_i2c_write_data(struct i2c_adapter *control,
> +						uint8_t address,
> +						uint8_t *data,
> +						uint32_t numbytes)
> +{
> +	uint32_t ret;
> +	SwI2cRequest_t req;
> +	struct amdgpu_device *adev = to_amdgpu_device(control);
> +
> +	memset(&req, 0, sizeof(req));
> +	sienna_cichlid_fill_i2c_req(&req, true, address, numbytes, data);
> +
> +	mutex_lock(&adev->smu.mutex);
> +	ret = smu_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, true);
> +	mutex_unlock(&adev->smu.mutex);
> +
> +	if (!ret) {
> +		dev_dbg(adev->dev, "sienna_cichlid_i2c_write(), address = %x, bytes = %d , data: ",
> +					 (uint16_t)address, numbytes);
> +
> +		print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
> +			       8, 1, data, numbytes, false);
> +		/*
> +		 * According to EEPROM spec there is a MAX of 10 ms required for
> +		 * EEPROM to flush internal RX buffer after STOP was issued at the
> +		 * end of write transaction. During this time the EEPROM will not be
> +		 * responsive to any more commands - so wait a bit more.
> +		 */
> +		msleep(10);
> +
> +	} else
> +		dev_err(adev->dev, "sienna_cichlid_i2c_write- error occurred :%x", ret);
> +
> +	return ret;
> +}
> +
> +static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap,
> +			      struct i2c_msg *msgs, int num)
> +{
> +	uint32_t  i, j, ret, data_size, data_chunk_size, next_eeprom_addr = 0;
> +	uint8_t *data_ptr, data_chunk[MAX_SW_I2C_COMMANDS] = { 0 };
> +
> +	for (i = 0; i < num; i++) {
> +		/*
> +		 * SMU interface allows at most MAX_SW_I2C_COMMANDS bytes of data at
> +		 * once and hence the data needs to be spliced into chunks and sent each
> +		 * chunk separately
> +		 */
> +		data_size = msgs[i].len - 2;
> +		data_chunk_size = MAX_SW_I2C_COMMANDS - 2;
> +		next_eeprom_addr = (msgs[i].buf[0] << 8 & 0xff00) | (msgs[i].buf[1] & 0xff);
> +		data_ptr = msgs[i].buf + 2;
> +
> +		for (j = 0; j < data_size / data_chunk_size; j++) {
> +			/* Insert the EEPROM dest addess, bits 0-15 */
> +			data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
> +			data_chunk[1] = (next_eeprom_addr & 0xff);
> +
> +			if (msgs[i].flags & I2C_M_RD) {
> +				ret = sienna_cichlid_i2c_read_data(i2c_adap,
> +							     (uint8_t)msgs[i].addr,
> +							     data_chunk, MAX_SW_I2C_COMMANDS);
> +
> +				memcpy(data_ptr, data_chunk + 2, data_chunk_size);
> +			} else {
> +
> +				memcpy(data_chunk + 2, data_ptr, data_chunk_size);
> +
> +				ret = sienna_cichlid_i2c_write_data(i2c_adap,
> +							      (uint8_t)msgs[i].addr,
> +							      data_chunk, MAX_SW_I2C_COMMANDS);
> +			}
> +
> +			if (ret) {
> +				num = -EIO;
> +				goto fail;
> +			}
> +
> +			next_eeprom_addr += data_chunk_size;
> +			data_ptr += data_chunk_size;
> +		}
> +
> +		if (data_size % data_chunk_size) {
> +			data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
> +			data_chunk[1] = (next_eeprom_addr & 0xff);
> +
> +			if (msgs[i].flags & I2C_M_RD) {
> +				ret = sienna_cichlid_i2c_read_data(i2c_adap,
> +							     (uint8_t)msgs[i].addr,
> +							     data_chunk, (data_size % data_chunk_size) + 2);
> +
> +				memcpy(data_ptr, data_chunk + 2, data_size % data_chunk_size);
> +			} else {
> +				memcpy(data_chunk + 2, data_ptr, data_size % data_chunk_size);
> +
> +				ret = sienna_cichlid_i2c_write_data(i2c_adap,
> +							      (uint8_t)msgs[i].addr,
> +							      data_chunk, (data_size % data_chunk_size) + 2);
> +			}
> +
> +			if (ret) {
> +				num = -EIO;
> +				goto fail;
> +			}
> +		}
> +	}
> +
> +fail:
> +	return num;
> +}
> +
> +static u32 sienna_cichlid_i2c_func(struct i2c_adapter *adap)
> +{
> +	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
> +}
> +
> +
> +static const struct i2c_algorithm sienna_cichlid_i2c_algo = {
> +	.master_xfer = sienna_cichlid_i2c_xfer,
> +	.functionality = sienna_cichlid_i2c_func,
> +};
> +
> +static bool sienna_cichlid_i2c_adapter_is_added(struct i2c_adapter *control)
> +{
> +	struct amdgpu_device *adev = to_amdgpu_device(control);
> +
> +	return control->dev.parent == &adev->pdev->dev;
> +}
> +
> +static int sienna_cichlid_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control)
> +{
> +	struct amdgpu_device *adev = to_amdgpu_device(control);
> +	int res;
> +
> +	/* smu_i2c_eeprom_init may be called twice in sriov */
> +	if (sienna_cichlid_i2c_adapter_is_added(control))
> +		return 0;
> +
> +	control->owner = THIS_MODULE;
> +	control->class = I2C_CLASS_SPD;
> +	control->dev.parent = &adev->pdev->dev;
> +	control->algo = &sienna_cichlid_i2c_algo;
> +	snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
> +
> +	res = i2c_add_adapter(control);
> +	if (res)
> +		DRM_ERROR("Failed to register hw i2c, err: %d\n", res);
> +
> +	return res;
> +}
> +
> +static void sienna_cichlid_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control)
> +{
> +	if (!sienna_cichlid_i2c_adapter_is_added(control))
> +		return;
> +
> +	i2c_del_adapter(control);
> +}
> +
> +
>   static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
>   	.tables_init = sienna_cichlid_tables_init,
>   	.alloc_dpm_context = sienna_cichlid_allocate_dpm_context,
> @@ -2500,6 +2737,8 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
>   	.set_default_dpm_table = sienna_cichlid_set_default_dpm_table,
>   	.dpm_set_vcn_enable = sienna_cichlid_dpm_set_vcn_enable,
>   	.dpm_set_jpeg_enable = sienna_cichlid_dpm_set_jpeg_enable,
> +	.i2c_eeprom_init = sienna_cichlid_i2c_control_init,
> +	.i2c_eeprom_fini = sienna_cichlid_i2c_control_fini,
>   	.print_clk_levels = sienna_cichlid_print_clk_levels,
>   	.force_clk_levels = sienna_cichlid_force_clk_levels,
>   	.populate_umd_state_clk = sienna_cichlid_populate_umd_state_clk,
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 6/6] drm/amdgpu/sienna_cichlid: add SMU i2c support
  2020-07-21 17:01   ` Andrey Grodzovsky
@ 2020-07-21 17:02     ` Deucher, Alexander
  0 siblings, 0 replies; 11+ messages in thread
From: Deucher, Alexander @ 2020-07-21 17:02 UTC (permalink / raw)
  To: Grodzovsky, Andrey, Alex Deucher, amd-gfx


[-- Attachment #1.1: Type: text/plain, Size: 12951 bytes --]

[AMD Official Use Only - Internal Distribution Only]

I tried that at first, but the smu i2c interface structures are different per asic.

Alex

________________________________
From: Grodzovsky, Andrey <Andrey.Grodzovsky@amd.com>
Sent: Tuesday, July 21, 2020 1:01 PM
To: Alex Deucher <alexdeucher@gmail.com>; amd-gfx@lists.freedesktop.org <amd-gfx@lists.freedesktop.org>
Cc: Deucher, Alexander <Alexander.Deucher@amd.com>
Subject: Re: [PATCH 6/6] drm/amdgpu/sienna_cichlid: add SMU i2c support

Looks like same code as arcturus - should we make it common helper code and
reuse in both ?

Andrey

On 7/21/20 12:52 PM, Alex Deucher wrote:
> Enable SMU i2c bus access for sienna_cichlid asics.
>
> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
> ---
>   .../drm/amd/powerplay/sienna_cichlid_ppt.c    | 239 ++++++++++++++++++
>   1 file changed, 239 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c
> index 5faef41b63a3..e1857fbb0a6f 100644
> --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c
> +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c
> @@ -23,6 +23,7 @@
>
>   #include <linux/firmware.h>
>   #include <linux/pci.h>
> +#include <linux/i2c.h>
>   #include "amdgpu.h"
>   #include "amdgpu_smu.h"
>   #include "smu_internal.h"
> @@ -52,6 +53,8 @@
>   #undef pr_info
>   #undef pr_debug
>
> +#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
> +
>   #define FEATURE_MASK(feature) (1ULL << feature)
>   #define SMC_DPM_FEATURE ( \
>        FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) | \
> @@ -455,6 +458,8 @@ static int sienna_cichlid_tables_init(struct smu_context *smu, struct smu_table
>                       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
>        SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
>                       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
> +     SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t),
> +                    PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
>        SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t),
>                       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
>        SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE,
> @@ -2487,6 +2492,238 @@ static void sienna_cichlid_dump_pptable(struct smu_context *smu)
>        dev_info(smu->adev->dev, "MmHubPadding[7] = 0x%x\n", pptable->MmHubPadding[7]);
>   }
>
> +static void sienna_cichlid_fill_i2c_req(SwI2cRequest_t  *req, bool write,
> +                               uint8_t address, uint32_t numbytes,
> +                               uint8_t *data)
> +{
> +     int i;
> +
> +     BUG_ON(numbytes > MAX_SW_I2C_COMMANDS);
> +
> +     req->I2CcontrollerPort = 0;
> +     req->I2CSpeed = 2;
> +     req->SlaveAddress = address;
> +     req->NumCmds = numbytes;
> +
> +     for (i = 0; i < numbytes; i++) {
> +             SwI2cCmd_t *cmd =  &req->SwI2cCmds[i];
> +
> +             /* First 2 bytes are always write for lower 2b EEPROM address */
> +             if (i < 2)
> +                     cmd->CmdConfig = CMDCONFIG_READWRITE_MASK;
> +             else
> +                     cmd->CmdConfig = write ? CMDCONFIG_READWRITE_MASK : 0;
> +
> +
> +             /* Add RESTART for read  after address filled */
> +             cmd->CmdConfig |= (i == 2 && !write) ? CMDCONFIG_RESTART_MASK : 0;
> +
> +             /* Add STOP in the end */172.31.4.187
> +             cmd->CmdConfig |= (i == (numbytes - 1)) ? CMDCONFIG_STOP_MASK : 0;
> +
> +             /* Fill with data regardless if read or write to simplify code */
> +             cmd->ReadWriteData = data[i];
> +     }
> +}
> +
> +static int sienna_cichlid_i2c_read_data(struct i2c_adapter *control,
> +                                            uint8_t address,
> +                                            uint8_t *data,
> +                                            uint32_t numbytes)
> +{
> +     uint32_t  i, ret = 0;
> +     SwI2cRequest_t req;
> +     struct amdgpu_device *adev = to_amdgpu_device(control);
> +     struct smu_table_context *smu_table = &adev->smu.smu_table;
> +     struct smu_table *table = &smu_table->driver_table;
> +
> +     memset(&req, 0, sizeof(req));
> +     sienna_cichlid_fill_i2c_req(&req, false, address, numbytes, data);
> +
> +     mutex_lock(&adev->smu.mutex);
> +     /* Now read data starting with that address */
> +     ret = smu_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req,
> +                                     true);
> +     mutex_unlock(&adev->smu.mutex);
> +
> +     if (!ret) {
> +             SwI2cRequest_t *res = (SwI2cRequest_t *)table->cpu_addr;
> +
> +             /* Assume SMU  fills res.SwI2cCmds[i].Data with read bytes */
> +             for (i = 0; i < numbytes; i++)
> +                     data[i] = res->SwI2cCmds[i].ReadWriteData;
> +
> +             dev_dbg(adev->dev, "sienna_cichlid_i2c_read_data, address = %x, bytes = %d, data :",
> +                               (uint16_t)address, numbytes);
> +
> +             print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
> +                            8, 1, data, numbytes, false);
> +     } else
> +             dev_err(adev->dev, "sienna_cichlid_i2c_read_data - error occurred :%x", ret);
> +
> +     return ret;
> +}
> +
> +static int sienna_cichlid_i2c_write_data(struct i2c_adapter *control,
> +                                             uint8_t address,
> +                                             uint8_t *data,
> +                                             uint32_t numbytes)
> +{
> +     uint32_t ret;
> +     SwI2cRequest_t req;
> +     struct amdgpu_device *adev = to_amdgpu_device(control);
> +
> +     memset(&req, 0, sizeof(req));
> +     sienna_cichlid_fill_i2c_req(&req, true, address, numbytes, data);
> +
> +     mutex_lock(&adev->smu.mutex);
> +     ret = smu_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, true);
> +     mutex_unlock(&adev->smu.mutex);
> +
> +     if (!ret) {
> +             dev_dbg(adev->dev, "sienna_cichlid_i2c_write(), address = %x, bytes = %d , data: ",
> +                                      (uint16_t)address, numbytes);
> +
> +             print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
> +                            8, 1, data, numbytes, false);
> +             /*
> +              * According to EEPROM spec there is a MAX of 10 ms required for
> +              * EEPROM to flush internal RX buffer after STOP was issued at the
> +              * end of write transaction. During this time the EEPROM will not be
> +              * responsive to any more commands - so wait a bit more.
> +              */
> +             msleep(10);
> +
> +     } else
> +             dev_err(adev->dev, "sienna_cichlid_i2c_write- error occurred :%x", ret);
> +
> +     return ret;
> +}
> +
> +static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap,
> +                           struct i2c_msg *msgs, int num)
> +{
> +     uint32_t  i, j, ret, data_size, data_chunk_size, next_eeprom_addr = 0;
> +     uint8_t *data_ptr, data_chunk[MAX_SW_I2C_COMMANDS] = { 0 };
> +
> +     for (i = 0; i < num; i++) {
> +             /*
> +              * SMU interface allows at most MAX_SW_I2C_COMMANDS bytes of data at
> +              * once and hence the data needs to be spliced into chunks and sent each
> +              * chunk separately
> +              */
> +             data_size = msgs[i].len - 2;
> +             data_chunk_size = MAX_SW_I2C_COMMANDS - 2;
> +             next_eeprom_addr = (msgs[i].buf[0] << 8 & 0xff00) | (msgs[i].buf[1] & 0xff);
> +             data_ptr = msgs[i].buf + 2;
> +
> +             for (j = 0; j < data_size / data_chunk_size; j++) {
> +                     /* Insert the EEPROM dest addess, bits 0-15 */
> +                     data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
> +                     data_chunk[1] = (next_eeprom_addr & 0xff);
> +
> +                     if (msgs[i].flags & I2C_M_RD) {
> +                             ret = sienna_cichlid_i2c_read_data(i2c_adap,
> +                                                          (uint8_t)msgs[i].addr,
> +                                                          data_chunk, MAX_SW_I2C_COMMANDS);
> +
> +                             memcpy(data_ptr, data_chunk + 2, data_chunk_size);
> +                     } else {
> +
> +                             memcpy(data_chunk + 2, data_ptr, data_chunk_size);
> +
> +                             ret = sienna_cichlid_i2c_write_data(i2c_adap,
> +                                                           (uint8_t)msgs[i].addr,
> +                                                           data_chunk, MAX_SW_I2C_COMMANDS);
> +                     }
> +
> +                     if (ret) {
> +                             num = -EIO;
> +                             goto fail;
> +                     }
> +
> +                     next_eeprom_addr += data_chunk_size;
> +                     data_ptr += data_chunk_size;
> +             }
> +
> +             if (data_size % data_chunk_size) {
> +                     data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
> +                     data_chunk[1] = (next_eeprom_addr & 0xff);
> +
> +                     if (msgs[i].flags & I2C_M_RD) {
> +                             ret = sienna_cichlid_i2c_read_data(i2c_adap,
> +                                                          (uint8_t)msgs[i].addr,
> +                                                          data_chunk, (data_size % data_chunk_size) + 2);
> +
> +                             memcpy(data_ptr, data_chunk + 2, data_size % data_chunk_size);
> +                     } else {
> +                             memcpy(data_chunk + 2, data_ptr, data_size % data_chunk_size);
> +
> +                             ret = sienna_cichlid_i2c_write_data(i2c_adap,
> +                                                           (uint8_t)msgs[i].addr,
> +                                                           data_chunk, (data_size % data_chunk_size) + 2);
> +                     }
> +
> +                     if (ret) {
> +                             num = -EIO;
> +                             goto fail;
> +                     }
> +             }
> +     }
> +
> +fail:
> +     return num;
> +}
> +
> +static u32 sienna_cichlid_i2c_func(struct i2c_adapter *adap)
> +{
> +     return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
> +}
> +
> +
> +static const struct i2c_algorithm sienna_cichlid_i2c_algo = {
> +     .master_xfer = sienna_cichlid_i2c_xfer,
> +     .functionality = sienna_cichlid_i2c_func,
> +};
> +
> +static bool sienna_cichlid_i2c_adapter_is_added(struct i2c_adapter *control)
> +{
> +     struct amdgpu_device *adev = to_amdgpu_device(control);
> +
> +     return control->dev.parent == &adev->pdev->dev;
> +}
> +
> +static int sienna_cichlid_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control)
> +{
> +     struct amdgpu_device *adev = to_amdgpu_device(control);
> +     int res;
> +
> +     /* smu_i2c_eeprom_init may be called twice in sriov */
> +     if (sienna_cichlid_i2c_adapter_is_added(control))
> +             return 0;
> +
> +     control->owner = THIS_MODULE;
> +     control->class = I2C_CLASS_SPD;
> +     control->dev.parent = &adev->pdev->dev;
> +     control->algo = &sienna_cichlid_i2c_algo;
> +     snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
> +
> +     res = i2c_add_adapter(control);
> +     if (res)
> +             DRM_ERROR("Failed to register hw i2c, err: %d\n", res);
> +
> +     return res;
> +}
> +
> +static void sienna_cichlid_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control)
> +{
> +     if (!sienna_cichlid_i2c_adapter_is_added(control))
> +             return;
> +
> +     i2c_del_adapter(control);
> +}
> +
> +
>   static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
>        .tables_init = sienna_cichlid_tables_init,
>        .alloc_dpm_context = sienna_cichlid_allocate_dpm_context,
> @@ -2500,6 +2737,8 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
>        .set_default_dpm_table = sienna_cichlid_set_default_dpm_table,
>        .dpm_set_vcn_enable = sienna_cichlid_dpm_set_vcn_enable,
>        .dpm_set_jpeg_enable = sienna_cichlid_dpm_set_jpeg_enable,
> +     .i2c_eeprom_init = sienna_cichlid_i2c_control_init,
> +     .i2c_eeprom_fini = sienna_cichlid_i2c_control_fini,
>        .print_clk_levels = sienna_cichlid_print_clk_levels,
>        .force_clk_levels = sienna_cichlid_force_clk_levels,
>        .populate_umd_state_clk = sienna_cichlid_populate_umd_state_clk,

[-- Attachment #1.2: Type: text/html, Size: 31070 bytes --]

[-- Attachment #2: Type: text/plain, Size: 154 bytes --]

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 6/6] drm/amdgpu/sienna_cichlid: add SMU i2c support
  2020-07-21 16:52 ` [PATCH 6/6] drm/amdgpu/sienna_cichlid: " Alex Deucher
  2020-07-21 17:01   ` Andrey Grodzovsky
@ 2020-07-21 18:01   ` Andrey Grodzovsky
  1 sibling, 0 replies; 11+ messages in thread
From: Andrey Grodzovsky @ 2020-07-21 18:01 UTC (permalink / raw)
  To: Alex Deucher, amd-gfx; +Cc: Alex Deucher

Series besides patch 5/6 which you said is the wrong version is Reviewed-by: 
Andrey Grodzovsky <andrey.grodzovsky@amd.com>

Andrey

On 7/21/20 12:52 PM, Alex Deucher wrote:
> Enable SMU i2c bus access for sienna_cichlid asics.
>
> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
> ---
>   .../drm/amd/powerplay/sienna_cichlid_ppt.c    | 239 ++++++++++++++++++
>   1 file changed, 239 insertions(+)
>
> diff --git a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c
> index 5faef41b63a3..e1857fbb0a6f 100644
> --- a/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c
> +++ b/drivers/gpu/drm/amd/powerplay/sienna_cichlid_ppt.c
> @@ -23,6 +23,7 @@
>   
>   #include <linux/firmware.h>
>   #include <linux/pci.h>
> +#include <linux/i2c.h>
>   #include "amdgpu.h"
>   #include "amdgpu_smu.h"
>   #include "smu_internal.h"
> @@ -52,6 +53,8 @@
>   #undef pr_info
>   #undef pr_debug
>   
> +#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
> +
>   #define FEATURE_MASK(feature) (1ULL << feature)
>   #define SMC_DPM_FEATURE ( \
>   	FEATURE_MASK(FEATURE_DPM_PREFETCHER_BIT) | \
> @@ -455,6 +458,8 @@ static int sienna_cichlid_tables_init(struct smu_context *smu, struct smu_table
>   		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
>   	SMU_TABLE_INIT(tables, SMU_TABLE_SMU_METRICS, sizeof(SmuMetrics_t),
>   		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
> +	SMU_TABLE_INIT(tables, SMU_TABLE_I2C_COMMANDS, sizeof(SwI2cRequest_t),
> +		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
>   	SMU_TABLE_INIT(tables, SMU_TABLE_OVERDRIVE, sizeof(OverDriveTable_t),
>   		       PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM);
>   	SMU_TABLE_INIT(tables, SMU_TABLE_PMSTATUSLOG, SMU11_TOOL_SIZE,
> @@ -2487,6 +2492,238 @@ static void sienna_cichlid_dump_pptable(struct smu_context *smu)
>   	dev_info(smu->adev->dev, "MmHubPadding[7] = 0x%x\n", pptable->MmHubPadding[7]);
>   }
>   
> +static void sienna_cichlid_fill_i2c_req(SwI2cRequest_t  *req, bool write,
> +				  uint8_t address, uint32_t numbytes,
> +				  uint8_t *data)
> +{
> +	int i;
> +
> +	BUG_ON(numbytes > MAX_SW_I2C_COMMANDS);
> +
> +	req->I2CcontrollerPort = 0;
> +	req->I2CSpeed = 2;
> +	req->SlaveAddress = address;
> +	req->NumCmds = numbytes;
> +
> +	for (i = 0; i < numbytes; i++) {
> +		SwI2cCmd_t *cmd =  &req->SwI2cCmds[i];
> +
> +		/* First 2 bytes are always write for lower 2b EEPROM address */
> +		if (i < 2)
> +			cmd->CmdConfig = CMDCONFIG_READWRITE_MASK;
> +		else
> +			cmd->CmdConfig = write ? CMDCONFIG_READWRITE_MASK : 0;
> +
> +
> +		/* Add RESTART for read  after address filled */
> +		cmd->CmdConfig |= (i == 2 && !write) ? CMDCONFIG_RESTART_MASK : 0;
> +
> +		/* Add STOP in the end */
> +		cmd->CmdConfig |= (i == (numbytes - 1)) ? CMDCONFIG_STOP_MASK : 0;
> +
> +		/* Fill with data regardless if read or write to simplify code */
> +		cmd->ReadWriteData = data[i];
> +	}
> +}
> +
> +static int sienna_cichlid_i2c_read_data(struct i2c_adapter *control,
> +					       uint8_t address,
> +					       uint8_t *data,
> +					       uint32_t numbytes)
> +{
> +	uint32_t  i, ret = 0;
> +	SwI2cRequest_t req;
> +	struct amdgpu_device *adev = to_amdgpu_device(control);
> +	struct smu_table_context *smu_table = &adev->smu.smu_table;
> +	struct smu_table *table = &smu_table->driver_table;
> +
> +	memset(&req, 0, sizeof(req));
> +	sienna_cichlid_fill_i2c_req(&req, false, address, numbytes, data);
> +
> +	mutex_lock(&adev->smu.mutex);
> +	/* Now read data starting with that address */
> +	ret = smu_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req,
> +					true);
> +	mutex_unlock(&adev->smu.mutex);
> +
> +	if (!ret) {
> +		SwI2cRequest_t *res = (SwI2cRequest_t *)table->cpu_addr;
> +
> +		/* Assume SMU  fills res.SwI2cCmds[i].Data with read bytes */
> +		for (i = 0; i < numbytes; i++)
> +			data[i] = res->SwI2cCmds[i].ReadWriteData;
> +
> +		dev_dbg(adev->dev, "sienna_cichlid_i2c_read_data, address = %x, bytes = %d, data :",
> +				  (uint16_t)address, numbytes);
> +
> +		print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
> +			       8, 1, data, numbytes, false);
> +	} else
> +		dev_err(adev->dev, "sienna_cichlid_i2c_read_data - error occurred :%x", ret);
> +
> +	return ret;
> +}
> +
> +static int sienna_cichlid_i2c_write_data(struct i2c_adapter *control,
> +						uint8_t address,
> +						uint8_t *data,
> +						uint32_t numbytes)
> +{
> +	uint32_t ret;
> +	SwI2cRequest_t req;
> +	struct amdgpu_device *adev = to_amdgpu_device(control);
> +
> +	memset(&req, 0, sizeof(req));
> +	sienna_cichlid_fill_i2c_req(&req, true, address, numbytes, data);
> +
> +	mutex_lock(&adev->smu.mutex);
> +	ret = smu_update_table(&adev->smu, SMU_TABLE_I2C_COMMANDS, 0, &req, true);
> +	mutex_unlock(&adev->smu.mutex);
> +
> +	if (!ret) {
> +		dev_dbg(adev->dev, "sienna_cichlid_i2c_write(), address = %x, bytes = %d , data: ",
> +					 (uint16_t)address, numbytes);
> +
> +		print_hex_dump(KERN_DEBUG, "data: ", DUMP_PREFIX_NONE,
> +			       8, 1, data, numbytes, false);
> +		/*
> +		 * According to EEPROM spec there is a MAX of 10 ms required for
> +		 * EEPROM to flush internal RX buffer after STOP was issued at the
> +		 * end of write transaction. During this time the EEPROM will not be
> +		 * responsive to any more commands - so wait a bit more.
> +		 */
> +		msleep(10);
> +
> +	} else
> +		dev_err(adev->dev, "sienna_cichlid_i2c_write- error occurred :%x", ret);
> +
> +	return ret;
> +}
> +
> +static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap,
> +			      struct i2c_msg *msgs, int num)
> +{
> +	uint32_t  i, j, ret, data_size, data_chunk_size, next_eeprom_addr = 0;
> +	uint8_t *data_ptr, data_chunk[MAX_SW_I2C_COMMANDS] = { 0 };
> +
> +	for (i = 0; i < num; i++) {
> +		/*
> +		 * SMU interface allows at most MAX_SW_I2C_COMMANDS bytes of data at
> +		 * once and hence the data needs to be spliced into chunks and sent each
> +		 * chunk separately
> +		 */
> +		data_size = msgs[i].len - 2;
> +		data_chunk_size = MAX_SW_I2C_COMMANDS - 2;
> +		next_eeprom_addr = (msgs[i].buf[0] << 8 & 0xff00) | (msgs[i].buf[1] & 0xff);
> +		data_ptr = msgs[i].buf + 2;
> +
> +		for (j = 0; j < data_size / data_chunk_size; j++) {
> +			/* Insert the EEPROM dest addess, bits 0-15 */
> +			data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
> +			data_chunk[1] = (next_eeprom_addr & 0xff);
> +
> +			if (msgs[i].flags & I2C_M_RD) {
> +				ret = sienna_cichlid_i2c_read_data(i2c_adap,
> +							     (uint8_t)msgs[i].addr,
> +							     data_chunk, MAX_SW_I2C_COMMANDS);
> +
> +				memcpy(data_ptr, data_chunk + 2, data_chunk_size);
> +			} else {
> +
> +				memcpy(data_chunk + 2, data_ptr, data_chunk_size);
> +
> +				ret = sienna_cichlid_i2c_write_data(i2c_adap,
> +							      (uint8_t)msgs[i].addr,
> +							      data_chunk, MAX_SW_I2C_COMMANDS);
> +			}
> +
> +			if (ret) {
> +				num = -EIO;
> +				goto fail;
> +			}
> +
> +			next_eeprom_addr += data_chunk_size;
> +			data_ptr += data_chunk_size;
> +		}
> +
> +		if (data_size % data_chunk_size) {
> +			data_chunk[0] = ((next_eeprom_addr >> 8) & 0xff);
> +			data_chunk[1] = (next_eeprom_addr & 0xff);
> +
> +			if (msgs[i].flags & I2C_M_RD) {
> +				ret = sienna_cichlid_i2c_read_data(i2c_adap,
> +							     (uint8_t)msgs[i].addr,
> +							     data_chunk, (data_size % data_chunk_size) + 2);
> +
> +				memcpy(data_ptr, data_chunk + 2, data_size % data_chunk_size);
> +			} else {
> +				memcpy(data_chunk + 2, data_ptr, data_size % data_chunk_size);
> +
> +				ret = sienna_cichlid_i2c_write_data(i2c_adap,
> +							      (uint8_t)msgs[i].addr,
> +							      data_chunk, (data_size % data_chunk_size) + 2);
> +			}
> +
> +			if (ret) {
> +				num = -EIO;
> +				goto fail;
> +			}
> +		}
> +	}
> +
> +fail:
> +	return num;
> +}
> +
> +static u32 sienna_cichlid_i2c_func(struct i2c_adapter *adap)
> +{
> +	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
> +}
> +
> +
> +static const struct i2c_algorithm sienna_cichlid_i2c_algo = {
> +	.master_xfer = sienna_cichlid_i2c_xfer,
> +	.functionality = sienna_cichlid_i2c_func,
> +};
> +
> +static bool sienna_cichlid_i2c_adapter_is_added(struct i2c_adapter *control)
> +{
> +	struct amdgpu_device *adev = to_amdgpu_device(control);
> +
> +	return control->dev.parent == &adev->pdev->dev;
> +}
> +
> +static int sienna_cichlid_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control)
> +{
> +	struct amdgpu_device *adev = to_amdgpu_device(control);
> +	int res;
> +
> +	/* smu_i2c_eeprom_init may be called twice in sriov */
> +	if (sienna_cichlid_i2c_adapter_is_added(control))
> +		return 0;
> +
> +	control->owner = THIS_MODULE;
> +	control->class = I2C_CLASS_SPD;
> +	control->dev.parent = &adev->pdev->dev;
> +	control->algo = &sienna_cichlid_i2c_algo;
> +	snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
> +
> +	res = i2c_add_adapter(control);
> +	if (res)
> +		DRM_ERROR("Failed to register hw i2c, err: %d\n", res);
> +
> +	return res;
> +}
> +
> +static void sienna_cichlid_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control)
> +{
> +	if (!sienna_cichlid_i2c_adapter_is_added(control))
> +		return;
> +
> +	i2c_del_adapter(control);
> +}
> +
> +
>   static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
>   	.tables_init = sienna_cichlid_tables_init,
>   	.alloc_dpm_context = sienna_cichlid_allocate_dpm_context,
> @@ -2500,6 +2737,8 @@ static const struct pptable_funcs sienna_cichlid_ppt_funcs = {
>   	.set_default_dpm_table = sienna_cichlid_set_default_dpm_table,
>   	.dpm_set_vcn_enable = sienna_cichlid_dpm_set_vcn_enable,
>   	.dpm_set_jpeg_enable = sienna_cichlid_dpm_set_jpeg_enable,
> +	.i2c_eeprom_init = sienna_cichlid_i2c_control_init,
> +	.i2c_eeprom_fini = sienna_cichlid_i2c_control_fini,
>   	.print_clk_levels = sienna_cichlid_print_clk_levels,
>   	.force_clk_levels = sienna_cichlid_force_clk_levels,
>   	.populate_umd_state_clk = sienna_cichlid_populate_umd_state_clk,
_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/6] drm/amdgpu: move i2c bus lock out of ras structure
@ 2020-07-21 18:08 Alex Deucher
  0 siblings, 0 replies; 11+ messages in thread
From: Alex Deucher @ 2020-07-21 18:08 UTC (permalink / raw)
  To: amd-gfx; +Cc: Alex Deucher, Andrey Grodzovsky

It's not really ras related.  It's just a lock for the
bus in general.  This removes the ras dependency from
the smu i2c bus.

Reviewed-by: Andrey Grodzovsky <andrey.grodzovsky@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h        |  1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h |  1 -
 drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c     | 10 +++-------
 3 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
index 7f3cd7185650..aa27fe65cdfa 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dpm.h
@@ -425,6 +425,7 @@ struct amdgpu_pm {
 	u32                     default_sclk;
 	u32                     default_mclk;
 	struct amdgpu_i2c_chan *i2c_bus;
+	bool                    bus_locked;
 	/* internal thermal controller on rv6xx+ */
 	enum amdgpu_int_thermal_type int_thermal_type;
 	struct device	        *int_hwmon_dev;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
index 7e8647a05df7..9e7d640920fb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras_eeprom.h
@@ -47,7 +47,6 @@ struct amdgpu_ras_eeprom_control {
 	uint32_t next_addr;
 	unsigned int num_recs;
 	struct mutex tbl_mutex;
-	bool bus_locked;
 	uint32_t tbl_byte_sum;
 	uint16_t i2c_address; // 8-bit represented address
 };
diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
index 9bffbab35041..f3d0324c4a7f 100644
--- a/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
+++ b/drivers/gpu/drm/amd/amdgpu/smu_v11_0_i2c.c
@@ -32,7 +32,6 @@
 #include "amdgpu_amdkfd.h"
 #include <linux/i2c.h>
 #include <linux/pci.h>
-#include "amdgpu_ras.h"
 
 /* error codes */
 #define I2C_OK                0
@@ -592,14 +591,13 @@ static uint32_t smu_v11_0_i2c_eeprom_write_data(struct i2c_adapter *control,
 static void lock_bus(struct i2c_adapter *i2c, unsigned int flags)
 {
 	struct amdgpu_device *adev = to_amdgpu_device(i2c);
-	struct amdgpu_ras_eeprom_control *control = &adev->psp.ras.ras->eeprom_control;
 
 	if (!smu_v11_0_i2c_bus_lock(i2c)) {
 		DRM_ERROR("Failed to lock the bus from SMU");
 		return;
 	}
 
-	control->bus_locked = true;
+	adev->pm.bus_locked = true;
 }
 
 static int trylock_bus(struct i2c_adapter *i2c, unsigned int flags)
@@ -611,14 +609,13 @@ static int trylock_bus(struct i2c_adapter *i2c, unsigned int flags)
 static void unlock_bus(struct i2c_adapter *i2c, unsigned int flags)
 {
 	struct amdgpu_device *adev = to_amdgpu_device(i2c);
-	struct amdgpu_ras_eeprom_control *control = &adev->psp.ras.ras->eeprom_control;
 
 	if (!smu_v11_0_i2c_bus_unlock(i2c)) {
 		DRM_ERROR("Failed to unlock the bus from SMU");
 		return;
 	}
 
-	control->bus_locked = false;
+	adev->pm.bus_locked = false;
 }
 
 static const struct i2c_lock_operations smu_v11_0_i2c_i2c_lock_ops = {
@@ -632,9 +629,8 @@ static int smu_v11_0_i2c_eeprom_i2c_xfer(struct i2c_adapter *i2c_adap,
 {
 	int i, ret;
 	struct amdgpu_device *adev = to_amdgpu_device(i2c_adap);
-	struct amdgpu_ras_eeprom_control *control = &adev->psp.ras.ras->eeprom_control;
 
-	if (!control->bus_locked) {
+	if (!adev->pm.bus_locked) {
 		DRM_ERROR("I2C bus unlocked, stopping transaction!");
 		return -EIO;
 	}
-- 
2.25.4

_______________________________________________
amd-gfx mailing list
amd-gfx@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/amd-gfx

^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2020-07-21 18:09 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-21 16:52 [PATCH 1/6] drm/amdgpu: move i2c bus lock out of ras structure Alex Deucher
2020-07-21 16:52 ` [PATCH 2/6] drm/amdgpu: remove eeprom from the smu i2c handlers Alex Deucher
2020-07-21 16:52 ` [PATCH 3/6] drm/amdgpu/vega20: enable the smu i2c bus for all boards Alex Deucher
2020-07-21 16:52 ` [PATCH 4/6] drm/amdgpu/swSMU: remove eeprom from the smu i2c handlers Alex Deucher
2020-07-21 16:52 ` [PATCH 5/6] drm/amdgpu/navi1x: add SMU i2c support Alex Deucher
2020-07-21 16:56   ` Deucher, Alexander
2020-07-21 16:52 ` [PATCH 6/6] drm/amdgpu/sienna_cichlid: " Alex Deucher
2020-07-21 17:01   ` Andrey Grodzovsky
2020-07-21 17:02     ` Deucher, Alexander
2020-07-21 18:01   ` Andrey Grodzovsky
2020-07-21 18:08 [PATCH 1/6] drm/amdgpu: move i2c bus lock out of ras structure Alex Deucher

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.