All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/11] Fixes and implementation of AMD SFH 1.1 functionality
@ 2022-07-12 18:18 Basavaraj Natikar
  2022-07-12 18:18 ` [PATCH 01/11] HID: amd_sfh: Add NULL check for hid device Basavaraj Natikar
                   ` (11 more replies)
  0 siblings, 12 replies; 13+ messages in thread
From: Basavaraj Natikar @ 2022-07-12 18:18 UTC (permalink / raw)
  To: jikos, benjamin.tissoires, linux-input; +Cc: Basavaraj Natikar

Changes includes fixes and support of new firmware (SFH 1.1) with new
PCI device ID to implement SFH1.1 functionality which is used by
newer AMD SOCs.

Basavaraj Natikar (11):
  HID: amd_sfh: Add NULL check for hid device
  HID: amd_sfh: Move common macros and structures
  HID: amd_sfh: Move request_list struct to header file
  HID: amd_sfh: Move request_list variable to client data
  HID: amd_sfh: Add descriptor operations in amd_mp2_ops
  HID: amd_sfh: Add PM operations in amd_mp2_ops
  HID: amd_sfh: Add remove operation in amd_mp2_ops
  HID: amd_sfh: Move global functions to static
  HID: amd_sfh: Move amd_sfh_work to common interface
  HID: amd_sfh: Move interrupt handling to common interface
  HID: amd_sfh: Implement SFH1.1 functionality

 drivers/hid/amd-sfh-hid/Makefile              |   3 +
 drivers/hid/amd-sfh-hid/amd_sfh_client.c      | 115 +++++--
 drivers/hid/amd-sfh-hid/amd_sfh_common.h      |  76 ++++
 drivers/hid/amd-sfh-hid/amd_sfh_hid.c         |  12 +-
 drivers/hid/amd-sfh-hid/amd_sfh_hid.h         |  12 +-
 drivers/hid/amd-sfh-hid/amd_sfh_pcie.c        |  75 ++--
 drivers/hid/amd-sfh-hid/amd_sfh_pcie.h        |  52 +--
 .../hid_descriptor/amd_sfh_hid_desc.c         |  17 +-
 .../hid_descriptor/amd_sfh_hid_desc.h         |   3 -
 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c | 300 ++++++++++++++++
 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c | 324 ++++++++++++++++++
 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.h |  26 ++
 .../amd-sfh-hid/sfh1_1/amd_sfh_interface.c    |  73 ++++
 .../amd-sfh-hid/sfh1_1/amd_sfh_interface.h    | 154 +++++++++
 14 files changed, 1099 insertions(+), 143 deletions(-)
 create mode 100644 drivers/hid/amd-sfh-hid/amd_sfh_common.h
 create mode 100644 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
 create mode 100644 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
 create mode 100644 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.h
 create mode 100644 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
 create mode 100644 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h

-- 
2.25.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH 01/11] HID: amd_sfh: Add NULL check for hid device
  2022-07-12 18:18 [PATCH 00/11] Fixes and implementation of AMD SFH 1.1 functionality Basavaraj Natikar
@ 2022-07-12 18:18 ` Basavaraj Natikar
  2022-07-12 18:18 ` [PATCH 02/11] HID: amd_sfh: Move common macros and structures Basavaraj Natikar
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Basavaraj Natikar @ 2022-07-12 18:18 UTC (permalink / raw)
  To: jikos, benjamin.tissoires, linux-input; +Cc: Basavaraj Natikar

On removal of hid device during SFH set report may cause NULL pointer
exception. Hence add NULL check for hid device before accessing.

