Commit f264481a authored by Basavaraj Natikar's avatar Basavaraj Natikar Committed by Jiri Kosina

HID: amd_sfh: Extend driver capabilities for multi-generation support

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: default avatarBasavaraj Natikar <Basavaraj.Natikar@amd.com>
Reviewed-by: default avatarNehal Shah <nehal-bakulchandra.shah@amd.com>
Reviewed-by: default avatarShyam Sundar S K <Shyam-sundar.S-k@amd.com>
Signed-off-by: default avatarJiri Kosina <jkosina@suse.cz>
parent 231bc539
...@@ -202,7 +202,7 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata) ...@@ -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); rc = amdtp_hid_probe(cl_data->cur_hid_dev, cl_data);
if (rc) if (rc)
return rc; return rc;
amd_start_sensor(privdata, info); privdata->mp2_ops->start(privdata, info);
cl_data->sensor_sts[i] = 1; cl_data->sensor_sts[i] = 1;
} }
privdata->cl_data = cl_data; privdata->cl_data = cl_data;
...@@ -230,7 +230,7 @@ int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata) ...@@ -230,7 +230,7 @@ int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata)
int i; int i;
for (i = 0; i < cl_data->num_hid_devices; 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);
cancel_delayed_work_sync(&cl_data->work_buffer); cancel_delayed_work_sync(&cl_data->work_buffer);
......
...@@ -30,6 +30,48 @@ static int sensor_mask_override = -1; ...@@ -30,6 +30,48 @@ static int sensor_mask_override = -1;
module_param_named(sensor_mask, sensor_mask_override, int, 0444); module_param_named(sensor_mask, sensor_mask_override, int, 0444);
MODULE_PARM_DESC(sensor_mask, "override the detected sensors mask"); 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) void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info)
{ {
union sfh_cmd_param cmd_param; union sfh_cmd_param cmd_param;
...@@ -98,7 +140,6 @@ int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id) ...@@ -98,7 +140,6 @@ int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id)
{ {
int activestatus, num_of_sensors = 0; int activestatus, num_of_sensors = 0;
const struct dmi_system_id *dmi_id; const struct dmi_system_id *dmi_id;
u32 activecontrolstatus;
if (sensor_mask_override == -1) { if (sensor_mask_override == -1) {
dmi_id = dmi_first_match(dmi_sensor_mask_overrides); dmi_id = dmi_first_match(dmi_sensor_mask_overrides);
...@@ -109,8 +150,7 @@ int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id) ...@@ -109,8 +150,7 @@ int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id)
if (sensor_mask_override >= 0) { if (sensor_mask_override >= 0) {
activestatus = sensor_mask_override; activestatus = sensor_mask_override;
} else { } else {
activecontrolstatus = readl(privdata->mmio + AMD_P2C_MSG3); activestatus = privdata->mp2_acs >> 4;
activestatus = activecontrolstatus >> 4;
} }
if (ACEL_EN & activestatus) if (ACEL_EN & activestatus)
...@@ -130,8 +170,38 @@ int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id) ...@@ -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) static void amd_mp2_pci_remove(void *privdata)
{ {
struct amd_mp2_dev *mp2 = privdata;
amd_sfh_hid_client_deinit(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) static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
...@@ -164,6 +234,8 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i ...@@ -164,6 +234,8 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
if (rc) if (rc)
return rc; return rc;
mp2_select_ops(privdata);
return amd_sfh_hid_client_init(privdata); return amd_sfh_hid_client_init(privdata);
} }
......
...@@ -22,9 +22,13 @@ ...@@ -22,9 +22,13 @@
#define AMD_C2P_MSG1 0x10504 #define AMD_C2P_MSG1 0x10504
#define AMD_C2P_MSG2 0x10508 #define AMD_C2P_MSG2 0x10508
#define AMD_C2P_MSG(regno) (0x10500 + ((regno) * 4))
/* MP2 P2C Message Registers */ /* MP2 P2C Message Registers */
#define AMD_P2C_MSG3 0x1068C /* Supported Sensors info */ #define AMD_P2C_MSG3 0x1068C /* Supported Sensors info */
#define V2_STATUS 0x2
/* SFH Command register */ /* SFH Command register */
union sfh_cmd_base { union sfh_cmd_base {
u32 ul; u32 ul;
...@@ -33,6 +37,15 @@ union sfh_cmd_base { ...@@ -33,6 +37,15 @@ union sfh_cmd_base {
u32 sensor_id : 8; u32 sensor_id : 8;
u32 period : 16; u32 period : 16;
} s; } 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 { union sfh_cmd_param {
...@@ -61,6 +74,9 @@ struct amd_mp2_dev { ...@@ -61,6 +74,9 @@ struct amd_mp2_dev {
struct pci_dev *pdev; struct pci_dev *pdev;
struct amdtp_cl_data *cl_data; struct amdtp_cl_data *cl_data;
void __iomem *mmio; void __iomem *mmio;
const struct amd_mp2_ops *mp2_ops;
/* mp2 active control status */
u32 mp2_acs;
}; };
struct amd_mp2_sensor_info { struct amd_mp2_sensor_info {
...@@ -69,10 +85,21 @@ struct amd_mp2_sensor_info { ...@@ -69,10 +85,21 @@ struct amd_mp2_sensor_info {
dma_addr_t dma_address; 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_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_sensor(struct amd_mp2_dev *privdata, u16 sensor_idx);
void amd_stop_all_sensors(struct amd_mp2_dev *privdata); 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_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_init(struct amd_mp2_dev *privdata);
int amd_sfh_hid_client_deinit(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 #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment