From patchwork Tue Jul 6 08:04:34 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kai-Heng Feng X-Patchwork-Id: 1501066 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (no SPF record) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4GJw861YXhz9sW8; Tue, 6 Jul 2021 18:04:54 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1m0g4Y-0003nS-HA; Tue, 06 Jul 2021 08:04:50 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.86_2) (envelope-from ) id 1m0g4W-0003mh-CJ for kernel-team@lists.ubuntu.com; Tue, 06 Jul 2021 08:04:48 +0000 Received: from 1.general.khfeng.us.vpn ([10.172.68.174] helo=localhost) by youngberry.canonical.com with esmtpsa (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.93) (envelope-from ) id 1m0g4V-0005VR-HN for kernel-team@lists.ubuntu.com; Tue, 06 Jul 2021 08:04:48 +0000 From: Kai-Heng Feng To: kernel-team@lists.ubuntu.com Subject: [PATCH 1/3] HID: amd_sfh: Extend driver capabilities for multi-generation support Date: Tue, 6 Jul 2021 16:04:34 +0800 Message-Id: <20210706080436.291606-3-kai.heng.feng@canonical.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210706080436.291606-1-kai.heng.feng@canonical.com> References: <20210706080436.291606-1-kai.heng.feng@canonical.com> MIME-Version: 1.0 X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Basavaraj Natikar BugLink: https://bugs.launchpad.net/bugs/1934747 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 Reviewed-by: Nehal Shah Reviewed-by: Shyam Sundar S K Signed-off-by: Jiri Kosina (cherry picked from commit f264481ad614dfd9aae59eeefa5fc664cdf173ae linux-next) Signed-off-by: Kai-Heng Feng --- drivers/hid/amd-sfh-hid/amd_sfh_client.c | 4 +- drivers/hid/amd-sfh-hid/amd_sfh_pcie.c | 80 ++++++++++++++++++++++-- drivers/hid/amd-sfh-hid/amd_sfh_pcie.h | 27 ++++++++ 3 files changed, 105 insertions(+), 6 deletions(-) diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_client.c b/drivers/hid/amd-sfh-hid/amd_sfh_client.c index 3589d9945da1..d3d5dcec7cf1 100644 --- a/drivers/hid/amd-sfh-hid/amd_sfh_client.c +++ b/drivers/hid/amd-sfh-hid/amd_sfh_client.c @@ -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); diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c index ddecc84fd6f0..48ff54dc5d70 100644 --- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c +++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c @@ -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); } diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h index 489415f7c22c..6297d78c7aef 100644 --- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h +++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h @@ -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; @@ -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