Fixes: 4b2c53d93a4b ("SFH:Transport Driver to add support of AMD Sensor Fusion Hub (SFH)")
Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
---
 drivers/hid/amd-sfh-hid/amd_sfh_hid.c | 12 ++++++++----
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_hid.c b/drivers/hid/amd-sfh-hid/amd_sfh_hid.c
index 1089134030b0..1b18291fc5af 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_hid.c
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_hid.c
@@ -101,11 +101,15 @@ static int amdtp_wait_for_response(struct hid_device *hid)
 
 void amdtp_hid_wakeup(struct hid_device *hid)
 {
-	struct amdtp_hid_data *hid_data = hid->driver_data;
-	struct amdtp_cl_data *cli_data = hid_data->cli_data;
+	struct amdtp_hid_data *hid_data;
+	struct amdtp_cl_data *cli_data;
 
-	cli_data->request_done[cli_data->cur_hid_dev] = true;
-	wake_up_interruptible(&hid_data->hid_wait);
+	if (hid) {
+		hid_data = hid->driver_data;
+		cli_data = hid_data->cli_data;
+		cli_data->request_done[cli_data->cur_hid_dev] = true;
+		wake_up_interruptible(&hid_data->hid_wait);
+	}
 }
 
 static struct hid_ll_driver amdtp_hid_ll_driver = {
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 02/11] HID: amd_sfh: Move common macros and structures
  2022-07-12 18:18 [PATCH 00/11] Fixes and implementation of AMD SFH 1.1 functionality Basavaraj Natikar
  2022-07-12 18:18 ` [PATCH 01/11] HID: amd_sfh: Add NULL check for hid device Basavaraj Natikar
@ 2022-07-12 18:18 ` Basavaraj Natikar
  2022-07-12 18:18 ` [PATCH 03/11] HID: amd_sfh: Move request_list struct to header file Basavaraj Natikar
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Basavaraj Natikar @ 2022-07-12 18:18 UTC (permalink / raw)
  To: jikos, benjamin.tissoires, linux-input; +Cc: Basavaraj Natikar

Introduce common macros and structures to support multiple generations
of AMD SOCs, move them to amd_sfh_common.h.

Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
---
 drivers/hid/amd-sfh-hid/amd_sfh_common.h | 59 ++++++++++++++++++++++++
 drivers/hid/amd-sfh-hid/amd_sfh_pcie.h   | 42 +----------------
 2 files changed, 60 insertions(+), 41 deletions(-)
 create mode 100644 drivers/hid/amd-sfh-hid/amd_sfh_common.h

diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_common.h b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
new file mode 100644
index 000000000000..40da53d5efd0
--- /dev/null
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * AMD MP2 common macros and structures
+ *
+ * Copyright (c) 2022, Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Author: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
+ */
+#ifndef AMD_SFH_COMMON_H
+#define AMD_SFH_COMMON_H
+
+#include <linux/pci.h>
+#include "amd_sfh_hid.h"
+
+#define PCI_DEVICE_ID_AMD_MP2		0x15E4
+
+#define AMD_C2P_MSG(regno) (0x10500 + ((regno) * 4))
+#define AMD_P2C_MSG(regno) (0x10680 + ((regno) * 4))
+
+#define SENSOR_ENABLED			4
+#define SENSOR_DISABLED			5
+
+#define AMD_SFH_IDLE_LOOP		200
+
+enum cmd_id {
+	NO_OP,
+	ENABLE_SENSOR,
+	DISABLE_SENSOR,
+	STOP_ALL_SENSORS = 8,
+};
+
+struct amd_mp2_sensor_info {
+	u8 sensor_idx;
+	u32 period;
+	dma_addr_t dma_address;
+};
+
+struct amd_mp2_dev {
+	struct pci_dev *pdev;
+	struct amdtp_cl_data *cl_data;
+	void __iomem *mmio;
+	const struct amd_mp2_ops *mp2_ops;
+	struct amd_input_data in_data;
+	/* mp2 active control status */
+	u32 mp2_acs;
+};
+
+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);
+	int (*response)(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts);
+	void (*clear_intr)(struct amd_mp2_dev *privdata);
+	int (*init_intr)(struct amd_mp2_dev *privdata);
+	int (*discovery_status)(struct amd_mp2_dev *privdata);
+};
+
+#endif
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
index 8c760526132a..2feac14f5d3c 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
@@ -10,35 +10,20 @@
 #ifndef PCIE_MP2_AMD_H
 #define PCIE_MP2_AMD_H
 
-#include <linux/pci.h>
-#include "amd_sfh_hid.h"
-
-#define PCI_DEVICE_ID_AMD_MP2	0x15E4
-
-#define ENABLE_SENSOR		1
-#define DISABLE_SENSOR		2
-#define STOP_ALL_SENSORS	8
+#include "amd_sfh_common.h"
 
 /* MP2 C2P Message Registers */
 #define AMD_C2P_MSG0	0x10500
 #define AMD_C2P_MSG1	0x10504
 #define AMD_C2P_MSG2	0x10508
 
-#define AMD_C2P_MSG(regno) (0x10500 + ((regno) * 4))
-#define AMD_P2C_MSG(regno) (0x10680 + ((regno) * 4))
-
 /* MP2 P2C Message Registers */
 #define AMD_P2C_MSG3	0x1068C /* Supported Sensors info */
 
 #define V2_STATUS	0x2
 
-#define SENSOR_ENABLED     4
-#define SENSOR_DISABLED    5
-
 #define HPD_IDX		16
 
-#define AMD_SFH_IDLE_LOOP	200
-
 #define SENSOR_DISCOVERY_STATUS_MASK		GENMASK(5, 3)
 #define SENSOR_DISCOVERY_STATUS_SHIFT		3
 
@@ -96,22 +81,6 @@ enum sensor_idx {
 	als_idx = 19
 };
 
-struct amd_mp2_dev {
-	struct pci_dev *pdev;
-	struct amdtp_cl_data *cl_data;
-	void __iomem *mmio;
-	const struct amd_mp2_ops *mp2_ops;
-	struct amd_input_data in_data;
-	/* mp2 active control status */
-	u32 mp2_acs;
-};
-
-struct amd_mp2_sensor_info {
-	u8 sensor_idx;
-	u32 period;
-	dma_addr_t dma_address;
-};
-
 enum mem_use_type {
 	USE_DRAM,
 	USE_C2P_REG,
@@ -140,13 +109,4 @@ void amd_mp2_suspend(struct amd_mp2_dev *mp2);
 void amd_mp2_resume(struct amd_mp2_dev *mp2);
 const char *get_sensor_name(int idx);
 
-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);
-	 int (*response)(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts);
-	 void (*clear_intr)(struct amd_mp2_dev *privdata);
-	 int (*init_intr)(struct amd_mp2_dev *privdata);
-	 int (*discovery_status)(struct amd_mp2_dev *privdata);
-};
 #endif
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 03/11] HID: amd_sfh: Move request_list struct to header file
  2022-07-12 18:18 [PATCH 00/11] Fixes and implementation of AMD SFH 1.1 functionality Basavaraj Natikar
  2022-07-12 18:18 ` [PATCH 01/11] HID: amd_sfh: Add NULL check for hid device Basavaraj Natikar
  2022-07-12 18:18 ` [PATCH 02/11] HID: amd_sfh: Move common macros and structures Basavaraj Natikar
@ 2022-07-12 18:18 ` Basavaraj Natikar
  2022-07-12 18:18 ` [PATCH 04/11] HID: amd_sfh: Move request_list variable to client data Basavaraj Natikar
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Basavaraj Natikar @ 2022-07-12 18:18 UTC (permalink / raw)
  To: jikos, benjamin.tissoires, linux-input; +Cc: Basavaraj Natikar

request_list structure can be used in multiple files to support all
AMD SOCs. Hence move request_list structure to header file.

Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
---
 drivers/hid/amd-sfh-hid/amd_sfh_client.c | 10 ----------
 drivers/hid/amd-sfh-hid/amd_sfh_hid.h    |  9 +++++++++
 2 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_client.c b/drivers/hid/amd-sfh-hid/amd_sfh_client.c
index 0f770a2b47ff..fac9e8a66120 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_client.c
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_client.c
@@ -18,16 +18,6 @@
 #include "amd_sfh_pcie.h"
 #include "amd_sfh_hid.h"
 
-
-struct request_list {
-	struct hid_device *hid;
-	struct list_head list;
-	u8 report_id;
-	u8 sensor_idx;
-	u8 report_type;
-	u8 current_index;
-};
-
 static struct request_list req_list;
 
 void amd_sfh_set_report(struct hid_device *hid, int report_id,
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_hid.h b/drivers/hid/amd-sfh-hid/amd_sfh_hid.h
index ad264db63180..e2e4cc5fc946 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_hid.h
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_hid.h
@@ -15,6 +15,15 @@
 #define AMD_SFH_HID_VENDOR	0x1022
 #define AMD_SFH_HID_PRODUCT	0x0001
 
+struct request_list {
+	struct hid_device *hid;
+	struct list_head list;
+	u8 report_id;
+	u8 sensor_idx;
+	u8 report_type;
+	u8 current_index;
+};
+
 struct amd_input_data {
 	u32 *sensor_virt_addr[MAX_HID_DEVICES];
 	u8 *input_report[MAX_HID_DEVICES];
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 04/11] HID: amd_sfh: Move request_list variable to client data
  2022-07-12 18:18 [PATCH 00/11] Fixes and implementation of AMD SFH 1.1 functionality Basavaraj Natikar
                   ` (2 preceding siblings ...)
  2022-07-12 18:18 ` [PATCH 03/11] HID: amd_sfh: Move request_list struct to header file Basavaraj Natikar
@ 2022-07-12 18:18 ` Basavaraj Natikar
  2022-07-12 18:18 ` [PATCH 05/11] HID: amd_sfh: Add descriptor operations in amd_mp2_ops Basavaraj Natikar
                   ` (7 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Basavaraj Natikar @ 2022-07-12 18:18 UTC (permalink / raw)
  To: jikos, benjamin.tissoires, linux-input; +Cc: Basavaraj Natikar

request_list variable can be used in multiple files to support all
AMD SOCs. Hence move request_list variable to client data.

Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
---
 drivers/hid/amd-sfh-hid/amd_sfh_client.c | 12 +++++++-----
 drivers/hid/amd-sfh-hid/amd_sfh_hid.h    |  1 +
 2 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_client.c b/drivers/hid/amd-sfh-hid/amd_sfh_client.c
index fac9e8a66120..e3b3db514c91 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_client.c
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_client.c
@@ -18,8 +18,6 @@
 #include "amd_sfh_pcie.h"
 #include "amd_sfh_hid.h"
 
-static struct request_list req_list;
-
 void amd_sfh_set_report(struct hid_device *hid, int report_id,
 			int report_type)
 {
@@ -40,6 +38,7 @@ int amd_sfh_get_report(struct hid_device *hid, int report_id, int report_type)
 {
 	struct amdtp_hid_data *hid_data = hid->driver_data;
 	struct amdtp_cl_data *cli_data = hid_data->cli_data;
+	struct request_list *req_list = &cli_data->req_list;
 	int i;
 
 	for (i = 0; i < cli_data->num_hid_devices; i++) {
@@ -56,7 +55,7 @@ int amd_sfh_get_report(struct hid_device *hid, int report_id, int report_type)
 			new->report_id = report_id;
 			cli_data->report_id[i] = report_id;
 			cli_data->request_done[i] = false;
-			list_add(&new->list, &req_list.list);
+			list_add(&new->list, &req_list->list);
 			break;
 		}
 	}
@@ -67,13 +66,14 @@ int amd_sfh_get_report(struct hid_device *hid, int report_id, int report_type)
 static void amd_sfh_work(struct work_struct *work)
 {
 	struct amdtp_cl_data *cli_data = container_of(work, struct amdtp_cl_data, work.work);
+	struct request_list *req_list = &cli_data->req_list;
 	struct amd_input_data *in_data = cli_data->in_data;
 	struct request_list *req_node;
 	u8 current_index, sensor_index;
 	u8 report_id, node_type;
 	u8 report_size = 0;
 
-	req_node = list_last_entry(&req_list.list, struct request_list, list);
+	req_node = list_last_entry(&req_list->list, struct request_list, list);
 	list_del(&req_node->list);
 	current_index = req_node->current_index;
 	sensor_index = req_node->sensor_idx;
@@ -154,19 +154,21 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
 	struct amd_input_data *in_data = &privdata->in_data;
 	struct amdtp_cl_data *cl_data = privdata->cl_data;
 	struct amd_mp2_sensor_info info;
+	struct request_list *req_list;
 	struct device *dev;
 	u32 feature_report_size;
 	u32 input_report_size;
 	int rc, i, status;
 	u8 cl_idx;
 
+	req_list = &cl_data->req_list;
 	dev = &privdata->pdev->dev;
 
 	cl_data->num_hid_devices = amd_mp2_get_sensor_num(privdata, &cl_data->sensor_idx[0]);
 
 	INIT_DELAYED_WORK(&cl_data->work, amd_sfh_work);
 	INIT_DELAYED_WORK(&cl_data->work_buffer, amd_sfh_work_buffer);
-	INIT_LIST_HEAD(&req_list.list);
+	INIT_LIST_HEAD(&req_list->list);
 	cl_data->in_data = in_data;
 
 	for (i = 0; i < cl_data->num_hid_devices; i++) {
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_hid.h b/drivers/hid/amd-sfh-hid/amd_sfh_hid.h
index e2e4cc5fc946..ecdd2f48cfb8 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_hid.h
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_hid.h
@@ -52,6 +52,7 @@ struct amdtp_cl_data {
 	struct amd_input_data *in_data;
 	struct delayed_work work;
 	struct delayed_work work_buffer;
+	struct request_list req_list;
 };
 
 /**
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 05/11] HID: amd_sfh: Add descriptor operations in amd_mp2_ops
  2022-07-12 18:18 [PATCH 00/11] Fixes and implementation of AMD SFH 1.1 functionality Basavaraj Natikar
                   ` (3 preceding siblings ...)
  2022-07-12 18:18 ` [PATCH 04/11] HID: amd_sfh: Move request_list variable to client data Basavaraj Natikar
@ 2022-07-12 18:18 ` Basavaraj Natikar
  2022-07-12 18:18 ` [PATCH 06/11] HID: amd_sfh: Add PM " Basavaraj Natikar
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Basavaraj Natikar @ 2022-07-12 18:18 UTC (permalink / raw)
  To: jikos, benjamin.tissoires, linux-input; +Cc: Basavaraj Natikar

Add dynamic descriptor operations as part of amd_mp2_ops structure to
support all AMD SOCs and use wherever applicable.

Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
---
 drivers/hid/amd-sfh-hid/amd_sfh_client.c      | 33 +++++++++++--------
 drivers/hid/amd-sfh-hid/amd_sfh_common.h      |  7 +++-
 drivers/hid/amd-sfh-hid/amd_sfh_hid.h         |  2 --
 drivers/hid/amd-sfh-hid/amd_sfh_pcie.c        |  4 +--
 drivers/hid/amd-sfh-hid/amd_sfh_pcie.h        |  1 +
 .../hid_descriptor/amd_sfh_hid_desc.c         | 17 +++++++---
 .../hid_descriptor/amd_sfh_hid_desc.h         |  3 --
 7 files changed, 42 insertions(+), 25 deletions(-)

diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_client.c b/drivers/hid/amd-sfh-hid/amd_sfh_client.c
index e3b3db514c91..e9ccdad66d12 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_client.c
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_client.c
@@ -70,6 +70,8 @@ static void amd_sfh_work(struct work_struct *work)
 	struct amd_input_data *in_data = cli_data->in_data;
 	struct request_list *req_node;
 	u8 current_index, sensor_index;
+	struct amd_mp2_ops *mp2_ops;
+	struct amd_mp2_dev *mp2;
 	u8 report_id, node_type;
 	u8 report_size = 0;
 
@@ -81,9 +83,11 @@ static void amd_sfh_work(struct work_struct *work)
 	node_type = req_node->report_type;
 	kfree(req_node);
 
+	mp2 = container_of(in_data, struct amd_mp2_dev, in_data);
+	mp2_ops = mp2->mp2_ops;
 	if (node_type == HID_FEATURE_REPORT) {
-		report_size = get_feature_report(sensor_index, report_id,
-						 cli_data->feature_report[current_index]);
+		report_size = mp2_ops->get_feat_rep(sensor_index, report_id,
+						    cli_data->feature_report[current_index]);
 		if (report_size)
 			hid_input_report(cli_data->hid_sensor_hubs[current_index],
 					 cli_data->report_type[current_index],
@@ -92,7 +96,7 @@ static void amd_sfh_work(struct work_struct *work)
 			pr_err("AMDSFH: Invalid report size\n");
 
 	} else if (node_type == HID_INPUT_REPORT) {
-		report_size = get_input_report(current_index, sensor_index, report_id, in_data);
+		report_size = mp2_ops->get_in_rep(current_index, sensor_index, report_id, in_data);
 		if (report_size)
 			hid_input_report(cli_data->hid_sensor_hubs[current_index],
 					 cli_data->report_type[current_index],
@@ -109,13 +113,15 @@ static void amd_sfh_work_buffer(struct work_struct *work)
 {
 	struct amdtp_cl_data *cli_data = container_of(work, struct amdtp_cl_data, work_buffer.work);
 	struct amd_input_data *in_data = cli_data->in_data;
+	struct amd_mp2_dev *mp2;
 	u8 report_size;
 	int i;
 
 	for (i = 0; i < cli_data->num_hid_devices; i++) {
 		if (cli_data->sensor_sts[i] == SENSOR_ENABLED) {
-			report_size = get_input_report
-				(i, cli_data->sensor_idx[i], cli_data->report_id[i], in_data);
+			mp2 = container_of(in_data, struct amd_mp2_dev, in_data);
+			report_size = mp2->mp2_ops->get_in_rep(i, cli_data->sensor_idx[i],
+							       cli_data->report_id[i], in_data);
 			hid_input_report(cli_data->hid_sensor_hubs[i], HID_INPUT_REPORT,
 					 in_data->input_report[i], report_size, 0);
 		}
@@ -153,6 +159,7 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
 {
 	struct amd_input_data *in_data = &privdata->in_data;
 	struct amdtp_cl_data *cl_data = privdata->cl_data;
+	struct amd_mp2_ops *mp2_ops = privdata->mp2_ops;
 	struct amd_mp2_sensor_info info;
 	struct request_list *req_list;
 	struct device *dev;
@@ -163,6 +170,7 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
 
 	req_list = &cl_data->req_list;
 	dev = &privdata->pdev->dev;
+	amd_sfh_set_desc_ops(mp2_ops);
 
 	cl_data->num_hid_devices = amd_mp2_get_sensor_num(privdata, &cl_data->sensor_idx[0]);
 
@@ -179,17 +187,17 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
 		cl_data->sensor_requested_cnt[i] = 0;
 		cl_data->cur_hid_dev = i;
 		cl_idx = cl_data->sensor_idx[i];
-		cl_data->report_descr_sz[i] = get_descr_sz(cl_idx, descr_size);
+		cl_data->report_descr_sz[i] = mp2_ops->get_desc_sz(cl_idx, descr_size);
 		if (!cl_data->report_descr_sz[i]) {
 			rc = -EINVAL;
 			goto cleanup;
 		}
-		feature_report_size = get_descr_sz(cl_idx, feature_size);
+		feature_report_size = mp2_ops->get_desc_sz(cl_idx, feature_size);
 		if (!feature_report_size) {
 			rc = -EINVAL;
 			goto cleanup;
 		}
-		input_report_size =  get_descr_sz(cl_idx, input_size);
+		input_report_size =  mp2_ops->get_desc_sz(cl_idx, input_size);
 		if (!input_report_size) {
 			rc = -EINVAL;
 			goto cleanup;
@@ -214,17 +222,17 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
 			rc = -ENOMEM;
 			goto cleanup;
 		}
-		rc = get_report_descriptor(cl_idx, cl_data->report_descr[i]);
+		rc = mp2_ops->get_rep_desc(cl_idx, cl_data->report_descr[i]);
 		if (rc)
 			return rc;
-		privdata->mp2_ops->start(privdata, info);
+		mp2_ops->start(privdata, info);
 		status = amd_sfh_wait_for_response
 				(privdata, cl_data->sensor_idx[i], SENSOR_ENABLED);
 		if (status == SENSOR_ENABLED) {
 			cl_data->sensor_sts[i] = SENSOR_ENABLED;
 			rc = amdtp_hid_probe(cl_data->cur_hid_dev, cl_data);
 			if (rc) {
-				privdata->mp2_ops->stop(privdata, cl_data->sensor_idx[i]);
+				mp2_ops->stop(privdata, cl_data->sensor_idx[i]);
 				status = amd_sfh_wait_for_response
 					(privdata, cl_data->sensor_idx[i], SENSOR_DISABLED);
 				if (status != SENSOR_ENABLED)
@@ -240,8 +248,7 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
 			cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
 			cl_data->sensor_sts[i]);
 	}
-	if (privdata->mp2_ops->discovery_status &&
-	    privdata->mp2_ops->discovery_status(privdata) == 0) {
+	if (mp2_ops->discovery_status && mp2_ops->discovery_status(privdata) == 0) {
 		amd_sfh_hid_client_deinit(privdata);
 		for (i = 0; i < cl_data->num_hid_devices; i++) {
 			devm_kfree(dev, cl_data->feature_report[i]);
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_common.h b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
index 40da53d5efd0..d2a72ab64ebf 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_common.h
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
@@ -40,7 +40,7 @@ struct amd_mp2_dev {
 	struct pci_dev *pdev;
 	struct amdtp_cl_data *cl_data;
 	void __iomem *mmio;
-	const struct amd_mp2_ops *mp2_ops;
+	struct amd_mp2_ops *mp2_ops;
 	struct amd_input_data in_data;
 	/* mp2 active control status */
 	u32 mp2_acs;
@@ -54,6 +54,11 @@ struct amd_mp2_ops {
 	void (*clear_intr)(struct amd_mp2_dev *privdata);
 	int (*init_intr)(struct amd_mp2_dev *privdata);
 	int (*discovery_status)(struct amd_mp2_dev *privdata);
+	int (*get_rep_desc)(int sensor_idx, u8 rep_desc[]);
+	u32 (*get_desc_sz)(int sensor_idx, int descriptor_name);
+	u8 (*get_feat_rep)(int sensor_idx, int report_id, u8 *feature_report);
+	u8 (*get_in_rep)(u8 current_index, int sensor_idx, int report_id,
+			 struct amd_input_data *in_data);
 };
 
 #endif
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_hid.h b/drivers/hid/amd-sfh-hid/amd_sfh_hid.h
index ecdd2f48cfb8..3754fb423e3a 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_hid.h
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_hid.h
@@ -79,6 +79,4 @@ void amdtp_hid_remove(struct amdtp_cl_data *cli_data);
 int amd_sfh_get_report(struct hid_device *hid, int report_id, int report_type);
 void amd_sfh_set_report(struct hid_device *hid, int report_id, int report_type);
 void amdtp_hid_wakeup(struct hid_device *hid);
-u8 get_input_report(u8 current_index, int sensor_idx, int report_id,
-		    struct amd_input_data *in_data);
 #endif
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
index dadc491bbf6b..f169b4413abb 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
@@ -244,7 +244,7 @@ static void amd_mp2_pci_remove(void *privdata)
 	amd_sfh_clear_intr(mp2);
 }
 
-static const struct amd_mp2_ops amd_sfh_ops_v2 = {
+static 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,
@@ -254,7 +254,7 @@ static const struct amd_mp2_ops amd_sfh_ops_v2 = {
 	.discovery_status = amd_sfh_dis_sts_v2,
 };
 
-static const struct amd_mp2_ops amd_sfh_ops = {
+static struct amd_mp2_ops amd_sfh_ops = {
 	.start = amd_start_sensor,
 	.stop = amd_stop_sensor,
 	.stop_all = amd_stop_all_sensors,
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
index 2feac14f5d3c..71c114acdd2b 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
@@ -108,5 +108,6 @@ u32 amd_sfh_wait_for_response(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts);
 void amd_mp2_suspend(struct amd_mp2_dev *mp2);
 void amd_mp2_resume(struct amd_mp2_dev *mp2);
 const char *get_sensor_name(int idx);
+void amd_sfh_set_desc_ops(struct amd_mp2_ops *mp2_ops);
 
 #endif
diff --git a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c
index 76095bd53c65..f9a8c02d5a7b 100644
--- a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c
+++ b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.c
@@ -29,7 +29,7 @@
 #define HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM                      0x04
 #define ILLUMINANCE_MASK					GENMASK(14, 0)
 
-int get_report_descriptor(int sensor_idx, u8 *rep_desc)
+static int get_report_descriptor(int sensor_idx, u8 *rep_desc)
 {
 	switch (sensor_idx) {
 	case accel_idx: /* accel */
@@ -63,7 +63,7 @@ int get_report_descriptor(int sensor_idx, u8 *rep_desc)
 	return 0;
 }
 
-u32 get_descr_sz(int sensor_idx, int descriptor_name)
+static u32 get_descr_sz(int sensor_idx, int descriptor_name)
 {
 	switch (sensor_idx) {
 	case accel_idx:
@@ -133,7 +133,7 @@ static void get_common_features(struct common_feature_property *common, int repo
 	common->report_interval =  HID_DEFAULT_REPORT_INTERVAL;
 }
 
-u8 get_feature_report(int sensor_idx, int report_id, u8 *feature_report)
+static u8 get_feature_report(int sensor_idx, int report_id, u8 *feature_report)
 {
 	struct accel3_feature_report acc_feature;
 	struct gyro_feature_report gyro_feature;
@@ -200,7 +200,8 @@ static void get_common_inputs(struct common_input_property *common, int report_i
 	common->event_type = HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM;
 }
 
-u8 get_input_report(u8 current_index, int sensor_idx, int report_id, struct amd_input_data *in_data)
+static u8 get_input_report(u8 current_index, int sensor_idx, int report_id,
+			   struct amd_input_data *in_data)
 {
 	struct amd_mp2_dev *privdata = container_of(in_data, struct amd_mp2_dev, in_data);
 	u32 *sensor_virt_addr = in_data->sensor_virt_addr[current_index];
@@ -267,3 +268,11 @@ u8 get_input_report(u8 current_index, int sensor_idx, int report_id, struct amd_
 	}
 	return report_size;
 }
+
+void amd_sfh_set_desc_ops(struct amd_mp2_ops *mp2_ops)
+{
+	mp2_ops->get_rep_desc = get_report_descriptor;
+	mp2_ops->get_feat_rep = get_feature_report;
+	mp2_ops->get_in_rep = get_input_report;
+	mp2_ops->get_desc_sz = get_descr_sz;
+}
diff --git a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h
index 70b1b7abe2c6..ebd55675eb62 100644
--- a/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h
+++ b/drivers/hid/amd-sfh-hid/hid_descriptor/amd_sfh_hid_desc.h
@@ -111,7 +111,4 @@ struct hpd_input_report {
 	u8 human_presence;
 } __packed;
 
-int get_report_descriptor(int sensor_idx, u8 rep_desc[]);
-u32 get_descr_sz(int sensor_idx, int descriptor_name);
-u8 get_feature_report(int sensor_idx, int report_id, u8 *feature_report);
 #endif
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 06/11] HID: amd_sfh: Add PM operations in amd_mp2_ops
  2022-07-12 18:18 [PATCH 00/11] Fixes and implementation of AMD SFH 1.1 functionality Basavaraj Natikar
                   ` (4 preceding siblings ...)
  2022-07-12 18:18 ` [PATCH 05/11] HID: amd_sfh: Add descriptor operations in amd_mp2_ops Basavaraj Natikar
@ 2022-07-12 18:18 ` Basavaraj Natikar
  2022-07-12 18:18 ` [PATCH 07/11] HID: amd_sfh: Add remove operation " Basavaraj Natikar
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Basavaraj Natikar @ 2022-07-12 18:18 UTC (permalink / raw)
  To: jikos, benjamin.tissoires, linux-input; +Cc: Basavaraj Natikar

Add PM operations as part of amd_mp2_ops structure to support all
AMD SOCs and use wherever applicable.

Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
---
 drivers/hid/amd-sfh-hid/amd_sfh_client.c | 54 ++++++++++++++++++++++++
 drivers/hid/amd-sfh-hid/amd_sfh_common.h |  2 +
 drivers/hid/amd-sfh-hid/amd_sfh_pcie.c   | 41 +-----------------
 3 files changed, 58 insertions(+), 39 deletions(-)

diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_client.c b/drivers/hid/amd-sfh-hid/amd_sfh_client.c
index e9ccdad66d12..b198b564db7d 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_client.c
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_client.c
@@ -155,6 +155,57 @@ const char *get_sensor_name(int idx)
 	}
 }
 
+static void amd_sfh_resume(struct amd_mp2_dev *mp2)
+{
+	struct amdtp_cl_data *cl_data = mp2->cl_data;
+	struct amd_mp2_sensor_info info;
+	int i, status;
+
+	for (i = 0; i < cl_data->num_hid_devices; i++) {
+		if (cl_data->sensor_sts[i] == SENSOR_DISABLED) {
+			info.period = AMD_SFH_IDLE_LOOP;
+			info.sensor_idx = cl_data->sensor_idx[i];
+			info.dma_address = cl_data->sensor_dma_addr[i];
+			mp2->mp2_ops->start(mp2, info);
+			status = amd_sfh_wait_for_response
+					(mp2, cl_data->sensor_idx[i], SENSOR_ENABLED);
+			if (status == SENSOR_ENABLED)
+				cl_data->sensor_sts[i] = SENSOR_ENABLED;
+			dev_dbg(&mp2->pdev->dev, "resume sid 0x%x (%s) status 0x%x\n",
+				cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
+				cl_data->sensor_sts[i]);
+		}
+	}
+
+	schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
+	if (mp2->mp2_ops->clear_intr)
+		mp2->mp2_ops->clear_intr(mp2);
+}
+
+static void amd_sfh_suspend(struct amd_mp2_dev *mp2)
+{
+	struct amdtp_cl_data *cl_data = mp2->cl_data;
+	int i, status;
+
+	for (i = 0; i < cl_data->num_hid_devices; i++) {
+		if (cl_data->sensor_idx[i] != HPD_IDX &&
+		    cl_data->sensor_sts[i] == SENSOR_ENABLED) {
+			mp2->mp2_ops->stop(mp2, cl_data->sensor_idx[i]);
+			status = amd_sfh_wait_for_response
+					(mp2, cl_data->sensor_idx[i], SENSOR_DISABLED);
+			if (status != SENSOR_ENABLED)
+				cl_data->sensor_sts[i] = SENSOR_DISABLED;
+			dev_dbg(&mp2->pdev->dev, "suspend sid 0x%x (%s) status 0x%x\n",
+				cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
+				cl_data->sensor_sts[i]);
+		}
+	}
+
+	cancel_delayed_work_sync(&cl_data->work_buffer);
+	if (mp2->mp2_ops->clear_intr)
+		mp2->mp2_ops->clear_intr(mp2);
+}
+
 int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
 {
 	struct amd_input_data *in_data = &privdata->in_data;
@@ -172,6 +223,9 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
 	dev = &privdata->pdev->dev;
 	amd_sfh_set_desc_ops(mp2_ops);
 
+	mp2_ops->suspend = amd_sfh_suspend;
+	mp2_ops->resume = amd_sfh_resume;
+
 	cl_data->num_hid_devices = amd_mp2_get_sensor_num(privdata, &cl_data->sensor_idx[0]);
 
 	INIT_DELAYED_WORK(&cl_data->work, amd_sfh_work);
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_common.h b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
index d2a72ab64ebf..2b45d507ead7 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_common.h
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
@@ -54,6 +54,8 @@ struct amd_mp2_ops {
 	void (*clear_intr)(struct amd_mp2_dev *privdata);
 	int (*init_intr)(struct amd_mp2_dev *privdata);
 	int (*discovery_status)(struct amd_mp2_dev *privdata);
+	void (*suspend)(struct amd_mp2_dev *mp2);
+	void (*resume)(struct amd_mp2_dev *mp2);
 	int (*get_rep_desc)(int sensor_idx, u8 rep_desc[]);
 	u32 (*get_desc_sz)(int sensor_idx, int descriptor_name);
 	u8 (*get_feat_rep)(int sensor_idx, int report_id, u8 *feature_report);
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
index f169b4413abb..be9ac3778f37 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
@@ -339,28 +339,8 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
 static int __maybe_unused amd_mp2_pci_resume(struct device *dev)
 {
 	struct amd_mp2_dev *mp2 = dev_get_drvdata(dev);
-	struct amdtp_cl_data *cl_data = mp2->cl_data;
-	struct amd_mp2_sensor_info info;
-	int i, status;
-
-	for (i = 0; i < cl_data->num_hid_devices; i++) {
-		if (cl_data->sensor_sts[i] == SENSOR_DISABLED) {
-			info.period = AMD_SFH_IDLE_LOOP;
-			info.sensor_idx = cl_data->sensor_idx[i];
-			info.dma_address = cl_data->sensor_dma_addr[i];
-			mp2->mp2_ops->start(mp2, info);
-			status = amd_sfh_wait_for_response
-					(mp2, cl_data->sensor_idx[i], SENSOR_ENABLED);
-			if (status == SENSOR_ENABLED)
-				cl_data->sensor_sts[i] = SENSOR_ENABLED;
-			dev_dbg(dev, "suspend sid 0x%x (%s) status 0x%x\n",
-				cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
-				cl_data->sensor_sts[i]);
-		}
-	}
 
-	schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
-	amd_sfh_clear_intr(mp2);
+	mp2->mp2_ops->resume(mp2);
 
 	return 0;
 }
@@ -368,25 +348,8 @@ static int __maybe_unused amd_mp2_pci_resume(struct device *dev)
 static int __maybe_unused amd_mp2_pci_suspend(struct device *dev)
 {
 	struct amd_mp2_dev *mp2 = dev_get_drvdata(dev);
-	struct amdtp_cl_data *cl_data = mp2->cl_data;
-	int i, status;
-
-	for (i = 0; i < cl_data->num_hid_devices; i++) {
-		if (cl_data->sensor_idx[i] != HPD_IDX &&
-		    cl_data->sensor_sts[i] == SENSOR_ENABLED) {
-			mp2->mp2_ops->stop(mp2, cl_data->sensor_idx[i]);
-			status = amd_sfh_wait_for_response
-					(mp2, cl_data->sensor_idx[i], SENSOR_DISABLED);
-			if (status != SENSOR_ENABLED)
-				cl_data->sensor_sts[i] = SENSOR_DISABLED;
-			dev_dbg(dev, "suspend sid 0x%x (%s) status 0x%x\n",
-				cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
-				cl_data->sensor_sts[i]);
-		}
-	}
 
-	cancel_delayed_work_sync(&cl_data->work_buffer);
-	amd_sfh_clear_intr(mp2);
+	mp2->mp2_ops->suspend(mp2);
 
 	return 0;
 }
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 07/11] HID: amd_sfh: Add remove operation in amd_mp2_ops
  2022-07-12 18:18 [PATCH 00/11] Fixes and implementation of AMD SFH 1.1 functionality Basavaraj Natikar
                   ` (5 preceding siblings ...)
  2022-07-12 18:18 ` [PATCH 06/11] HID: amd_sfh: Add PM " Basavaraj Natikar
@ 2022-07-12 18:18 ` Basavaraj Natikar
  2022-07-12 18:18 ` [PATCH 08/11] HID: amd_sfh: Move global functions to static Basavaraj Natikar
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Basavaraj Natikar @ 2022-07-12 18:18 UTC (permalink / raw)
  To: jikos, benjamin.tissoires, linux-input; +Cc: Basavaraj Natikar

Add remove operation as part of amd_mp2_ops structure to support all
AMD SOCs and use wherever applicable.

Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
---
 drivers/hid/amd-sfh-hid/amd_sfh_common.h | 1 +
 drivers/hid/amd-sfh-hid/amd_sfh_pcie.c   | 4 +++-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_common.h b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
index 2b45d507ead7..afecf7d2bebe 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_common.h
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
@@ -56,6 +56,7 @@ struct amd_mp2_ops {
 	int (*discovery_status)(struct amd_mp2_dev *privdata);
 	void (*suspend)(struct amd_mp2_dev *mp2);
 	void (*resume)(struct amd_mp2_dev *mp2);
+	void (*remove)(void *privdata);
 	int (*get_rep_desc)(int sensor_idx, u8 rep_desc[]);
 	u32 (*get_desc_sz)(int sensor_idx, int descriptor_name);
 	u8 (*get_feat_rep)(int sensor_idx, int report_id, u8 *feature_report);
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
index be9ac3778f37..62e6757f889d 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
@@ -252,12 +252,14 @@ static struct amd_mp2_ops amd_sfh_ops_v2 = {
 	.clear_intr = amd_sfh_clear_intr_v2,
 	.init_intr = amd_sfh_irq_init_v2,
 	.discovery_status = amd_sfh_dis_sts_v2,
+	.remove = amd_mp2_pci_remove,
 };
 
 static struct amd_mp2_ops amd_sfh_ops = {
 	.start = amd_start_sensor,
 	.stop = amd_stop_sensor,
 	.stop_all = amd_stop_all_sensors,
+	.remove = amd_mp2_pci_remove,
 };
 
 static void mp2_select_ops(struct amd_mp2_dev *privdata)
@@ -333,7 +335,7 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
 
 	amd_sfh_clear_intr(privdata);
 
-	return devm_add_action_or_reset(&pdev->dev, amd_mp2_pci_remove, privdata);
+	return devm_add_action_or_reset(&pdev->dev, privdata->mp2_ops->remove, privdata);
 }
 
 static int __maybe_unused amd_mp2_pci_resume(struct device *dev)
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 08/11] HID: amd_sfh: Move global functions to static
  2022-07-12 18:18 [PATCH 00/11] Fixes and implementation of AMD SFH 1.1 functionality Basavaraj Natikar
                   ` (6 preceding siblings ...)
  2022-07-12 18:18 ` [PATCH 07/11] HID: amd_sfh: Add remove operation " Basavaraj Natikar
@ 2022-07-12 18:18 ` Basavaraj Natikar
  2022-07-12 18:18 ` [PATCH 09/11] HID: amd_sfh: Move amd_sfh_work to common interface Basavaraj Natikar
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Basavaraj Natikar @ 2022-07-12 18:18 UTC (permalink / raw)
  To: jikos, benjamin.tissoires, linux-input; +Cc: Basavaraj Natikar

Move global functions declared from header files and make them as static
functions wherever applicable.

Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
---
 drivers/hid/amd-sfh-hid/amd_sfh_client.c | 4 ++--
 drivers/hid/amd-sfh-hid/amd_sfh_pcie.c   | 6 +++---
 drivers/hid/amd-sfh-hid/amd_sfh_pcie.h   | 7 -------
 3 files changed, 5 insertions(+), 12 deletions(-)

diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_client.c b/drivers/hid/amd-sfh-hid/amd_sfh_client.c
index b198b564db7d..1f59fabded85 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_client.c
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_client.c
@@ -129,7 +129,7 @@ static void amd_sfh_work_buffer(struct work_struct *work)
 	schedule_delayed_work(&cli_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
 }
 
-u32 amd_sfh_wait_for_response(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts)
+static u32 amd_sfh_wait_for_response(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts)
 {
 	if (mp2->mp2_ops->response)
 		sensor_sts = mp2->mp2_ops->response(mp2, sid, sensor_sts);
@@ -137,7 +137,7 @@ u32 amd_sfh_wait_for_response(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts)
 	return sensor_sts;
 }
 
-const char *get_sensor_name(int idx)
+static const char *get_sensor_name(int idx)
 {
 	switch (idx) {
 	case accel_idx:
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
index 62e6757f889d..c9a9ac11f124 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
@@ -136,7 +136,7 @@ static int amd_sfh_dis_sts_v2(struct amd_mp2_dev *privdata)
 		      SENSOR_DISCOVERY_STATUS_MASK) >> SENSOR_DISCOVERY_STATUS_SHIFT;
 }
 
-void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info)
+static void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info)
 {
 	union sfh_cmd_param cmd_param;
 	union sfh_cmd_base cmd_base;
@@ -157,7 +157,7 @@ void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info i
 	writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
 }
 
-void amd_stop_sensor(struct amd_mp2_dev *privdata, u16 sensor_idx)
+static void amd_stop_sensor(struct amd_mp2_dev *privdata, u16 sensor_idx)
 {
 	union sfh_cmd_base cmd_base;
 
@@ -171,7 +171,7 @@ void amd_stop_sensor(struct amd_mp2_dev *privdata, u16 sensor_idx)
 	writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
 }
 
-void amd_stop_all_sensors(struct amd_mp2_dev *privdata)
+static void amd_stop_all_sensors(struct amd_mp2_dev *privdata)
 {
 	union sfh_cmd_base cmd_base;
 
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
index 71c114acdd2b..dfb7cabd82ef 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h
@@ -98,16 +98,9 @@ struct hpd_status {
 	};
 };
 
-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);
-u32 amd_sfh_wait_for_response(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts);
-void amd_mp2_suspend(struct amd_mp2_dev *mp2);
-void amd_mp2_resume(struct amd_mp2_dev *mp2);
-const char *get_sensor_name(int idx);
 void amd_sfh_set_desc_ops(struct amd_mp2_ops *mp2_ops);
 
 #endif
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 09/11] HID: amd_sfh: Move amd_sfh_work to common interface
  2022-07-12 18:18 [PATCH 00/11] Fixes and implementation of AMD SFH 1.1 functionality Basavaraj Natikar
                   ` (7 preceding siblings ...)
  2022-07-12 18:18 ` [PATCH 08/11] HID: amd_sfh: Move global functions to static Basavaraj Natikar
@ 2022-07-12 18:18 ` Basavaraj Natikar
  2022-07-12 18:18 ` [PATCH 10/11] HID: amd_sfh: Move interrupt handling " Basavaraj Natikar
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 13+ messages in thread
From: Basavaraj Natikar @ 2022-07-12 18:18 UTC (permalink / raw)
  To: jikos, benjamin.tissoires, linux-input; +Cc: Basavaraj Natikar

amd_sfh_work can be used in multiple files to support all AMD SOCs.
Hence move amd_sfh_work to common interface.

Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
---
 drivers/hid/amd-sfh-hid/amd_sfh_client.c | 4 ++--
 drivers/hid/amd-sfh-hid/amd_sfh_common.h | 2 ++
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_client.c b/drivers/hid/amd-sfh-hid/amd_sfh_client.c
index 1f59fabded85..8e686081c8fc 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_client.c
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_client.c
@@ -63,7 +63,7 @@ int amd_sfh_get_report(struct hid_device *hid, int report_id, int report_type)
 	return 0;
 }
 
-static void amd_sfh_work(struct work_struct *work)
+void amd_sfh_work(struct work_struct *work)
 {
 	struct amdtp_cl_data *cli_data = container_of(work, struct amdtp_cl_data, work.work);
 	struct request_list *req_list = &cli_data->req_list;
@@ -109,7 +109,7 @@ static void amd_sfh_work(struct work_struct *work)
 	amdtp_hid_wakeup(cli_data->hid_sensor_hubs[current_index]);
 }
 
-static void amd_sfh_work_buffer(struct work_struct *work)
+void amd_sfh_work_buffer(struct work_struct *work)
 {
 	struct amdtp_cl_data *cli_data = container_of(work, struct amdtp_cl_data, work_buffer.work);
 	struct amd_input_data *in_data = cli_data->in_data;
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_common.h b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
index afecf7d2bebe..b3dd758ecca4 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_common.h
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
@@ -64,4 +64,6 @@ struct amd_mp2_ops {
 			 struct amd_input_data *in_data);
 };
 
+void amd_sfh_work(struct work_struct *work);
+void amd_sfh_work_buffer(struct work_struct *work);
 #endif
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 10/11] HID: amd_sfh: Move interrupt handling to common interface
  2022-07-12 18:18 [PATCH 00/11] Fixes and implementation of AMD SFH 1.1 functionality Basavaraj Natikar
                   ` (8 preceding siblings ...)
  2022-07-12 18:18 ` [PATCH 09/11] HID: amd_sfh: Move amd_sfh_work to common interface Basavaraj Natikar
@ 2022-07-12 18:18 ` Basavaraj Natikar
  2022-07-12 18:18 ` [PATCH 11/11] HID: amd_sfh: Implement SFH1.1 functionality Basavaraj Natikar
  2022-07-21 11:44 ` [PATCH 00/11] Fixes and implementation of AMD SFH 1.1 functionality Jiri Kosina
  11 siblings, 0 replies; 13+ messages in thread
From: Basavaraj Natikar @ 2022-07-12 18:18 UTC (permalink / raw)
  To: jikos, benjamin.tissoires, linux-input; +Cc: Basavaraj Natikar

Interrupt handling can be used in multiple files to support all
AMD SOCs. Hence move interrupt handling to common interface.

Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
---
 drivers/hid/amd-sfh-hid/amd_sfh_client.c | 6 ++----
 drivers/hid/amd-sfh-hid/amd_sfh_common.h | 4 ++++
 drivers/hid/amd-sfh-hid/amd_sfh_pcie.c   | 8 ++++----
 3 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_client.c b/drivers/hid/amd-sfh-hid/amd_sfh_client.c
index 8e686081c8fc..f95e623040f3 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_client.c
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_client.c
@@ -178,8 +178,7 @@ static void amd_sfh_resume(struct amd_mp2_dev *mp2)
 	}
 
 	schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
-	if (mp2->mp2_ops->clear_intr)
-		mp2->mp2_ops->clear_intr(mp2);
+	amd_sfh_clear_intr(mp2);
 }
 
 static void amd_sfh_suspend(struct amd_mp2_dev *mp2)
@@ -202,8 +201,7 @@ static void amd_sfh_suspend(struct amd_mp2_dev *mp2)
 	}
 
 	cancel_delayed_work_sync(&cl_data->work_buffer);
-	if (mp2->mp2_ops->clear_intr)
-		mp2->mp2_ops->clear_intr(mp2);
+	amd_sfh_clear_intr(mp2);
 }
 
 int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_common.h b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
index b3dd758ecca4..1efb72ec116f 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_common.h
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
@@ -66,4 +66,8 @@ struct amd_mp2_ops {
 
 void amd_sfh_work(struct work_struct *work);
 void amd_sfh_work_buffer(struct work_struct *work);
+void amd_sfh_clear_intr_v2(struct amd_mp2_dev *privdata);
+int amd_sfh_irq_init_v2(struct amd_mp2_dev *privdata);
+void amd_sfh_clear_intr(struct amd_mp2_dev *privdata);
+int amd_sfh_irq_init(struct amd_mp2_dev *privdata);
 #endif
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
index c9a9ac11f124..1425b57f3580 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
@@ -92,7 +92,7 @@ static void amd_stop_all_sensor_v2(struct amd_mp2_dev *privdata)
 	writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0);
 }
 
-static void amd_sfh_clear_intr_v2(struct amd_mp2_dev *privdata)
+void amd_sfh_clear_intr_v2(struct amd_mp2_dev *privdata)
 {
 	if (readl(privdata->mmio + AMD_P2C_MSG(4))) {
 		writel(0, privdata->mmio + AMD_P2C_MSG(4));
@@ -100,7 +100,7 @@ static void amd_sfh_clear_intr_v2(struct amd_mp2_dev *privdata)
 	}
 }
 
-static void amd_sfh_clear_intr(struct amd_mp2_dev *privdata)
+void amd_sfh_clear_intr(struct amd_mp2_dev *privdata)
 {
 	if (privdata->mp2_ops->clear_intr)
 		privdata->mp2_ops->clear_intr(privdata);
@@ -113,7 +113,7 @@ static irqreturn_t amd_sfh_irq_handler(int irq, void *data)
 	return IRQ_HANDLED;
 }
 
-static int amd_sfh_irq_init_v2(struct amd_mp2_dev *privdata)
+int amd_sfh_irq_init_v2(struct amd_mp2_dev *privdata)
 {
 	int rc;
 
@@ -279,7 +279,7 @@ static void mp2_select_ops(struct amd_mp2_dev *privdata)
 	}
 }
 
-static int amd_sfh_irq_init(struct amd_mp2_dev *privdata)
+int amd_sfh_irq_init(struct amd_mp2_dev *privdata)
 {
 	if (privdata->mp2_ops->init_intr)
 		return privdata->mp2_ops->init_intr(privdata);
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH 11/11] HID: amd_sfh: Implement SFH1.1 functionality
  2022-07-12 18:18 [PATCH 00/11] Fixes and implementation of AMD SFH 1.1 functionality Basavaraj Natikar
                   ` (9 preceding siblings ...)
  2022-07-12 18:18 ` [PATCH 10/11] HID: amd_sfh: Move interrupt handling " Basavaraj Natikar
@ 2022-07-12 18:18 ` Basavaraj Natikar
  2022-07-21 11:44 ` [PATCH 00/11] Fixes and implementation of AMD SFH 1.1 functionality Jiri Kosina
  11 siblings, 0 replies; 13+ messages in thread
From: Basavaraj Natikar @ 2022-07-12 18:18 UTC (permalink / raw)
  To: jikos, benjamin.tissoires, linux-input; +Cc: Basavaraj Natikar

Newer AMD SOCs use SFH1.1 memory access with new PCI-id. Hence add new
sfh1_1 sub directory to implement SFH1.1 functionality by defining new
PCI id, interface functions, descriptor functions and handlers which
invokes sfh1.1.

Signed-off-by: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
---
 drivers/hid/amd-sfh-hid/Makefile              |   3 +
 drivers/hid/amd-sfh-hid/amd_sfh_common.h      |   3 +
 drivers/hid/amd-sfh-hid/amd_sfh_pcie.c        |  12 +
 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c | 300 ++++++++++++++++
 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c | 324 ++++++++++++++++++
 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.h |  26 ++
 .../amd-sfh-hid/sfh1_1/amd_sfh_interface.c    |  73 ++++
 .../amd-sfh-hid/sfh1_1/amd_sfh_interface.h    | 154 +++++++++
 8 files changed, 895 insertions(+)
 create mode 100644 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
 create mode 100644 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
 create mode 100644 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.h
 create mode 100644 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
 create mode 100644 drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h

diff --git a/drivers/hid/amd-sfh-hid/Makefile b/drivers/hid/amd-sfh-hid/Makefile
index 35e704da5612..0222170ab7ad 100644
--- a/drivers/hid/amd-sfh-hid/Makefile
+++ b/drivers/hid/amd-sfh-hid/Makefile
@@ -9,5 +9,8 @@ amd_sfh-objs := amd_sfh_hid.o
 amd_sfh-objs += amd_sfh_client.o
 amd_sfh-objs += amd_sfh_pcie.o
 amd_sfh-objs += hid_descriptor/amd_sfh_hid_desc.o
+amd_sfh-objs += sfh1_1/amd_sfh_init.o
+amd_sfh-objs += sfh1_1/amd_sfh_interface.o
+amd_sfh-objs += sfh1_1/amd_sfh_desc.o
 
 ccflags-y += -I $(srctree)/$(src)/
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_common.h b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
index 1efb72ec116f..2643bb14fee2 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_common.h
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_common.h
@@ -14,6 +14,7 @@
 #include "amd_sfh_hid.h"
 
 #define PCI_DEVICE_ID_AMD_MP2		0x15E4
+#define PCI_DEVICE_ID_AMD_MP2_1_1	0x164A
 
 #define AMD_C2P_MSG(regno) (0x10500 + ((regno) * 4))
 #define AMD_P2C_MSG(regno) (0x10680 + ((regno) * 4))
@@ -40,6 +41,8 @@ struct amd_mp2_dev {
 	struct pci_dev *pdev;
 	struct amdtp_cl_data *cl_data;
 	void __iomem *mmio;
+	void __iomem *vsbase;
+	const struct amd_sfh1_1_ops *sfh1_1_ops;
 	struct amd_mp2_ops *mp2_ops;
 	struct amd_input_data in_data;
 	/* mp2 active control status */
diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
index 1425b57f3580..c9fb844e3360 100644
--- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
+++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c
@@ -19,6 +19,7 @@
 #include <linux/slab.h>
 
 #include "amd_sfh_pcie.h"
+#include "sfh1_1/amd_sfh_init.h"
 
 #define DRIVER_NAME	"pcie_mp2_amd"
 #define DRIVER_DESC	"AMD(R) PCIe MP2 Communication Driver"
@@ -318,6 +319,14 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
 	if (!privdata->cl_data)
 		return -ENOMEM;
 
+	privdata->sfh1_1_ops = (const struct amd_sfh1_1_ops *)id->driver_data;
+	if (privdata->sfh1_1_ops) {
+		rc = privdata->sfh1_1_ops->init(privdata);
+		if (rc)
+			return rc;
+		goto init_done;
+	}
+
 	mp2_select_ops(privdata);
 
 	rc = amd_sfh_irq_init(privdata);
@@ -333,6 +342,7 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
 		return rc;
 	}
 
+init_done:
 	amd_sfh_clear_intr(privdata);
 
 	return devm_add_action_or_reset(&pdev->dev, privdata->mp2_ops->remove, privdata);
@@ -361,6 +371,8 @@ static SIMPLE_DEV_PM_OPS(amd_mp2_pm_ops, amd_mp2_pci_suspend,
 
 static const struct pci_device_id amd_mp2_pci_tbl[] = {
 	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_MP2) },
+	{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_MP2_1_1),
+	  .driver_data = (kernel_ulong_t)&sfh1_1_ops },
 	{ }
 };
 MODULE_DEVICE_TABLE(pci, amd_mp2_pci_tbl);
diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
new file mode 100644
index 000000000000..0609fea581c9
--- /dev/null
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_desc.c
@@ -0,0 +1,300 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * AMD MP2 1.1 descriptor interfaces
+ *
+ * Copyright (c) 2022, Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Author: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
+ */
+
+#include <linux/hid-sensor-ids.h>
+
+#include "amd_sfh_interface.h"
+#include "../hid_descriptor/amd_sfh_hid_desc.h"
+#include "../hid_descriptor/amd_sfh_hid_report_desc.h"
+
+#define SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM			0x41
+#define SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM			0x51
+#define HID_DEFAULT_REPORT_INTERVAL					0x50
+#define HID_DEFAULT_MIN_VALUE						0X7F
+#define HID_DEFAULT_MAX_VALUE						0x80
+#define HID_DEFAULT_SENSITIVITY						0x7F
+#define HID_USAGE_SENSOR_PROPERTY_CONNECTION_TYPE_PC_INTEGRATED_ENUM	0x01
+/* state enums */
+#define HID_USAGE_SENSOR_STATE_READY_ENUM				0x02
+#define HID_USAGE_SENSOR_STATE_INITIALIZING_ENUM			0x05
+#define HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM			0x04
+
+static int get_report_desc(int sensor_idx, u8 *rep_desc)
+{
+	switch (sensor_idx) {
+	case ACCEL_IDX: /* accelerometer */
+		memset(rep_desc, 0, sizeof(accel3_report_descriptor));
+		memcpy(rep_desc, accel3_report_descriptor,
+		       sizeof(accel3_report_descriptor));
+		break;
+	case GYRO_IDX: /* gyroscope */
+		memset(rep_desc, 0, sizeof(gyro3_report_descriptor));
+		memcpy(rep_desc, gyro3_report_descriptor,
+		       sizeof(gyro3_report_descriptor));
+		break;
+	case MAG_IDX: /* magnetometer */
+		memset(rep_desc, 0, sizeof(comp3_report_descriptor));
+		memcpy(rep_desc, comp3_report_descriptor,
+		       sizeof(comp3_report_descriptor));
+		break;
+	case ALS_IDX: /* ambient light sensor */
+		memset(rep_desc, 0, sizeof(als_report_descriptor));
+		memcpy(rep_desc, als_report_descriptor,
+		       sizeof(als_report_descriptor));
+		break;
+	case HPD_IDX: /* HPD sensor */
+		memset(rep_desc, 0, sizeof(hpd_report_descriptor));
+		memcpy(rep_desc, hpd_report_descriptor,
+		       sizeof(hpd_report_descriptor));
+		break;
+	}
+	return 0;
+}
+
+static void get_common_features(struct common_feature_property *common, int report_id)
+{
+	common->report_id = report_id;
+	common->connection_type = HID_USAGE_SENSOR_PROPERTY_CONNECTION_TYPE_PC_INTEGRATED_ENUM;
+	common->report_state = SENSOR_PROP_REPORTING_STATE_ALL_EVENTS_ENUM;
+	common->power_state = SENSOR_PROP_POWER_STATE_D0_FULL_POWER_ENUM;
+	common->sensor_state = HID_USAGE_SENSOR_STATE_INITIALIZING_ENUM;
+	common->report_interval =  HID_DEFAULT_REPORT_INTERVAL;
+}
+
+static u8 get_feature_rep(int sensor_idx, int report_id, u8 *feature_report)
+{
+	struct magno_feature_report magno_feature;
+	struct accel3_feature_report acc_feature;
+	struct gyro_feature_report gyro_feature;
+	struct hpd_feature_report hpd_feature;
+	struct als_feature_report als_feature;
+	u8 report_size = 0;
+
+	if (!feature_report)
+		return report_size;
+
+	switch (sensor_idx) {
+	case ACCEL_IDX: /* accelerometer */
+		get_common_features(&acc_feature.common_property, report_id);
+		acc_feature.accel_change_sesnitivity = HID_DEFAULT_SENSITIVITY;
+		acc_feature.accel_sensitivity_min = HID_DEFAULT_MIN_VALUE;
+		acc_feature.accel_sensitivity_max = HID_DEFAULT_MAX_VALUE;
+		memcpy(feature_report, &acc_feature, sizeof(acc_feature));
+		report_size = sizeof(acc_feature);
+		break;
+	case GYRO_IDX: /* gyroscope */
+		get_common_features(&gyro_feature.common_property, report_id);
+		gyro_feature.gyro_change_sesnitivity = HID_DEFAULT_SENSITIVITY;
+		gyro_feature.gyro_sensitivity_min = HID_DEFAULT_MIN_VALUE;
+		gyro_feature.gyro_sensitivity_max = HID_DEFAULT_MAX_VALUE;
+		memcpy(feature_report, &gyro_feature, sizeof(gyro_feature));
+		report_size = sizeof(gyro_feature);
+		break;
+	case MAG_IDX: /* magnetometer */
+		get_common_features(&magno_feature.common_property, report_id);
+		magno_feature.magno_headingchange_sensitivity = HID_DEFAULT_SENSITIVITY;
+		magno_feature.heading_min = HID_DEFAULT_MIN_VALUE;
+		magno_feature.heading_max = HID_DEFAULT_MAX_VALUE;
+		magno_feature.flux_change_sensitivity = HID_DEFAULT_MIN_VALUE;
+		magno_feature.flux_min = HID_DEFAULT_MIN_VALUE;
+		magno_feature.flux_max = HID_DEFAULT_MAX_VALUE;
+		memcpy(feature_report, &magno_feature, sizeof(magno_feature));
+		report_size = sizeof(magno_feature);
+		break;
+	case ALS_IDX:  /* ambient light sensor */
+		get_common_features(&als_feature.common_property, report_id);
+		als_feature.als_change_sesnitivity = HID_DEFAULT_SENSITIVITY;
+		als_feature.als_sensitivity_min = HID_DEFAULT_MIN_VALUE;
+		als_feature.als_sensitivity_max = HID_DEFAULT_MAX_VALUE;
+		memcpy(feature_report, &als_feature, sizeof(als_feature));
+		report_size = sizeof(als_feature);
+		break;
+	case HPD_IDX:  /* human presence detection sensor */
+		get_common_features(&hpd_feature.common_property, report_id);
+		memcpy(feature_report, &hpd_feature, sizeof(hpd_feature));
+		report_size = sizeof(hpd_feature);
+		break;
+	}
+	return report_size;
+}
+
+static void get_common_inputs(struct common_input_property *common, int report_id)
+{
+	common->report_id = report_id;
+	common->sensor_state = HID_USAGE_SENSOR_STATE_READY_ENUM;
+	common->event_type = HID_USAGE_SENSOR_EVENT_DATA_UPDATED_ENUM;
+}
+
+static int float_to_int(u32 float32)
+{
+	int fraction, shift, mantissa, sign, exp, zeropre;
+
+	mantissa = float32 & GENMASK(22, 0);
+	sign = (float32 & BIT(31)) ? -1 : 1;
+	exp = (float32 & ~BIT(31)) >> 23;
+
+	if (!exp && !mantissa)
+		return 0;
+
+	exp -= 127;
+	if (exp < 0) {
+		exp = -exp;
+		zeropre = (((BIT(23) + mantissa) * 100) >> 23) >> exp;
+		return zeropre >= 50 ? sign : 0;
+	}
+
+	shift = 23 - exp;
+	float32 = BIT(exp) + (mantissa >> shift);
+	fraction = mantissa & GENMASK(shift - 1, 0);
+
+	return (((fraction * 100) >> shift) >= 50) ? sign * (float32 + 1) : sign * float32;
+}
+
+static u8 get_input_rep(u8 current_index, int sensor_idx, int report_id,
+			struct amd_input_data *in_data)
+{
+	struct amd_mp2_dev *mp2 = container_of(in_data, struct amd_mp2_dev, in_data);
+	u8 *input_report = in_data->input_report[current_index];
+	struct magno_input_report magno_input;
+	struct accel3_input_report acc_input;
+	struct gyro_input_report gyro_input;
+	struct als_input_report als_input;
+	struct hpd_input_report hpd_input;
+	struct sfh_accel_data accel_data;
+	struct sfh_gyro_data gyro_data;
+	struct sfh_mag_data mag_data;
+	struct sfh_als_data als_data;
+	struct hpd_status hpdstatus;
+	void __iomem *sensoraddr;
+	u8 report_size = 0;
+
+	if (!input_report)
+		return report_size;
+
+	switch (sensor_idx) {
+	case ACCEL_IDX: /* accelerometer */
+		sensoraddr = mp2->vsbase + (ACCEL_IDX * SENSOR_DATA_MEM_SIZE_DEFAULT) +
+			     OFFSET_SENSOR_DATA_DEFAULT;
+		memcpy_fromio(&accel_data, sensoraddr, sizeof(struct sfh_accel_data));
+		get_common_inputs(&acc_input.common_property, report_id);
+		acc_input.in_accel_x_value = float_to_int(accel_data.acceldata.x) / 100;
+		acc_input.in_accel_y_value = float_to_int(accel_data.acceldata.y) / 100;
+		acc_input.in_accel_z_value = float_to_int(accel_data.acceldata.z) / 100;
+		memcpy(input_report, &acc_input, sizeof(acc_input));
+		report_size = sizeof(acc_input);
+		break;
+	case GYRO_IDX: /* gyroscope */
+		sensoraddr = mp2->vsbase + (GYRO_IDX * SENSOR_DATA_MEM_SIZE_DEFAULT) +
+			     OFFSET_SENSOR_DATA_DEFAULT;
+		memcpy_fromio(&gyro_data, sensoraddr, sizeof(struct sfh_gyro_data));
+		get_common_inputs(&gyro_input.common_property, report_id);
+		gyro_input.in_angel_x_value = float_to_int(gyro_data.gyrodata.x) / 1000;
+		gyro_input.in_angel_y_value = float_to_int(gyro_data.gyrodata.y) / 1000;
+		gyro_input.in_angel_z_value = float_to_int(gyro_data.gyrodata.z) / 1000;
+		memcpy(input_report, &gyro_input, sizeof(gyro_input));
+		report_size = sizeof(gyro_input);
+		break;
+	case MAG_IDX: /* magnetometer */
+		sensoraddr = mp2->vsbase + (MAG_IDX * SENSOR_DATA_MEM_SIZE_DEFAULT) +
+			     OFFSET_SENSOR_DATA_DEFAULT;
+		memcpy_fromio(&mag_data, sensoraddr, sizeof(struct sfh_mag_data));
+		get_common_inputs(&magno_input.common_property, report_id);
+		magno_input.in_magno_x = float_to_int(mag_data.magdata.x) / 100;
+		magno_input.in_magno_y = float_to_int(mag_data.magdata.y) / 100;
+		magno_input.in_magno_z = float_to_int(mag_data.magdata.z) / 100;
+		magno_input.in_magno_accuracy = mag_data.accuracy / 100;
+		memcpy(input_report, &magno_input, sizeof(magno_input));
+		report_size = sizeof(magno_input);
+		break;
+	case ALS_IDX:
+		sensoraddr = mp2->vsbase + (ALS_IDX * SENSOR_DATA_MEM_SIZE_DEFAULT) +
+			     OFFSET_SENSOR_DATA_DEFAULT;
+		memcpy_fromio(&als_data, sensoraddr, sizeof(struct sfh_als_data));
+		get_common_inputs(&als_input.common_property, report_id);
+		als_input.illuminance_value = als_data.lux;
+		report_size = sizeof(als_input);
+		memcpy(input_report, &als_input, sizeof(als_input));
+		break;
+	case HPD_IDX:
+		get_common_inputs(&hpd_input.common_property, report_id);
+		hpdstatus.val = readl(mp2->mmio + AMD_C2P_MSG(4));
+		hpd_input.human_presence = hpdstatus.shpd.presence;
+		report_size = sizeof(hpd_input);
+		memcpy(input_report, &hpd_input, sizeof(hpd_input));
+		break;
+	}
+	return report_size;
+}
+
+static u32 get_desc_size(int sensor_idx, int descriptor_name)
+{
+	switch (sensor_idx) {
+	case ACCEL_IDX:
+		switch (descriptor_name) {
+		case descr_size:
+			return sizeof(accel3_report_descriptor);
+		case input_size:
+			return sizeof(struct accel3_input_report);
+		case feature_size:
+			return sizeof(struct accel3_feature_report);
+		}
+		break;
+	case GYRO_IDX:
+		switch (descriptor_name) {
+		case descr_size:
+			return sizeof(gyro3_report_descriptor);
+		case input_size:
+			return sizeof(struct gyro_input_report);
+		case feature_size:
+			return sizeof(struct gyro_feature_report);
+		}
+		break;
+	case MAG_IDX:
+		switch (descriptor_name) {
+		case descr_size:
+			return sizeof(comp3_report_descriptor);
+		case input_size:
+			return sizeof(struct magno_input_report);
+		case feature_size:
+			return sizeof(struct magno_feature_report);
+		}
+		break;
+	case ALS_IDX:
+		switch (descriptor_name) {
+		case descr_size:
+			return sizeof(als_report_descriptor);
+		case input_size:
+			return sizeof(struct als_input_report);
+		case feature_size:
+			return sizeof(struct als_feature_report);
+		}
+		break;
+	case HPD_IDX:
+		switch (descriptor_name) {
+		case descr_size:
+			return sizeof(hpd_report_descriptor);
+		case input_size:
+			return sizeof(struct hpd_input_report);
+		case feature_size:
+			return sizeof(struct hpd_feature_report);
+		}
+		break;
+	}
+
+	return 0;
+}
+
+void amd_sfh1_1_set_desc_ops(struct amd_mp2_ops *mp2_ops)
+{
+	mp2_ops->get_rep_desc = get_report_desc;
+	mp2_ops->get_feat_rep = get_feature_rep;
+	mp2_ops->get_desc_sz = get_desc_size;
+	mp2_ops->get_in_rep = get_input_rep;
+}
diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
new file mode 100644
index 000000000000..70436f9fad2f
--- /dev/null
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
@@ -0,0 +1,324 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * AMD MP2 1.1 communication driver
+ *
+ * Copyright (c) 2022, Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Author: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/hid.h>
+
+#include "amd_sfh_init.h"
+#include "amd_sfh_interface.h"
+#include "../hid_descriptor/amd_sfh_hid_desc.h"
+
+static int amd_sfh_get_sensor_num(struct amd_mp2_dev *mp2, u8 *sensor_id)
+{
+	struct sfh_sensor_list *slist;
+	struct sfh_base_info binfo;
+	int num_of_sensors = 0;
+	int i;
+
+	memcpy_fromio(&binfo, mp2->vsbase, sizeof(struct sfh_base_info));
+	slist = &binfo.sbase.s_list;
+
+	for (i = 0; i < MAX_IDX; i++) {
+		switch (i) {
+		case ACCEL_IDX:
+		case GYRO_IDX:
+		case MAG_IDX:
+		case ALS_IDX:
+		case HPD_IDX:
+			if (BIT(i) & slist->sl.sensors)
+				sensor_id[num_of_sensors++] = i;
+			break;
+		}
+	}
+
+	return num_of_sensors;
+}
+
+static u32 amd_sfh_wait_for_response(struct amd_mp2_dev *mp2, u8 sid, u32 cmd_id)
+{
+	if (mp2->mp2_ops->response)
+		return mp2->mp2_ops->response(mp2, sid, cmd_id);
+
+	return 0;
+}
+
+static const char *get_sensor_name(int idx)
+{
+	switch (idx) {
+	case ACCEL_IDX:
+		return "accelerometer";
+	case GYRO_IDX:
+		return "gyroscope";
+	case MAG_IDX:
+		return "magnetometer";
+	case ALS_IDX:
+		return "ALS";
+	case HPD_IDX:
+		return "HPD";
+	default:
+		return "unknown sensor type";
+	}
+}
+
+static int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata)
+{
+	struct amdtp_cl_data *cl_data = privdata->cl_data;
+	int i, status;
+
+	for (i = 0; i < cl_data->num_hid_devices; i++) {
+		if (cl_data->sensor_sts[i] == SENSOR_ENABLED) {
+			privdata->mp2_ops->stop(privdata, cl_data->sensor_idx[i]);
+			status = amd_sfh_wait_for_response
+					(privdata, cl_data->sensor_idx[i], DISABLE_SENSOR);
+			if (status == 0)
+				cl_data->sensor_sts[i] = SENSOR_DISABLED;
+			dev_dbg(&privdata->pdev->dev, "stopping sid 0x%x (%s) status 0x%x\n",
+				cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
+				cl_data->sensor_sts[i]);
+		}
+	}
+
+	cancel_delayed_work_sync(&cl_data->work);
+	cancel_delayed_work_sync(&cl_data->work_buffer);
+	amdtp_hid_remove(cl_data);
+
+	return 0;
+}
+
+static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata)
+{
+	struct amd_input_data *in_data = &privdata->in_data;
+	struct amdtp_cl_data *cl_data = privdata->cl_data;
+	struct amd_mp2_ops *mp2_ops = privdata->mp2_ops;
+	struct amd_mp2_sensor_info info;
+	struct request_list *req_list;
+	u32 feature_report_size;
+	u32 input_report_size;
+	struct device *dev;
+	int rc, i, status;
+	u8 cl_idx;
+
+	req_list = &cl_data->req_list;
+	dev = &privdata->pdev->dev;
+	amd_sfh1_1_set_desc_ops(mp2_ops);
+
+	cl_data->num_hid_devices = amd_sfh_get_sensor_num(privdata, &cl_data->sensor_idx[0]);
+
+	INIT_DELAYED_WORK(&cl_data->work, amd_sfh_work);
+	INIT_DELAYED_WORK(&cl_data->work_buffer, amd_sfh_work_buffer);
+	INIT_LIST_HEAD(&req_list->list);
+	cl_data->in_data = in_data;
+
+	for (i = 0; i < cl_data->num_hid_devices; i++) {
+		cl_data->sensor_sts[i] = SENSOR_DISABLED;
+		cl_data->sensor_requested_cnt[i] = 0;
+		cl_data->cur_hid_dev = i;
+		cl_idx = cl_data->sensor_idx[i];
+
+		cl_data->report_descr_sz[i] = mp2_ops->get_desc_sz(cl_idx, descr_size);
+		if (!cl_data->report_descr_sz[i]) {
+			rc = -EINVAL;
+			goto cleanup;
+		}
+		feature_report_size = mp2_ops->get_desc_sz(cl_idx, feature_size);
+		if (!feature_report_size) {
+			rc = -EINVAL;
+			goto cleanup;
+		}
+		input_report_size =  mp2_ops->get_desc_sz(cl_idx, input_size);
+		if (!input_report_size) {
+			rc = -EINVAL;
+			goto cleanup;
+		}
+		cl_data->feature_report[i] = devm_kzalloc(dev, feature_report_size, GFP_KERNEL);
+		if (!cl_data->feature_report[i]) {
+			rc = -ENOMEM;
+			goto cleanup;
+		}
+		in_data->input_report[i] = devm_kzalloc(dev, input_report_size, GFP_KERNEL);
+		if (!in_data->input_report[i]) {
+			rc = -ENOMEM;
+			goto cleanup;
+		}
+
+		info.sensor_idx = cl_idx;
+
+		cl_data->report_descr[i] =
+			devm_kzalloc(dev, cl_data->report_descr_sz[i], GFP_KERNEL);
+		if (!cl_data->report_descr[i]) {
+			rc = -ENOMEM;
+			goto cleanup;
+		}
+		rc = mp2_ops->get_rep_desc(cl_idx, cl_data->report_descr[i]);
+		if (rc)
+			return rc;
+
+		writel(0, privdata->mmio + AMD_P2C_MSG(0));
+		mp2_ops->start(privdata, info);
+		status = amd_sfh_wait_for_response
+				(privdata, cl_data->sensor_idx[i], ENABLE_SENSOR);
+
+		status = (status == 0) ? SENSOR_ENABLED : SENSOR_DISABLED;
+
+		if (status == SENSOR_ENABLED) {
+			cl_data->sensor_sts[i] = SENSOR_ENABLED;
+			rc = amdtp_hid_probe(i, cl_data);
+			if (rc) {
+				mp2_ops->stop(privdata, cl_data->sensor_idx[i]);
+				status = amd_sfh_wait_for_response
+					(privdata, cl_data->sensor_idx[i], DISABLE_SENSOR);
+				if (status == 0)
+					status = SENSOR_DISABLED;
+				if (status != SENSOR_ENABLED)
+					cl_data->sensor_sts[i] = SENSOR_DISABLED;
+				dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n",
+					cl_data->sensor_idx[i],
+					get_sensor_name(cl_data->sensor_idx[i]),
+					cl_data->sensor_sts[i]);
+				goto cleanup;
+			}
+		}
+		dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n",
+			cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
+			cl_data->sensor_sts[i]);
+	}
+
+	schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
+	return 0;
+
+cleanup:
+	amd_sfh_hid_client_deinit(privdata);
+	for (i = 0; i < cl_data->num_hid_devices; i++) {
+		devm_kfree(dev, cl_data->feature_report[i]);
+		devm_kfree(dev, in_data->input_report[i]);
+		devm_kfree(dev, cl_data->report_descr[i]);
+	}
+	return rc;
+}
+
+static void amd_sfh_resume(struct amd_mp2_dev *mp2)
+{
+	struct amdtp_cl_data *cl_data = mp2->cl_data;
+	struct amd_mp2_sensor_info info;
+	int i, status;
+
+	for (i = 0; i < cl_data->num_hid_devices; i++) {
+		if (cl_data->sensor_sts[i] == SENSOR_DISABLED) {
+			info.sensor_idx = cl_data->sensor_idx[i];
+			mp2->mp2_ops->start(mp2, info);
+			status = amd_sfh_wait_for_response
+					(mp2, cl_data->sensor_idx[i], ENABLE_SENSOR);
+			if (status == 0)
+				status = SENSOR_ENABLED;
+			if (status == SENSOR_ENABLED)
+				cl_data->sensor_sts[i] = SENSOR_ENABLED;
+			dev_dbg(&mp2->pdev->dev, "resume sid 0x%x (%s) status 0x%x\n",
+				cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
+				cl_data->sensor_sts[i]);
+		}
+	}
+
+	schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
+	amd_sfh_clear_intr(mp2);
+}
+
+static void amd_sfh_suspend(struct amd_mp2_dev *mp2)
+{
+	struct amdtp_cl_data *cl_data = mp2->cl_data;
+	int i, status;
+
+	for (i = 0; i < cl_data->num_hid_devices; i++) {
+		if (cl_data->sensor_idx[i] != HPD_IDX &&
+		    cl_data->sensor_sts[i] == SENSOR_ENABLED) {
+			mp2->mp2_ops->stop(mp2, cl_data->sensor_idx[i]);
+			status = amd_sfh_wait_for_response
+					(mp2, cl_data->sensor_idx[i], DISABLE_SENSOR);
+			if (status == 0)
+				status = SENSOR_DISABLED;
+			if (status != SENSOR_ENABLED)
+				cl_data->sensor_sts[i] = SENSOR_DISABLED;
+			dev_dbg(&mp2->pdev->dev, "suspend sid 0x%x (%s) status 0x%x\n",
+				cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
+				cl_data->sensor_sts[i]);
+		}
+	}
+
+	cancel_delayed_work_sync(&cl_data->work_buffer);
+	amd_sfh_clear_intr(mp2);
+}
+
+static void amd_mp2_pci_remove(void *privdata)
+{
+	struct amd_mp2_dev *mp2 = privdata;
+
+	amd_sfh_hid_client_deinit(privdata);
+	mp2->mp2_ops->stop_all(mp2);
+	pci_intx(mp2->pdev, false);
+	amd_sfh_clear_intr(mp2);
+}
+
+static void amd_sfh_set_ops(struct amd_mp2_dev *mp2)
+{
+	struct amd_mp2_ops *mp2_ops;
+
+	sfh_interface_init(mp2);
+	mp2_ops = mp2->mp2_ops;
+	mp2_ops->clear_intr = amd_sfh_clear_intr_v2,
+	mp2_ops->init_intr = amd_sfh_irq_init_v2,
+	mp2_ops->suspend = amd_sfh_suspend;
+	mp2_ops->resume = amd_sfh_resume;
+	mp2_ops->remove = amd_mp2_pci_remove;
+}
+
+int amd_sfh1_1_init(struct amd_mp2_dev *mp2)
+{
+	u32 phy_base = readl(mp2->mmio + AMD_C2P_MSG(22));
+	struct device *dev = &mp2->pdev->dev;
+	struct sfh_base_info binfo;
+	int rc;
+
+	phy_base <<= 21;
+	if (!devm_request_mem_region(dev, phy_base, 128 * 1024, "amd_sfh")) {
+		dev_err(dev, "can't reserve mmio registers\n");
+		return -ENOMEM;
+	}
+
+	mp2->vsbase = devm_ioremap(dev, phy_base, 128 * 1024);
+	if (!mp2->vsbase) {
+		dev_err(dev, "failed to remap vsbase\n");
+		return -ENOMEM;
+	}
+
+	/* Before accessing give time for SFH firmware for processing configuration */
+	msleep(5000);
+
+	memcpy_fromio(&binfo, mp2->vsbase, sizeof(struct sfh_base_info));
+	if (binfo.sbase.fw_info.fw_ver == 0 || binfo.sbase.s_list.sl.sensors == 0) {
+		dev_err(dev, "failed to get sensors\n");
+		return -EOPNOTSUPP;
+	}
+	dev_dbg(dev, "firmware version 0x%x\n", binfo.sbase.fw_info.fw_ver);
+
+	amd_sfh_set_ops(mp2);
+
+	rc = amd_sfh_irq_init(mp2);
+	if (rc) {
+		dev_err(dev, "amd_sfh_irq_init failed\n");
+		return rc;
+	}
+
+	rc = amd_sfh1_1_hid_client_init(mp2);
+	if (rc) {
+		dev_err(dev, "amd_sfh1_1_hid_client_init failed\n");
+		return rc;
+	}
+
+	return rc;
+}
diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.h b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.h
new file mode 100644
index 000000000000..21c44990bbeb
--- /dev/null
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * AMD MP2 1.1 initialization structures
+ *
+ * Copyright (c) 2022, Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Author: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
+ */
+
+#ifndef AMD_SFH_INIT_H
+#define AMD_SFH_INIT_H
+
+#include "../amd_sfh_common.h"
+
+struct amd_sfh1_1_ops {
+	int (*init)(struct amd_mp2_dev *mp2);
+};
+
+int amd_sfh1_1_init(struct amd_mp2_dev *mp2);
+
+static const struct amd_sfh1_1_ops __maybe_unused sfh1_1_ops = {
+	.init = amd_sfh1_1_init,
+};
+
+#endif
diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
new file mode 100644
index 000000000000..14a1578055b6
--- /dev/null
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.c
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * AMD MP2 1.1 communication interfaces
+ *
+ * Copyright (c) 2022, Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Author: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
+ */
+#include <linux/iopoll.h>
+#include "amd_sfh_interface.h"
+
+static int amd_sfh_wait_response(struct amd_mp2_dev *mp2, u8 sid, u32 cmd_id)
+{
+	struct sfh_cmd_response cmd_resp;
+
+	/* Get response with status within a max of 1600 ms timeout */
+	if (!readl_poll_timeout(mp2->mmio + AMD_P2C_MSG(0), cmd_resp.resp,
+				(cmd_resp.response.response == 0 &&
+				cmd_resp.response.cmd_id == cmd_id && (sid == 0xff ||
+				cmd_resp.response.sensor_id == sid)), 500, 1600000))
+		return cmd_resp.response.response;
+
+	return -1;
+}
+
+static void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info)
+{
+	struct sfh_cmd_base cmd_base;
+
+	cmd_base.ul = 0;
+	cmd_base.cmd.cmd_id = ENABLE_SENSOR;
+	cmd_base.cmd.intr_disable = 0;
+	cmd_base.cmd.sensor_id = info.sensor_idx;
+
+	writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG(0));
+}
+
+static void amd_stop_sensor(struct amd_mp2_dev *privdata, u16 sensor_idx)
+{
+	struct sfh_cmd_base cmd_base;
+
+	cmd_base.ul = 0;
+	cmd_base.cmd.cmd_id = DISABLE_SENSOR;
+	cmd_base.cmd.intr_disable = 0;
+	cmd_base.cmd.sensor_id = sensor_idx;
+
+	writeq(0x0, privdata->mmio + AMD_C2P_MSG(1));
+	writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG(0));
+}
+
+static void amd_stop_all_sensor(struct amd_mp2_dev *privdata)
+{
+	struct sfh_cmd_base cmd_base;
+
+	cmd_base.ul = 0;
+	cmd_base.cmd.cmd_id = STOP_ALL_SENSORS;
+	cmd_base.cmd.intr_disable = 0;
+
+	writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG(0));
+}
+
+static struct amd_mp2_ops amd_sfh_ops = {
+	.start = amd_start_sensor,
+	.stop = amd_stop_sensor,
+	.stop_all = amd_stop_all_sensor,
+	.response = amd_sfh_wait_response,
+};
+
+void sfh_interface_init(struct amd_mp2_dev *mp2)
+{
+	mp2->mp2_ops = &amd_sfh_ops;
+}
diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h
new file mode 100644
index 000000000000..ae47a369dc05
--- /dev/null
+++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_interface.h
@@ -0,0 +1,154 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * AMD MP2 1.1 communication interfaces
+ *
+ * Copyright (c) 2022, Advanced Micro Devices, Inc.
+ * All Rights Reserved.
+ *
+ * Author: Basavaraj Natikar <Basavaraj.Natikar@amd.com>
+ */
+
+#ifndef AMD_SFH_INTERFACE_H
+#define AMD_SFH_INTERFACE_H
+
+#include "../amd_sfh_common.h"
+
+#define SENSOR_DATA_MEM_SIZE_DEFAULT		256
+#define TOTAL_STATIC_MEM_DEFAULT		1024
+#define OFFSET_SFH_INFO_BASE_DEFAULT		0
+#define OFFSET_SENSOR_DATA_DEFAULT		(OFFSET_SFH_INFO_BASE_DEFAULT + \
+							TOTAL_STATIC_MEM_DEFAULT)
+enum sensor_index {
+	ACCEL_IDX,
+	GYRO_IDX,
+	MAG_IDX,
+	ALS_IDX = 4,
+	HPD_IDX = 5,
+	MAX_IDX = 15,
+};
+
+struct sfh_cmd_base {
+	union {
+		u32 ul;
+		struct {
+			u32 sensor_id		: 4;
+			u32 cmd_id		: 4;
+			u32 sub_cmd_id		: 6;
+			u32 length		: 12;
+			u32 rsvd		: 5;
+			u32 intr_disable	: 1;
+		} cmd;
+	};
+};
+
+struct sfh_cmd_response {
+	union {
+		u32 resp;
+		struct {
+			u32 response	: 8;
+			u32 sensor_id	: 4;
+			u32 cmd_id	: 4;
+			u32 sub_cmd	: 6;
+			u32 rsvd2	: 10;
+		} response;
+	};
+};
+
+struct sfh_platform_info {
+	union {
+		u32 pi;
+		struct {
+			u32 cust_id		: 16;
+			u32 plat_id		: 6;
+			u32 interface_id	: 4;
+			u32 rsvd		: 6;
+		} pinfo;
+	};
+};
+
+struct sfh_firmware_info {
+	union {
+		u32 fw_ver;
+		struct {
+			u32 minor_rev : 8;
+			u32 major_rev : 8;
+			u32 minor_ver : 8;
+			u32 major_ver : 8;
+		} fver;
+	};
+};
+
+struct sfh_sensor_list {
+	union {
+		u32 slist;
+		struct {
+			u32 sensors	: 16;
+			u32 rsvd	: 16;
+		} sl;
+	};
+};
+
+struct sfh_base_info {
+	union {
+		u32 sfh_base[24];
+		struct {
+			struct sfh_platform_info plat_info;
+			struct sfh_firmware_info  fw_info;
+			struct sfh_sensor_list s_list;
+		} sbase;
+	};
+};
+
+struct sfh_common_data {
+	u64 timestamp;
+	u32 intr_cnt;
+	u32 featvalid		: 16;
+	u32 rsvd		: 13;
+	u32 sensor_state	: 3;
+};
+
+struct sfh_float32 {
+	u32 x;
+	u32 y;
+	u32 z;
+};
+
+struct sfh_accel_data {
+	struct sfh_common_data commondata;
+	struct sfh_float32 acceldata;
+	u32 accelstatus;
+};
+
+struct sfh_gyro_data {
+	struct sfh_common_data commondata;
+	struct sfh_float32 gyrodata;
+	u32 result;
+};
+
+struct sfh_mag_data {
+	struct sfh_common_data commondata;
+	struct sfh_float32 magdata;
+	u32 accuracy;
+};
+
+struct sfh_als_data {
+	struct sfh_common_data commondata;
+	u16 lux;
+};
+
+struct hpd_status {
+	union {
+		struct {
+			u32 distance			: 16;
+			u32 probablity			: 8;
+			u32 presence			: 2;
+			u32 rsvd			: 5;
+			u32 state			: 1;
+		} shpd;
+		u32 val;
+	};
+};
+
+void sfh_interface_init(struct amd_mp2_dev *mp2);
+void amd_sfh1_1_set_desc_ops(struct amd_mp2_ops *mp2_ops);
+#endif
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH 00/11] Fixes and implementation of AMD SFH 1.1 functionality
  2022-07-12 18:18 [PATCH 00/11] Fixes and implementation of AMD SFH 1.1 functionality Basavaraj Natikar
                   ` (10 preceding siblings ...)
  2022-07-12 18:18 ` [PATCH 11/11] HID: amd_sfh: Implement SFH1.1 functionality Basavaraj Natikar
@ 2022-07-21 11:44 ` Jiri Kosina
  11 siblings, 0 replies; 13+ messages in thread
From: Jiri Kosina @ 2022-07-21 11:44 UTC (permalink / raw)
  To: Basavaraj Natikar; +Cc: benjamin.tissoires, linux-input

On Tue, 12 Jul 2022, Basavaraj Natikar wrote:

> Changes includes fixes and support of new firmware (SFH 1.1) with new
> PCI device ID to implement SFH1.1 functionality which is used by
> newer AMD SOCs.

Queued in hid.git#for-5.20/amd-sfh. Thanks,

-- 
Jiri Kosina
SUSE Labs


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2022-07-21 11:45 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-12 18:18 [PATCH 00/11] Fixes and implementation of AMD SFH 1.1 functionality Basavaraj Natikar
2022-07-12 18:18 ` [PATCH 01/11] HID: amd_sfh: Add NULL check for hid device Basavaraj Natikar
2022-07-12 18:18 ` [PATCH 02/11] HID: amd_sfh: Move common macros and structures Basavaraj Natikar
2022-07-12 18:18 ` [PATCH 03/11] HID: amd_sfh: Move request_list struct to header file Basavaraj Natikar
2022-07-12 18:18 ` [PATCH 04/11] HID: amd_sfh: Move request_list variable to client data Basavaraj Natikar
2022-07-12 18:18 ` [PATCH 05/11] HID: amd_sfh: Add descriptor operations in amd_mp2_ops Basavaraj Natikar
2022-07-12 18:18 ` [PATCH 06/11] HID: amd_sfh: Add PM " Basavaraj Natikar
2022-07-12 18:18 ` [PATCH 07/11] HID: amd_sfh: Add remove operation " Basavaraj Natikar
2022-07-12 18:18 ` [PATCH 08/11] HID: amd_sfh: Move global functions to static Basavaraj Natikar
2022-07-12 18:18 ` [PATCH 09/11] HID: amd_sfh: Move amd_sfh_work to common interface Basavaraj Natikar
2022-07-12 18:18 ` [PATCH 10/11] HID: amd_sfh: Move interrupt handling " Basavaraj Natikar
2022-07-12 18:18 ` [PATCH 11/11] HID: amd_sfh: Implement SFH1.1 functionality Basavaraj Natikar
2022-07-21 11:44 ` [PATCH 00/11] Fixes and implementation of AMD SFH 1.1 functionality Jiri Kosina

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.