summaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/amd/pm
diff options
context:
space:
mode:
authorLuben Tuikov <luben.tuikov@amd.com>2022-01-20 04:20:53 +0300
committerAlex Deucher <alexander.deucher@amd.com>2022-01-27 23:49:48 +0300
commit2f60dd50769efcd6eedd0dc6b3f419cdd1f1f1fa (patch)
treed1665a769e56ca6e9b4e4548b1f2b00c6b003e42 /drivers/gpu/drm/amd/pm
parentf06d9e4eec7320f5a560e49ed652e785c8ab5c45 (diff)
downloadlinux-2f60dd50769efcd6eedd0dc6b3f419cdd1f1f1fa.tar.xz
drm/amd: Expose the FRU SMU I2C bus
Expose both SMU I2C buses. Some boards use the same bus for both the RAS and FRU EEPROMs and others use different buses. This enables the additional I2C bus and sets the right buses to use for RAS and FRU EEPROM access. Cc: Roy Sun <Roy.Sun@amd.com> Co-developed-by: Alex Deucher <Alexander.Deucher@amd.com> Signed-off-by: Luben Tuikov <luben.tuikov@amd.com> Reviewed-by: Alex Deucher <Alexander.Deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/amd/pm')
-rw-r--r--drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h14
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c4
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c4
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h4
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c69
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c68
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c71
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c44
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_internal.h4
9 files changed, 207 insertions, 75 deletions
diff --git a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
index ba857ca75392..2766b88ecf96 100644
--- a/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
+++ b/drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h
@@ -284,6 +284,15 @@ enum ip_power_state {
/* Used to mask smu debug modes */
#define SMU_DEBUG_HALT_ON_ERROR 0x1
+#define MAX_SMU_I2C_BUSES 2
+
+struct amdgpu_smu_i2c_bus {
+ struct i2c_adapter adapter;
+ struct amdgpu_device *adev;
+ int port;
+ struct mutex mutex;
+};
+
struct amdgpu_pm {
struct mutex mutex;
u32 current_sclk;
@@ -316,8 +325,9 @@ struct amdgpu_pm {
uint32_t pp_feature;
/* Used for I2C access to various EEPROMs on relevant ASICs */
- struct i2c_adapter smu_i2c;
- struct mutex smu_i2c_mutex;
+ struct amdgpu_smu_i2c_bus smu_i2c[MAX_SMU_I2C_BUSES];
+ struct i2c_adapter *ras_eeprom_i2c_bus;
+ struct i2c_adapter *fru_eeprom_i2c_bus;
struct list_head pm_attr_list;
atomic_t pwr_state[AMD_IP_BLOCK_TYPE_NUM];
diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c
index 9ad26c285ecd..a5c95b180672 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega20_smumgr.c
@@ -520,7 +520,7 @@ 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);
- ret = smu_v11_0_i2c_control_init(&adev->pm.smu_i2c);
+ ret = smu_v11_0_i2c_control_init(adev);
if (ret)
goto err4;
@@ -558,7 +558,7 @@ static int vega20_smu_fini(struct pp_hwmgr *hwmgr)
(struct vega20_smumgr *)(hwmgr->smu_backend);
struct amdgpu_device *adev = hwmgr->adev;
- smu_v11_0_i2c_control_fini(&adev->pm.smu_i2c);
+ smu_v11_0_i2c_control_fini(adev);
if (priv) {
amdgpu_bo_free_kernel(&priv->smu_tables.entry[TABLE_PPTABLE].handle,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index 264eb09ccfd5..9861d70a5dad 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -886,7 +886,7 @@ static int smu_smc_table_sw_init(struct smu_context *smu)
if (ret)
return ret;
- ret = smu_i2c_init(smu, &smu->adev->pm.smu_i2c);
+ ret = smu_i2c_init(smu);
if (ret)
return ret;
@@ -897,7 +897,7 @@ static int smu_smc_table_sw_fini(struct smu_context *smu)
{
int ret;
- smu_i2c_fini(smu, &smu->adev->pm.smu_i2c);
+ smu_i2c_fini(smu);
smu_free_dummy_read_table(smu);
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
index 18f24db7d202..4c585241ef66 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
@@ -816,12 +816,12 @@ struct pptable_funcs {
* other devices. The i2c's EEPROM also stores bad page tables on boards
* with ECC.
*/
- int (*i2c_init)(struct smu_context *smu, struct i2c_adapter *control);
+ int (*i2c_init)(struct smu_context *smu);
/**
* @i2c_fini: Tear down i2c.
*/
- void (*i2c_fini)(struct smu_context *smu, struct i2c_adapter *control);
+ void (*i2c_fini)(struct smu_context *smu);
/**
* @get_unique_id: Get the GPU's unique id. Used for asset tracking.
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
index 2c78d04d5611..0cf385e8b4e9 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -25,6 +25,7 @@
#include <linux/firmware.h>
#include "amdgpu.h"
+#include "amdgpu_dpm.h"
#include "amdgpu_smu.h"
#include "atomfirmware.h"
#include "amdgpu_atomfirmware.h"
@@ -45,6 +46,7 @@
#include <linux/pci.h>
#include "amdgpu_ras.h"
#include "smu_cmn.h"
+#include "amdgpu_dpm.h"
/*
* DO NOT use these for err/warn/info/debug messages.
@@ -56,8 +58,6 @@
#undef pr_info
#undef pr_debug
-#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
-
#define ARCTURUS_FEA_MAP(smu_feature, arcturus_feature) \
[smu_feature] = {1, (arcturus_feature)}
@@ -2062,7 +2062,8 @@ static int arcturus_dpm_set_vcn_enable(struct smu_context *smu, bool enable)
static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap,
struct i2c_msg *msg, int num_msgs)
{
- struct amdgpu_device *adev = to_amdgpu_device(i2c_adap);
+ struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(i2c_adap);
+ struct amdgpu_device *adev = smu_i2c->adev;
struct smu_context *smu = adev->powerplay.pp_handle;
struct smu_table_context *smu_table = &smu->smu_table;
struct smu_table *table = &smu_table->driver_table;
@@ -2074,7 +2075,7 @@ static int arcturus_i2c_xfer(struct i2c_adapter *i2c_adap,
if (!req)
return -ENOMEM;
- req->I2CcontrollerPort = 0;
+ req->I2CcontrollerPort = smu_i2c->port;
req->I2CSpeed = I2C_SPEED_FAST_400K;
req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */
dir = msg[0].flags & I2C_M_RD;
@@ -2153,28 +2154,60 @@ static const struct i2c_adapter_quirks arcturus_i2c_control_quirks = {
.max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2,
};
-static int arcturus_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control)
+static int arcturus_i2c_control_init(struct smu_context *smu)
{
- struct amdgpu_device *adev = to_amdgpu_device(control);
- int res;
+ struct amdgpu_device *adev = smu->adev;
+ int res, i;
+
+ for (i = 0; i < MAX_SMU_I2C_BUSES; i++) {
+ struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i];
+ struct i2c_adapter *control = &smu_i2c->adapter;
+
+ smu_i2c->adev = adev;
+ smu_i2c->port = i;
+ mutex_init(&smu_i2c->mutex);
+ control->owner = THIS_MODULE;
+ control->class = I2C_CLASS_HWMON;
+ control->dev.parent = &adev->pdev->dev;
+ control->algo = &arcturus_i2c_algo;
+ control->quirks = &arcturus_i2c_control_quirks;
+ snprintf(control->name, sizeof(control->name), "AMDGPU SMU %d", i);
+ i2c_set_adapdata(control, smu_i2c);
+
+ res = i2c_add_adapter(control);
+ if (res) {
+ DRM_ERROR("Failed to register hw i2c, err: %d\n", res);
+ goto Out_err;
+ }
+ }
- control->owner = THIS_MODULE;
- control->class = I2C_CLASS_HWMON;
- control->dev.parent = &adev->pdev->dev;
- control->algo = &arcturus_i2c_algo;
- control->quirks = &arcturus_i2c_control_quirks;
- snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
+ adev->pm.ras_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter;
+ adev->pm.fru_eeprom_i2c_bus = &adev->pm.smu_i2c[1].adapter;
- res = i2c_add_adapter(control);
- if (res)
- DRM_ERROR("Failed to register hw i2c, err: %d\n", res);
+ return 0;
+Out_err:
+ for ( ; i >= 0; i--) {
+ struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i];
+ struct i2c_adapter *control = &smu_i2c->adapter;
+ i2c_del_adapter(control);
+ }
return res;
}
-static void arcturus_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control)
+static void arcturus_i2c_control_fini(struct smu_context *smu)
{
- i2c_del_adapter(control);
+ struct amdgpu_device *adev = smu->adev;
+ int i;
+
+ for (i = 0; i < MAX_SMU_I2C_BUSES; i++) {
+ struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i];
+ struct i2c_adapter *control = &smu_i2c->adapter;
+
+ i2c_del_adapter(control);
+ }
+ adev->pm.ras_eeprom_i2c_bus = NULL;
+ adev->pm.fru_eeprom_i2c_bus = NULL;
}
static void arcturus_get_unique_id(struct smu_context *smu)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
index 84834c24a7e9..16a5d4d35981 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
@@ -27,6 +27,7 @@
#include <linux/pci.h>
#include <linux/i2c.h>
#include "amdgpu.h"
+#include "amdgpu_dpm.h"
#include "amdgpu_smu.h"
#include "atomfirmware.h"
#include "amdgpu_atomfirmware.h"
@@ -57,8 +58,6 @@
#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) | \
@@ -2746,7 +2745,8 @@ static ssize_t navi10_get_legacy_gpu_metrics(struct smu_context *smu,
static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap,
struct i2c_msg *msg, int num_msgs)
{
- struct amdgpu_device *adev = to_amdgpu_device(i2c_adap);
+ struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(i2c_adap);
+ struct amdgpu_device *adev = smu_i2c->adev;
struct smu_context *smu = adev->powerplay.pp_handle;
struct smu_table_context *smu_table = &smu->smu_table;
struct smu_table *table = &smu_table->driver_table;
@@ -2758,7 +2758,7 @@ static int navi10_i2c_xfer(struct i2c_adapter *i2c_adap,
if (!req)
return -ENOMEM;
- req->I2CcontrollerPort = 0;
+ req->I2CcontrollerPort = smu_i2c->port;
req->I2CSpeed = I2C_SPEED_FAST_400K;
req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */
dir = msg[0].flags & I2C_M_RD;
@@ -2836,28 +2836,60 @@ static const struct i2c_adapter_quirks navi10_i2c_control_quirks = {
.max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2,
};
-static int navi10_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control)
+static int navi10_i2c_control_init(struct smu_context *smu)
{
- struct amdgpu_device *adev = to_amdgpu_device(control);
- int res;
+ struct amdgpu_device *adev = smu->adev;
+ int res, i;
+
+ for (i = 0; i < MAX_SMU_I2C_BUSES; i++) {
+ struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i];
+ struct i2c_adapter *control = &smu_i2c->adapter;
+
+ smu_i2c->adev = adev;
+ smu_i2c->port = i;
+ mutex_init(&smu_i2c->mutex);
+ control->owner = THIS_MODULE;
+ control->class = I2C_CLASS_HWMON;
+ control->dev.parent = &adev->pdev->dev;
+ control->algo = &navi10_i2c_algo;
+ snprintf(control->name, sizeof(control->name), "AMDGPU SMU %d", i);
+ control->quirks = &navi10_i2c_control_quirks;
+ i2c_set_adapdata(control, smu_i2c);
+
+ res = i2c_add_adapter(control);
+ if (res) {
+ DRM_ERROR("Failed to register hw i2c, err: %d\n", res);
+ goto Out_err;
+ }
+ }
- control->owner = THIS_MODULE;
- control->class = I2C_CLASS_HWMON;
- control->dev.parent = &adev->pdev->dev;
- control->algo = &navi10_i2c_algo;
- snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
- control->quirks = &navi10_i2c_control_quirks;
+ adev->pm.ras_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter;
+ adev->pm.fru_eeprom_i2c_bus = &adev->pm.smu_i2c[1].adapter;
- res = i2c_add_adapter(control);
- if (res)
- DRM_ERROR("Failed to register hw i2c, err: %d\n", res);
+ return 0;
+Out_err:
+ for ( ; i >= 0; i--) {
+ struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i];
+ struct i2c_adapter *control = &smu_i2c->adapter;
+ i2c_del_adapter(control);
+ }
return res;
}
-static void navi10_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control)
+static void navi10_i2c_control_fini(struct smu_context *smu)
{
- i2c_del_adapter(control);
+ struct amdgpu_device *adev = smu->adev;
+ int i;
+
+ for (i = 0; i < MAX_SMU_I2C_BUSES; i++) {
+ struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i];
+ struct i2c_adapter *control = &smu_i2c->adapter;
+
+ i2c_del_adapter(control);
+ }
+ adev->pm.ras_eeprom_i2c_bus = NULL;
+ adev->pm.fru_eeprom_i2c_bus = NULL;
}
static ssize_t navi10_get_gpu_metrics(struct smu_context *smu,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
index dcd35c68e59b..1c71ea97d06f 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
@@ -27,6 +27,7 @@
#include <linux/pci.h>
#include <linux/i2c.h>
#include "amdgpu.h"
+#include "amdgpu_dpm.h"
#include "amdgpu_smu.h"
#include "atomfirmware.h"
#include "amdgpu_atomfirmware.h"
@@ -59,8 +60,6 @@
#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) | \
@@ -3441,7 +3440,8 @@ static void sienna_cichlid_dump_pptable(struct smu_context *smu)
static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap,
struct i2c_msg *msg, int num_msgs)
{
- struct amdgpu_device *adev = to_amdgpu_device(i2c_adap);
+ struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(i2c_adap);
+ struct amdgpu_device *adev = smu_i2c->adev;
struct smu_context *smu = adev->powerplay.pp_handle;
struct smu_table_context *smu_table = &smu->smu_table;
struct smu_table *table = &smu_table->driver_table;
@@ -3453,7 +3453,7 @@ static int sienna_cichlid_i2c_xfer(struct i2c_adapter *i2c_adap,
if (!req)
return -ENOMEM;
- req->I2CcontrollerPort = 1;
+ req->I2CcontrollerPort = smu_i2c->port;
req->I2CSpeed = I2C_SPEED_FAST_400K;
req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */
dir = msg[0].flags & I2C_M_RD;
@@ -3531,28 +3531,61 @@ static const struct i2c_adapter_quirks sienna_cichlid_i2c_control_quirks = {
.max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2,
};
-static int sienna_cichlid_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control)
+static int sienna_cichlid_i2c_control_init(struct smu_context *smu)
{
- struct amdgpu_device *adev = to_amdgpu_device(control);
- int res;
-
- control->owner = THIS_MODULE;
- control->class = I2C_CLASS_HWMON;
- control->dev.parent = &adev->pdev->dev;
- control->algo = &sienna_cichlid_i2c_algo;
- snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
- control->quirks = &sienna_cichlid_i2c_control_quirks;
+ struct amdgpu_device *adev = smu->adev;
+ int res, i;
+
+ for (i = 0; i < MAX_SMU_I2C_BUSES; i++) {
+ struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i];
+ struct i2c_adapter *control = &smu_i2c->adapter;
+
+ smu_i2c->adev = adev;
+ smu_i2c->port = i;
+ mutex_init(&smu_i2c->mutex);
+ control->owner = THIS_MODULE;
+ control->class = I2C_CLASS_HWMON;
+ control->dev.parent = &adev->pdev->dev;
+ control->algo = &sienna_cichlid_i2c_algo;
+ snprintf(control->name, sizeof(control->name), "AMDGPU SMU %d", i);
+ control->quirks = &sienna_cichlid_i2c_control_quirks;
+ i2c_set_adapdata(control, smu_i2c);
+
+ res = i2c_add_adapter(control);
+ if (res) {
+ DRM_ERROR("Failed to register hw i2c, err: %d\n", res);
+ goto Out_err;
+ }
+ }
+ /* assign the buses used for the FRU EEPROM and RAS EEPROM */
+ /* XXX ideally this would be something in a vbios data table */
+ adev->pm.ras_eeprom_i2c_bus = &adev->pm.smu_i2c[1].adapter;
+ adev->pm.fru_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter;
- res = i2c_add_adapter(control);
- if (res)
- DRM_ERROR("Failed to register hw i2c, err: %d\n", res);
+ return 0;
+Out_err:
+ for ( ; i >= 0; i--) {
+ struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i];
+ struct i2c_adapter *control = &smu_i2c->adapter;
+ i2c_del_adapter(control);
+ }
return res;
}
-static void sienna_cichlid_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control)
+static void sienna_cichlid_i2c_control_fini(struct smu_context *smu)
{
- i2c_del_adapter(control);
+ struct amdgpu_device *adev = smu->adev;
+ int i;
+
+ for (i = 0; i < MAX_SMU_I2C_BUSES; i++) {
+ struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i];
+ struct i2c_adapter *control = &smu_i2c->adapter;
+
+ i2c_del_adapter(control);
+ }
+ adev->pm.ras_eeprom_i2c_bus = NULL;
+ adev->pm.fru_eeprom_i2c_bus = NULL;
}
static ssize_t sienna_cichlid_get_gpu_metrics(struct smu_context *smu,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
index 8c02adbf446a..450049bcedcb 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/aldebaran_ppt.c
@@ -25,6 +25,7 @@
#include <linux/firmware.h>
#include "amdgpu.h"
+#include "amdgpu_dpm.h"
#include "amdgpu_smu.h"
#include "atomfirmware.h"
#include "amdgpu_atomfirmware.h"
@@ -56,8 +57,6 @@
#undef pr_info
#undef pr_debug
-#define to_amdgpu_device(x) (container_of(x, struct amdgpu_device, pm.smu_i2c))
-
#define ALDEBARAN_FEA_MAP(smu_feature, aldebaran_feature) \
[smu_feature] = {1, (aldebaran_feature)}
@@ -1465,7 +1464,8 @@ static bool aldebaran_is_dpm_running(struct smu_context *smu)
static int aldebaran_i2c_xfer(struct i2c_adapter *i2c_adap,
struct i2c_msg *msg, int num_msgs)
{
- struct amdgpu_device *adev = to_amdgpu_device(i2c_adap);
+ struct amdgpu_smu_i2c_bus *smu_i2c = i2c_get_adapdata(i2c_adap);
+ struct amdgpu_device *adev = smu_i2c->adev;
struct smu_context *smu = adev->powerplay.pp_handle;
struct smu_table_context *smu_table = &smu->smu_table;
struct smu_table *table = &smu_table->driver_table;
@@ -1477,7 +1477,7 @@ static int aldebaran_i2c_xfer(struct i2c_adapter *i2c_adap,
if (!req)
return -ENOMEM;
- req->I2CcontrollerPort = 0;
+ req->I2CcontrollerPort = smu_i2c->port;
req->I2CSpeed = I2C_SPEED_FAST_400K;
req->SlaveAddress = msg[0].addr << 1; /* wants an 8-bit address */
dir = msg[0].flags & I2C_M_RD;
@@ -1555,28 +1555,52 @@ static const struct i2c_adapter_quirks aldebaran_i2c_control_quirks = {
.max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2,
};
-static int aldebaran_i2c_control_init(struct smu_context *smu, struct i2c_adapter *control)
+static int aldebaran_i2c_control_init(struct smu_context *smu)
{
- struct amdgpu_device *adev = to_amdgpu_device(control);
+ struct amdgpu_device *adev = smu->adev;
+ struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[0];
+ struct i2c_adapter *control = &smu_i2c->adapter;
int res;
+ smu_i2c->adev = adev;
+ smu_i2c->port = 0;
+ mutex_init(&smu_i2c->mutex);
control->owner = THIS_MODULE;
control->class = I2C_CLASS_SPD;
control->dev.parent = &adev->pdev->dev;
control->algo = &aldebaran_i2c_algo;
- snprintf(control->name, sizeof(control->name), "AMDGPU SMU");
+ snprintf(control->name, sizeof(control->name), "AMDGPU SMU 0");
control->quirks = &aldebaran_i2c_control_quirks;
+ i2c_set_adapdata(control, smu_i2c);
res = i2c_add_adapter(control);
- if (res)
+ if (res) {
DRM_ERROR("Failed to register hw i2c, err: %d\n", res);
+ goto Out_err;
+ }
+
+ adev->pm.ras_eeprom_i2c_bus = &adev->pm.smu_i2c[0].adapter;
+
+ return 0;
+Out_err:
+ i2c_del_adapter(control);
return res;
}
-static void aldebaran_i2c_control_fini(struct smu_context *smu, struct i2c_adapter *control)
+static void aldebaran_i2c_control_fini(struct smu_context *smu)
{
- i2c_del_adapter(control);
+ struct amdgpu_device *adev = smu->adev;
+ int i;
+
+ for (i = 0; i < MAX_SMU_I2C_BUSES; i++) {
+ struct amdgpu_smu_i2c_bus *smu_i2c = &adev->pm.smu_i2c[i];
+ struct i2c_adapter *control = &smu_i2c->adapter;
+
+ i2c_del_adapter(control);
+ }
+ adev->pm.ras_eeprom_i2c_bus = NULL;
+ adev->pm.fru_eeprom_i2c_bus = NULL;
}
static void aldebaran_get_unique_id(struct smu_context *smu)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h
index 59f9cfff3d61..a290b5789195 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_internal.h
@@ -78,8 +78,8 @@
#define smu_dump_pptable(smu) smu_ppt_funcs(dump_pptable, 0, smu)
#define smu_update_pcie_parameters(smu, pcie_gen_cap, pcie_width_cap) smu_ppt_funcs(update_pcie_parameters, 0, smu, pcie_gen_cap, pcie_width_cap)
#define smu_set_power_source(smu, power_src) smu_ppt_funcs(set_power_source, 0, smu, power_src)
-#define smu_i2c_init(smu, control) smu_ppt_funcs(i2c_init, 0, smu, control)
-#define smu_i2c_fini(smu, control) smu_ppt_funcs(i2c_fini, 0, smu, control)
+#define smu_i2c_init(smu) smu_ppt_funcs(i2c_init, 0, smu)
+#define smu_i2c_fini(smu) smu_ppt_funcs(i2c_fini, 0, smu)
#define smu_get_unique_id(smu) smu_ppt_funcs(get_unique_id, 0, smu)
#define smu_log_thermal_throttling(smu) smu_ppt_funcs(log_thermal_throttling_event, 0, smu)
#define smu_get_asic_power_limits(smu, current, default, max) smu_ppt_funcs(get_power_limit, 0, smu, current, default, max)