Skip to content

Commit

Permalink
HID: amd_sfh: Extend driver capabilities for multi-generation support
Browse files Browse the repository at this point in the history
Initial driver support only covered the first generation of SFH
platforms. In order to support the future generations introduce
ops selection to distinguish the different platforms.

Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
Reviewed-by: Nehal Shah <nehal-bakulchandra.shah@amd.com>
Reviewed-by: Shyam Sundar S K <Shyam-sundar.S-k@amd.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
  • Loading branch information
Basavaraj Natikar authored and Jiri Kosina committed Jun 24, 2021
1 parent 231bc53 commit f264481
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 6 deletions.
4 changes: 2 additions & 2 deletions drivers/hid/amd-sfh-hid/amd_sfh_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
rc = amdtp_hid_probe(cl_data->cur_hid_dev, cl_data);
if (rc)
return rc;
amd_start_sensor(privdata, info);
privdata->mp2_ops->start(privdata, info);
cl_data->sensor_sts[i] = 1;
}
privdata->cl_data = cl_data;
Expand Down Expand Up @@ -230,7 +230,7 @@ int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata)
int i;

for (i = 0; i < cl_data->num_hid_devices; i++)
amd_stop_sensor(privdata, i);
privdata->mp2_ops->stop(privdata, i);

cancel_delayed_work_sync(&cl_data->work);
cancel_delayed_work_sync(&cl_data->work_buffer);
Expand Down
80 changes: 76 additions & 4 deletions drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,48 @@ static int sensor_mask_override = -1;
module_param_named(sensor_mask, sensor_mask_override, int, 0444);
MODULE_PARM_DESC(sensor_mask, "override the detected sensors mask");

static void amd_start_sensor_v2(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info)
{
union sfh_cmd_base cmd_base;

cmd_base.ul = 0;
cmd_base.cmd_v2.cmd_id = ENABLE_SENSOR;
cmd_base.cmd_v2.period = info.period;
cmd_base.cmd_v2.sensor_id = info.sensor_idx;
cmd_base.cmd_v2.length = 16;

if (info.sensor_idx == als_idx)
cmd_base.cmd_v2.mem_type = USE_C2P_REG;

writeq(info.dma_address, privdata->mmio + AMD_C2P_MSG1);
writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
}

static void amd_stop_sensor_v2(struct amd_mp2_dev *privdata, u16 sensor_idx)
{
union sfh_cmd_base cmd_base;

cmd_base.ul = 0;
cmd_base.cmd_v2.cmd_id = DISABLE_SENSOR;
cmd_base.cmd_v2.period = 0;
cmd_base.cmd_v2.sensor_id = sensor_idx;
cmd_base.cmd_v2.length = 16;

writeq(0x0, privdata->mmio + AMD_C2P_MSG2);
writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
}

static void amd_stop_all_sensor_v2(struct amd_mp2_dev *privdata)
{
union sfh_cmd_base cmd_base;

cmd_base.cmd_v2.cmd_id = STOP_ALL_SENSORS;
cmd_base.cmd_v2.period = 0;
cmd_base.cmd_v2.sensor_id = 0;

writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
}

void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info)
{
union sfh_cmd_param cmd_param;
Expand Down Expand Up @@ -98,7 +140,6 @@ int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id)
{
int activestatus, num_of_sensors = 0;
const struct dmi_system_id *dmi_id;
u32 activecontrolstatus;

if (sensor_mask_override == -1) {
dmi_id = dmi_first_match(dmi_sensor_mask_overrides);
Expand All @@ -109,8 +150,7 @@ int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id)
if (sensor_mask_override >= 0) {
activestatus = sensor_mask_override;
} else {
activecontrolstatus = readl(privdata->mmio + AMD_P2C_MSG3);
activestatus = activecontrolstatus >> 4;
activestatus = privdata->mp2_acs >> 4;
}

if (ACEL_EN & activestatus)
Expand All @@ -130,8 +170,38 @@ int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id)

static void amd_mp2_pci_remove(void *privdata)
{
struct amd_mp2_dev *mp2 = privdata;
amd_sfh_hid_client_deinit(privdata);
amd_stop_all_sensors(privdata);
mp2->mp2_ops->stop_all(mp2);
}

static const struct amd_mp2_ops amd_sfh_ops_v2 = {
.start = amd_start_sensor_v2,
.stop = amd_stop_sensor_v2,
.stop_all = amd_stop_all_sensor_v2,
};

static const struct amd_mp2_ops amd_sfh_ops = {
.start = amd_start_sensor,
.stop = amd_stop_sensor,
.stop_all = amd_stop_all_sensors,
};

static void mp2_select_ops(struct amd_mp2_dev *privdata)
{
u8 acs;

privdata->mp2_acs = readl(privdata->mmio + AMD_P2C_MSG3);
acs = privdata->mp2_acs & GENMASK(3, 0);

switch (acs) {
case V2_STATUS:
privdata->mp2_ops = &amd_sfh_ops_v2;
break;
default:
privdata->mp2_ops = &amd_sfh_ops;
break;
}
}

static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
Expand Down Expand Up @@ -164,6 +234,8 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
if (rc)
return rc;

mp2_select_ops(privdata);

return amd_sfh_hid_client_init(privdata);
}

Expand Down
27 changes: 27 additions & 0 deletions drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,13 @@
#define AMD_C2P_MSG1 0x10504
#define AMD_C2P_MSG2 0x10508

#define AMD_C2P_MSG(regno) (0x10500 + ((regno) * 4))

/* MP2 P2C Message Registers */
#define AMD_P2C_MSG3 0x1068C /* Supported Sensors info */

#define V2_STATUS 0x2

/* SFH Command register */
union sfh_cmd_base {
u32 ul;
Expand All @@ -33,6 +37,15 @@ union sfh_cmd_base {
u32 sensor_id : 8;
u32 period : 16;
} s;
struct {
u32 cmd_id : 4;
u32 intr_enable : 1;
u32 rsvd1 : 3;
u32 length : 7;
u32 mem_type : 1;
u32 sensor_id : 8;
u32 period : 8;
} cmd_v2;
};

union sfh_cmd_param {
Expand Down Expand Up @@ -61,6 +74,9 @@ struct amd_mp2_dev {
struct pci_dev *pdev;
struct amdtp_cl_data *cl_data;
void __iomem *mmio;
const struct amd_mp2_ops *mp2_ops;
/* mp2 active control status */
u32 mp2_acs;
};

struct amd_mp2_sensor_info {
Expand All @@ -69,10 +85,21 @@ struct amd_mp2_sensor_info {
dma_addr_t dma_address;
};

enum mem_use_type {
USE_DRAM,
USE_C2P_REG,
};

void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info);
void amd_stop_sensor(struct amd_mp2_dev *privdata, u16 sensor_idx);
void amd_stop_all_sensors(struct amd_mp2_dev *privdata);
int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id);
int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata);
int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata);

struct amd_mp2_ops {
void (*start)(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info);
void (*stop)(struct amd_mp2_dev *privdata, u16 sensor_idx);
void (*stop_all)(struct amd_mp2_dev *privdata);
};
#endif

0 comments on commit f264481

Please sign in to comment.