Skip to content

Commit c556717

Browse files
author
Jiri Kosina
committed
Merge branch 'for-5.20/amd-sfh' into for-linus
- support for AMD SOCs using SFH1.1 memory access (Basavaraj Natikar)
2 parents 1117d18 + 5d4d0f1 commit c556717

14 files changed

+1103
-143
lines changed

drivers/hid/amd-sfh-hid/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,8 @@ amd_sfh-objs := amd_sfh_hid.o
99
amd_sfh-objs += amd_sfh_client.o
1010
amd_sfh-objs += amd_sfh_pcie.o
1111
amd_sfh-objs += hid_descriptor/amd_sfh_hid_desc.o
12+
amd_sfh-objs += sfh1_1/amd_sfh_init.o
13+
amd_sfh-objs += sfh1_1/amd_sfh_interface.o
14+
amd_sfh-objs += sfh1_1/amd_sfh_desc.o
1215

1316
ccflags-y += -I $(srctree)/$(src)/

drivers/hid/amd-sfh-hid/amd_sfh_client.c

Lines changed: 85 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,6 @@
1818
#include "amd_sfh_pcie.h"
1919
#include "amd_sfh_hid.h"
2020

21-
22-
struct request_list {
23-
struct hid_device *hid;
24-
struct list_head list;
25-
u8 report_id;
26-
u8 sensor_idx;
27-
u8 report_type;
28-
u8 current_index;
29-
};
30-
31-
static struct request_list req_list;
32-
3321
void amd_sfh_set_report(struct hid_device *hid, int report_id,
3422
int report_type)
3523
{
@@ -50,6 +38,7 @@ int amd_sfh_get_report(struct hid_device *hid, int report_id, int report_type)
5038
{
5139
struct amdtp_hid_data *hid_data = hid->driver_data;
5240
struct amdtp_cl_data *cli_data = hid_data->cli_data;
41+
struct request_list *req_list = &cli_data->req_list;
5342
int i;
5443

5544
for (i = 0; i < cli_data->num_hid_devices; i++) {
@@ -66,34 +55,39 @@ int amd_sfh_get_report(struct hid_device *hid, int report_id, int report_type)
6655
new->report_id = report_id;
6756
cli_data->report_id[i] = report_id;
6857
cli_data->request_done[i] = false;
69-
list_add(&new->list, &req_list.list);
58+
list_add(&new->list, &req_list->list);
7059
break;
7160
}
7261
}
7362
schedule_delayed_work(&cli_data->work, 0);
7463
return 0;
7564
}
7665

