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.Chai@amd.com> Acked-by: Evan Quan <evan.quan@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Reviewed-by: Hawking Zhang <Hawking.Zhang@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
8813381a62
commit
ccc4200cfb
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue