HID: amd_sfh: Extend driver capabilities for multi-generation support
authorBasavaraj Natikar <Basavaraj.Natikar@amd.com>
Fri, 18 Jun 2021 08:18:36 +0000 (13:48 +0530)
committerJiri Kosina <jkosina@suse.cz>
Thu, 24 Jun 2021 12:28:03 +0000 (14:28 +0200)
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>
drivers/hid/amd-sfh-hid/amd_sfh_client.c
drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
drivers/hid/amd-sfh-hid/amd_sfh_pcie.h

index 3589d9945da1cb1b5b233ca4fedae504c8ef1d2b..d3d5dcec7cf10035d13c71ed61b7ee5f3067d8f8 100644 (file)
@@ -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;
@@ -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);
index ddecc84fd6f0d62d939df5fbe51bfb27ac051cb8..48ff54dc5d7062a1b3391f7195b52bb2d501de07 100644 (file)
@@ -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;
@@ -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);
@@ -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)
@@ -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)
@@ -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);
 }
 
index 489415f7c22ca1eb3c2713f5e207e37c48ae18c3..6297d78c7aef465f7155094e24e9c7812037f427 100644 (file)
 #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;
@@ -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 {
@@ -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 {
@@ -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