[AMD Official Use Only - General]

Fix typo.

Regards,
Hawking

-----Original Message-----
From: amd-gfx <amd-gfx-boun...@lists.freedesktop.org> On Behalf Of Zhang, 
Hawking
Sent: Wednesday, July 20, 2022 11:26
To: Chai, Thomas <yipeng.c...@amd.com>; amd-gfx@lists.freedesktop.org
Cc: Deucher, Alexander <alexander.deuc...@amd.com>; Zhou1, Tao 
<tao.zh...@amd.com>; Clements, John <john.cleme...@amd.com>; Quan, Evan 
<evan.q...@amd.com>; Li, Candice <candice...@amd.com>
Subject: RE: [PATCH] drm/pm/swsmu: add ras eeprom i2c function for smu13 v13_0_0

[AMD Official Use Only - General]

Reviewed-by: Hawking Zhang <hawking.zh...@amd.com>

Regards,
Hawking
-----Original Message-----
From: Chai, Thomas <yipeng.c...@amd.com> 
Sent: Wednesday, July 20, 2022 10:49
To: amd-gfx@lists.freedesktop.org
Cc: Chai, Thomas <yipeng.c...@amd.com>; Zhang, Hawking <hawking.zh...@amd.com>; 
Zhou1, Tao <tao.zh...@amd.com>; Clements, John <john.cleme...@amd.com>; Li, 
Candice <candice...@amd.com>; Chai, Thomas <yipeng.c...@amd.com>; Quan, Evan 
<evan.q...@amd.com>; Deucher, Alexander <alexander.deuc...@amd.com>
Subject: [PATCH] drm/pm/swsmu: add ras eeprom i2c function for smu13 v13_0_0

Add ras eeprom i2c function for smu13 v13_0_0.

Signed-off-by: YiPeng Chai <yipeng.c...@amd.com>
Acked-by: Evan Quan <evan.q...@amd.com>
Acked-by: Alex Deucher <alexander.deuc...@amd.com>
---
 .../drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c  | 157 ++++++++++++++++++
 1 file changed, 157 insertions(+)

diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c 
b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
index ce2fa04e3926..2b83191e8006 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
@@ -196,6 +196,7 @@ static struct cmn2asic_mapping 
smu_v13_0_0_table_map[SMU_TABLE_COUNT] = {
        TAB_MAP(DRIVER_SMU_CONFIG),
        TAB_MAP(ACTIVITY_MONITOR_COEFF),
        [SMU_TABLE_COMBO_PPTABLE] = {1, TABLE_COMBO_PPTABLE},
+       TAB_MAP(I2C_COMMANDS),
 };
 
 static struct cmn2asic_mapping smu_v13_0_0_pwr_src_map[SMU_POWER_SOURCE_COUNT] 
= { @@ -1606,9 +1607,165 @@ static bool 
smu_v13_0_0_is_mode1_reset_supported(struct smu_context *smu)
        return true;
 }
 
+static int smu_v13_0_0_i2c_xfer(struct i2c_adapter *i2c_adap,
+                                  struct i2c_msg *msg, int num_msgs) {
+       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;
+       SwI2cRequest_t *req, *res = (SwI2cRequest_t *)table->cpu_addr;
+       int i, j, r, c;
+       u16 dir;
+
+       if (!adev->pm.dpm_enabled)
+               return -EBUSY;
+
+       req = kzalloc(sizeof(*req), GFP_KERNEL);
+       if (!req)
+               return -ENOMEM;
+
+       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;
+
+       for (c = i = 0; i < num_msgs; i++) {
+               for (j = 0; j < msg[i].len; j++, c++) {
+                       SwI2cCmd_t *cmd = &req->SwI2cCmds[c];
+
+                       if (!(msg[i].flags & I2C_M_RD)) {
+                               /* write */
+                               cmd->CmdConfig |= CMDCONFIG_READWRITE_MASK;
+                               cmd->ReadWriteData = msg[i].buf[j];
+                       }
+
+                       if ((dir ^ msg[i].flags) & I2C_M_RD) {
+                               /* The direction changes.
+                                */
+                               dir = msg[i].flags & I2C_M_RD;
+                               cmd->CmdConfig |= CMDCONFIG_RESTART_MASK;
+                       }
+
+                       req->NumCmds++;
+
+                       /*
+                        * Insert STOP if we are at the last byte of either last
+                        * message for the transaction or the client explicitly
+                        * requires a STOP at this particular message.
+                        */
+                       if ((j == msg[i].len - 1) &&
+                           ((i == num_msgs - 1) || (msg[i].flags & 
I2C_M_STOP))) {
+                               cmd->CmdConfig &= ~CMDCONFIG_RESTART_MASK;
+                               cmd->CmdConfig |= CMDCONFIG_STOP_MASK;
+                       }
+               }
+       }
+       mutex_lock(&adev->pm.mutex);
+       r = smu_cmn_update_table(smu, SMU_TABLE_I2C_COMMANDS, 0, req, true);
+       mutex_unlock(&adev->pm.mutex);
+       if (r)
+               goto fail;
+
+       for (c = i = 0; i < num_msgs; i++) {
+               if (!(msg[i].flags & I2C_M_RD)) {
+                       c += msg[i].len;
+                       continue;
+               }
+               for (j = 0; j < msg[i].len; j++, c++) {
+                       SwI2cCmd_t *cmd = &res->SwI2cCmds[c];
+
+                       msg[i].buf[j] = cmd->ReadWriteData;
+               }
+       }
+       r = num_msgs;
+fail:
+       kfree(req);
+       return r;
+}
+
+static u32 smu_v13_0_0_i2c_func(struct i2c_adapter *adap) {
+       return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; }
+
+static const struct i2c_algorithm smu_v13_0_0_i2c_algo = {
+       .master_xfer = smu_v13_0_0_i2c_xfer,
+       .functionality = smu_v13_0_0_i2c_func, };
+
+static const struct i2c_adapter_quirks smu_v13_0_0_i2c_control_quirks = {
+       .flags = I2C_AQ_COMB | I2C_AQ_COMB_SAME_ADDR | I2C_AQ_NO_ZERO_LEN,
+       .max_read_len  = MAX_SW_I2C_COMMANDS,
+       .max_write_len = MAX_SW_I2C_COMMANDS,
+       .max_comb_1st_msg_len = 2,
+       .max_comb_2nd_msg_len = MAX_SW_I2C_COMMANDS - 2, };
+
+static int smu_v13_0_0_i2c_control_init(struct smu_context *smu) {
+       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_SPD;
+               control->dev.parent = &adev->pdev->dev;
+               control->algo = &smu_v13_0_0_i2c_algo;
+               snprintf(control->name, sizeof(control->name), "AMDGPU SMU %d", 
i);
+               control->quirks = &smu_v13_0_0_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;
+
+       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 smu_v13_0_0_i2c_control_fini(struct smu_context *smu) {
+       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 const struct pptable_funcs smu_v13_0_0_ppt_funcs = {
        .get_allowed_feature_mask = smu_v13_0_0_get_allowed_feature_mask,
        .set_default_dpm_table = smu_v13_0_0_set_default_dpm_table,
+       .i2c_init = smu_v13_0_0_i2c_control_init,
+       .i2c_fini = smu_v13_0_0_i2c_control_fini,
        .is_dpm_running = smu_v13_0_0_is_dpm_running,
        .dump_pptable = smu_v13_0_0_dump_pptable,
        .init_microcode = smu_v13_0_init_microcode,
--
2.25.1

Reply via email to