77-
static void amd_sfh_work(struct work_struct *work)
66+
void amd_sfh_work(struct work_struct *work)
7867
{
7968
struct amdtp_cl_data *cli_data = container_of(work, struct amdtp_cl_data, work.work);
69+
struct request_list *req_list = &cli_data->req_list;
8070
struct amd_input_data *in_data = cli_data->in_data;
8171
struct request_list *req_node;
8272
u8 current_index, sensor_index;
73+
struct amd_mp2_ops *mp2_ops;
74+
struct amd_mp2_dev *mp2;
8375
u8 report_id, node_type;
8476
u8 report_size = 0;
8577

86-
req_node = list_last_entry(&req_list.list, struct request_list, list);
78+
req_node = list_last_entry(&req_list->list, struct request_list, list);
8779
list_del(&req_node->list);
8880
current_index = req_node->current_index;
8981
sensor_index = req_node->sensor_idx;
9082
report_id = req_node->report_id;
9183
node_type = req_node->report_type;
9284
kfree(req_node);
9385

86+
mp2 = container_of(in_data, struct amd_mp2_dev, in_data);
87+
mp2_ops = mp2->mp2_ops;
9488
if (node_type == HID_FEATURE_REPORT) {
95-
report_size = get_feature_report(sensor_index, report_id,
96-
cli_data->feature_report[current_index]);
89+
report_size = mp2_ops->get_feat_rep(sensor_index, report_id,
90+
cli_data->feature_report[current_index]);
9791
if (report_size)
9892
hid_input_report(cli_data->hid_sensor_hubs[current_index],
9993
cli_data->report_type[current_index],
@@ -102,7 +96,7 @@ static void amd_sfh_work(struct work_struct *work)
10296
pr_err("AMDSFH: Invalid report size\n");
10397

10498
} else if (node_type == HID_INPUT_REPORT) {
105-
report_size = get_input_report(current_index, sensor_index, report_id, in_data);
99+
report_size = mp2_ops->get_in_rep(current_index, sensor_index, report_id, in_data);
106100
if (report_size)
107101
hid_input_report(cli_data->hid_sensor_hubs[current_index],
108102
cli_data->report_type[current_index],
@@ -115,33 +109,35 @@ static void amd_sfh_work(struct work_struct *work)
115109
amdtp_hid_wakeup(cli_data->hid_sensor_hubs[current_index]);
116110
}
117111

118-
static void amd_sfh_work_buffer(struct work_struct *work)
112+
void amd_sfh_work_buffer(struct work_struct *work)
119113
{
120114
struct amdtp_cl_data *cli_data = container_of(work, struct amdtp_cl_data, work_buffer.work);
121115
struct amd_input_data *in_data = cli_data->in_data;
116+
struct amd_mp2_dev *mp2;
122117
u8 report_size;
123118
int i;
124119

125120
for (i = 0; i < cli_data->num_hid_devices; i++) {
126121
if (cli_data->sensor_sts[i] == SENSOR_ENABLED) {
127-
report_size = get_input_report
128-
(i, cli_data->sensor_idx[i], cli_data->report_id[i], in_data);
122+
mp2 = container_of(in_data, struct amd_mp2_dev, in_data);
123+
report_size = mp2->mp2_ops->get_in_rep(i, cli_data->sensor_idx[i],
124+
cli_data->report_id[i], in_data);
129125
hid_input_report(cli_data->hid_sensor_hubs[i], HID_INPUT_REPORT,
130126
in_data->input_report[i], report_size, 0);
131127
}
132128
}
133129
schedule_delayed_work(&cli_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
134130
}
135131

136-
u32 amd_sfh_wait_for_response(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts)
132+
static u32 amd_sfh_wait_for_response(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts)
137133
{
138134
if (mp2->mp2_ops->response)
139135
sensor_sts = mp2->mp2_ops->response(mp2, sid, sensor_sts);
140136

141137
return sensor_sts;
142138
}
143139

144-
const char *get_sensor_name(int idx)
140+
static const char *get_sensor_name(int idx)
145141
{
146142
switch (idx) {
147143
case accel_idx:
@@ -159,24 +155,82 @@ const char *get_sensor_name(int idx)
159155
}
160156
}
161157

158+
static void amd_sfh_resume(struct amd_mp2_dev *mp2)
159+
{
160+
struct amdtp_cl_data *cl_data = mp2->cl_data;
161+
struct amd_mp2_sensor_info info;
162+
int i, status;
163+
164+
for (i = 0; i < cl_data->num_hid_devices; i++) {
165+
if (cl_data->sensor_sts[i] == SENSOR_DISABLED) {
166+
info.period = AMD_SFH_IDLE_LOOP;
167+
info.sensor_idx = cl_data->sensor_idx[i];
168+
info.dma_address = cl_data->sensor_dma_addr[i];
169+
mp2->mp2_ops->start(mp2, info);
170+
status = amd_sfh_wait_for_response
171+
(mp2, cl_data->sensor_idx[i], SENSOR_ENABLED);
172+
if (status == SENSOR_ENABLED)
173+
cl_data->sensor_sts[i] = SENSOR_ENABLED;
174+
dev_dbg(&mp2->pdev->dev, "resume sid 0x%x (%s) status 0x%x\n",
175+
cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
176+
cl_data->sensor_sts[i]);
177+
}
178+
}
179+
180+
schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
181+
amd_sfh_clear_intr(mp2);
182+
}
183+
184+
static void amd_sfh_suspend(struct amd_mp2_dev *mp2)
185+
{
186+
struct amdtp_cl_data *cl_data = mp2->cl_data;
187+
int i, status;
188+
189+
for (i = 0; i < cl_data->num_hid_devices; i++) {
190+
if (cl_data->sensor_idx[i] != HPD_IDX &&
191+
cl_data->sensor_sts[i] == SENSOR_ENABLED) {
192+
mp2->mp2_ops->stop(mp2, cl_data->sensor_idx[i]);
193+
status = amd_sfh_wait_for_response
194+
(mp2, cl_data->sensor_idx[i], SENSOR_DISABLED);
195+
if (status != SENSOR_ENABLED)
196+
cl_data->sensor_sts[i] = SENSOR_DISABLED;
197+
dev_dbg(&mp2->pdev->dev, "suspend sid 0x%x (%s) status 0x%x\n",
198+
cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
199+
cl_data->sensor_sts[i]);
200+
}
201+
}
202+
203+
cancel_delayed_work_sync(&cl_data->work_buffer);
204+
amd_sfh_clear_intr(mp2);
205+
}
206+
162207
int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
163208
{
164209
struct amd_input_data *in_data = &privdata->in_data;
165210
struct amdtp_cl_data *cl_data = privdata->cl_data;
211+
struct amd_mp2_ops *mp2_ops = privdata->mp2_ops;
166212
struct amd_mp2_sensor_info info;
213+
struct request_list *req_list;
167214
struct device *dev;
168215
u32 feature_report_size;
169216
u32 input_report_size;
170217
int rc, i, status;
171218
u8 cl_idx;
172219

220+
req_list = &cl_data->req_list;
173221
dev = &privdata->pdev->dev;
222+
amd_sfh_set_desc_ops(mp2_ops);
223+
224+
mp2_ops->suspend = amd_sfh_suspend;
225+
mp2_ops->resume = amd_sfh_resume;
174226

175227
cl_data->num_hid_devices = amd_mp2_get_sensor_num(privdata, &cl_data->sensor_idx[0]);
228+
if (cl_data->num_hid_devices == 0)
229+
return -ENODEV;
176230

177231
INIT_DELAYED_WORK(&cl_data->work, amd_sfh_work);
178232
INIT_DELAYED_WORK(&cl_data->work_buffer, amd_sfh_work_buffer);
179-
INIT_LIST_HEAD(&req_list.list);
233+
INIT_LIST_HEAD(&req_list->list);
180234
cl_data->in_data = in_data;
181235

182236
for (i = 0; i < cl_data->num_hid_devices; i++) {
@@ -187,17 +241,17 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
187241
cl_data->sensor_requested_cnt[i] = 0;
188242
cl_data->cur_hid_dev = i;
189243
cl_idx = cl_data->sensor_idx[i];
190-
cl_data->report_descr_sz[i] = get_descr_sz(cl_idx, descr_size);
244+
cl_data->report_descr_sz[i] = mp2_ops->get_desc_sz(cl_idx, descr_size);
191245
if (!cl_data->report_descr_sz[i]) {
192246
rc = -EINVAL;
193247
goto cleanup;
194248
}
195-
feature_report_size = get_descr_sz(cl_idx, feature_size);
249+
feature_report_size = mp2_ops->get_desc_sz(cl_idx, feature_size);
196250
if (!feature_report_size) {
197251
rc = -EINVAL;
198252
goto cleanup;
199253
}
200-
input_report_size = get_descr_sz(cl_idx, input_size);
254+
input_report_size = mp2_ops->get_desc_sz(cl_idx, input_size);
201255
if (!input_report_size) {
202256
rc = -EINVAL;
203257
goto cleanup;
@@ -222,17 +276,17 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
222276
rc = -ENOMEM;
223277
goto cleanup;
224278
}
225-
rc = get_report_descriptor(cl_idx, cl_data->report_descr[i]);
279+
rc = mp2_ops->get_rep_desc(cl_idx, cl_data->report_descr[i]);
226280
if (rc)
227281
return rc;
228-
privdata->mp2_ops->start(privdata, info);
282+
mp2_ops->start(privdata, info);
229283
status = amd_sfh_wait_for_response
230284
(privdata, cl_data->sensor_idx[i], SENSOR_ENABLED);
231285
if (status == SENSOR_ENABLED) {
232286
cl_data->sensor_sts[i] = SENSOR_ENABLED;
233287
rc = amdtp_hid_probe(cl_data->cur_hid_dev, cl_data);
234288
if (rc) {
235-
privdata->mp2_ops->stop(privdata, cl_data->sensor_idx[i]);
289+
mp2_ops->stop(privdata, cl_data->sensor_idx[i]);
236290
status = amd_sfh_wait_for_response
237291
(privdata, cl_data->sensor_idx[i], SENSOR_DISABLED);
238292
if (status != SENSOR_ENABLED)
@@ -248,8 +302,7 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
248302
cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
249303
cl_data->sensor_sts[i]);
250304
}
251-
if (privdata->mp2_ops->discovery_status &&
252-
privdata->mp2_ops->discovery_status(privdata) == 0) {
305+
if (mp2_ops->discovery_status && mp2_ops->discovery_status(privdata) == 0) {
253306
amd_sfh_hid_client_deinit(privdata);
254307
for (i = 0; i < cl_data->num_hid_devices; i++) {
255308
devm_kfree(dev, cl_data->feature_report[i]);
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/* SPDX-License-Identifier: GPL-2.0-or-later */
2+
/*
3+
* AMD MP2 common macros and structures
4+
*
5+
* Copyright (c) 2022, Advanced Micro Devices, Inc.
6+
* All Rights Reserved.
7+
*
8+
* Author: Basavaraj Natikar <[email protected]>
9+
*/
10+
#ifndef AMD_SFH_COMMON_H
11+
#define AMD_SFH_COMMON_H
12+
13+
#include <linux/pci.h>
14+
#include "amd_sfh_hid.h"
15+
16+
#define PCI_DEVICE_ID_AMD_MP2 0x15E4
17+
#define PCI_DEVICE_ID_AMD_MP2_1_1 0x164A
18+
19+
#define AMD_C2P_MSG(regno) (0x10500 + ((regno) * 4))
20+
#define AMD_P2C_MSG(regno) (0x10680 + ((regno) * 4))
21+
22+
#define SENSOR_ENABLED 4
23+
#define SENSOR_DISABLED 5
24+
25+
#define AMD_SFH_IDLE_LOOP 200
26+
27+
enum cmd_id {
28+
NO_OP,
29+
ENABLE_SENSOR,
30+
DISABLE_SENSOR,
31+
STOP_ALL_SENSORS = 8,
32+
};
33+
34+
struct amd_mp2_sensor_info {
35+
u8 sensor_idx;
36+
u32 period;
37+
dma_addr_t dma_address;
38+
};
39+
40+
struct amd_mp2_dev {
41+
struct pci_dev *pdev;
42+
struct amdtp_cl_data *cl_data;
43+
void __iomem *mmio;
44+
void __iomem *vsbase;
45+
const struct amd_sfh1_1_ops *sfh1_1_ops;
46+
struct amd_mp2_ops *mp2_ops;
47+
struct amd_input_data in_data;
48+
/* mp2 active control status */
49+
u32 mp2_acs;
50+
};
51+
52+
struct amd_mp2_ops {
53+
void (*start)(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info);
54+
void (*stop)(struct amd_mp2_dev *privdata, u16 sensor_idx);
55+
void (*stop_all)(struct amd_mp2_dev *privdata);
56+
int (*response)(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts);
57+
void (*clear_intr)(struct amd_mp2_dev *privdata);
58+
int (*init_intr)(struct amd_mp2_dev *privdata);
59+
int (*discovery_status)(struct amd_mp2_dev *privdata);
60+
void (*suspend)(struct amd_mp2_dev *mp2);
61+
void (*resume)(struct amd_mp2_dev *mp2);
62+
void (*remove)(void *privdata);
63+
int (*get_rep_desc)(int sensor_idx, u8 rep_desc[]);
64+
u32 (*get_desc_sz)(int sensor_idx, int descriptor_name);
65+
u8 (*get_feat_rep)(int sensor_idx, int report_id, u8 *feature_report);
66+
u8 (*get_in_rep)(u8 current_index, int sensor_idx, int report_id,
67+
struct amd_input_data *in_data);
68+
};
69+
70+
void amd_sfh_work(struct work_struct *work);
71+
void amd_sfh_work_buffer(struct work_struct *work);
72+
void amd_sfh_clear_intr_v2(struct amd_mp2_dev *privdata);
73+
int amd_sfh_irq_init_v2(struct amd_mp2_dev *privdata);
74+
void amd_sfh_clear_intr(struct amd_mp2_dev *privdata);
75+
int amd_sfh_irq_init(struct amd_mp2_dev *privdata);
76+
#endif

drivers/hid/amd-sfh-hid/amd_sfh_hid.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,15 @@ static int amdtp_wait_for_response(struct hid_device *hid)
101101

102102
void amdtp_hid_wakeup(struct hid_device *hid)
103103
{
104-
struct amdtp_hid_data *hid_data = hid->driver_data;
105-
struct amdtp_cl_data *cli_data = hid_data->cli_data;
104+
struct amdtp_hid_data *hid_data;
105+
struct amdtp_cl_data *cli_data;
106106

107-
cli_data->request_done[cli_data->cur_hid_dev] = true;
108-
wake_up_interruptible(&hid_data->hid_wait);
107+
if (hid) {
108+
hid_data = hid->driver_data;
109+
cli_data = hid_data->cli_data;
110+
cli_data->request_done[cli_data->cur_hid_dev] = true;
111+
wake_up_interruptible(&hid_data->hid_wait);
112+
}
109113
}
110114

111115
static struct hid_ll_driver amdtp_hid_ll_driver = {

drivers/hid/amd-sfh-hid/amd_sfh_hid.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,15 @@
1515
#define AMD_SFH_HID_VENDOR 0x1022
1616
#define AMD_SFH_HID_PRODUCT 0x0001
1717

18+
struct request_list {
19+
struct hid_device *hid;
20+
struct list_head list;
21+
u8 report_id;
22+
u8 sensor_idx;
23+
u8 report_type;
24+
u8 current_index;
25+
};
26+
1827
struct amd_input_data {
1928
u32 *sensor_virt_addr[MAX_HID_DEVICES];
2029
u8 *input_report[MAX_HID_DEVICES];
@@ -43,6 +52,7 @@ struct amdtp_cl_data {
4352
struct amd_input_data *in_data;
4453
struct delayed_work work;
4554
struct delayed_work work_buffer;
55+
struct request_list req_list;
4656
};
4757

4858
/**
@@ -69,6 +79,4 @@ void amdtp_hid_remove(struct amdtp_cl_data *cli_data);
6979
int amd_sfh_get_report(struct hid_device *hid, int report_id, int report_type);
7080
void amd_sfh_set_report(struct hid_device *hid, int report_id, int report_type);
7181
void amdtp_hid_wakeup(struct hid_device *hid);
72-
u8 get_input_report(u8 current_index, int sensor_idx, int report_id,
73-
struct amd_input_data *in_data);
7482
#endif

0 commit comments

Comments
 (0)