Skip to content

Commit 56e527b

Browse files
author
Jiri Kosina
committed
Merge branch 'for-5.15/amd-sfh' into for-linus
- Updates to the existing FW reporting mechanism, MP2 FW status checks, adding proper power management support for amd-sfh
2 parents bab94e9 + e665775 commit 56e527b

3 files changed

Lines changed: 139 additions & 15 deletions

File tree

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

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
#include "amd_sfh_pcie.h"
1818
#include "amd_sfh_hid.h"
1919

20-
#define AMD_SFH_IDLE_LOOP 200
2120

2221
struct request_list {
2322
struct hid_device *hid;
@@ -123,14 +122,24 @@ static void amd_sfh_work_buffer(struct work_struct *work)
123122
int i;
124123

125124
for (i = 0; i < cli_data->num_hid_devices; i++) {
126-
report_size = get_input_report(i, cli_data->sensor_idx[i], cli_data->report_id[i],
127-
in_data);
128-
hid_input_report(cli_data->hid_sensor_hubs[i], HID_INPUT_REPORT,
129-
in_data->input_report[i], report_size, 0);
125+
if (cli_data->sensor_sts[i] == SENSOR_ENABLED) {
126+
report_size = get_input_report
127+
(i, cli_data->sensor_idx[i], cli_data->report_id[i], in_data);
128+
hid_input_report(cli_data->hid_sensor_hubs[i], HID_INPUT_REPORT,
129+
in_data->input_report[i], report_size, 0);
130+
}
130131
}
131132
schedule_delayed_work(&cli_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
132133
}
133134

135+
u32 amd_sfh_wait_for_response(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts)
136+
{
137+
if (mp2->mp2_ops->response)
138+
sensor_sts = mp2->mp2_ops->response(mp2, sid, sensor_sts);
139+
140+
return sensor_sts;
141+
}
142+
134143
int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
135144
{
136145
struct amd_input_data *in_data = &privdata->in_data;
@@ -139,8 +148,8 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
139148
struct device *dev;
140149
u32 feature_report_size;
141150
u32 input_report_size;
151+
int rc, i, status;
142152
u8 cl_idx;
143-
int rc, i;
144153

145154
dev = &privdata->pdev->dev;
146155

@@ -155,7 +164,7 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
155164
in_data->sensor_virt_addr[i] = dma_alloc_coherent(dev, sizeof(int) * 8,
156165
&cl_data->sensor_dma_addr[i],
157166
GFP_KERNEL);
158-
cl_data->sensor_sts[i] = 0;
167+
cl_data->sensor_sts[i] = SENSOR_DISABLED;
159168
cl_data->sensor_requested_cnt[i] = 0;
160169
cl_data->cur_hid_dev = i;
161170
cl_idx = cl_data->sensor_idx[i];
@@ -184,7 +193,7 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
184193
rc = -ENOMEM;
185194
goto cleanup;
186195
}
187-
info.period = msecs_to_jiffies(AMD_SFH_IDLE_LOOP);
196+
info.period = AMD_SFH_IDLE_LOOP;
188197
info.sensor_idx = cl_idx;
189198
info.dma_address = cl_data->sensor_dma_addr[i];
190199

@@ -195,13 +204,27 @@ int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata)
195204
goto cleanup;
196205
}
197206
rc = get_report_descriptor(cl_idx, cl_data->report_descr[i]);
198-
if (rc)
199-
return rc;
200-
rc = amdtp_hid_probe(cl_data->cur_hid_dev, cl_data);
201207
if (rc)
202208
return rc;
203209
privdata->mp2_ops->start(privdata, info);
204-
cl_data->sensor_sts[i] = 1;
210+
status = amd_sfh_wait_for_response
211+
(privdata, cl_data->sensor_idx[i], SENSOR_ENABLED);
212+
if (status == SENSOR_ENABLED) {
213+
cl_data->sensor_sts[i] = SENSOR_ENABLED;
214+
rc = amdtp_hid_probe(cl_data->cur_hid_dev, cl_data);
215+
if (rc) {
216+
privdata->mp2_ops->stop(privdata, cl_data->sensor_idx[i]);
217+
status = amd_sfh_wait_for_response
218+
(privdata, cl_data->sensor_idx[i], SENSOR_DISABLED);
219+
if (status != SENSOR_ENABLED)
220+
cl_data->sensor_sts[i] = SENSOR_DISABLED;
221+
dev_dbg(dev, "sid 0x%x status 0x%x\n",
222+
cl_data->sensor_idx[i], cl_data->sensor_sts[i]);
223+
goto cleanup;
224+
}
225+
}
226+
dev_dbg(dev, "sid 0x%x status 0x%x\n",
227+
cl_data->sensor_idx[i], cl_data->sensor_sts[i]);
205228
}
206229
schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
207230
return 0;
@@ -224,10 +247,19 @@ int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata)
224247
{
225248
struct amdtp_cl_data *cl_data = privdata->cl_data;
226249
struct amd_input_data *in_data = cl_data->in_data;
227-
int i;
250+
int i, status;
228251

229-
for (i = 0; i < cl_data->num_hid_devices; i++)
230-
privdata->mp2_ops->stop(privdata, i);
252+
for (i = 0; i < cl_data->num_hid_devices; i++) {
253+
if (cl_data->sensor_sts[i] == SENSOR_ENABLED) {
254+
privdata->mp2_ops->stop(privdata, cl_data->sensor_idx[i]);
255+
status = amd_sfh_wait_for_response
256+
(privdata, cl_data->sensor_idx[i], SENSOR_DISABLED);
257+
if (status != SENSOR_ENABLED)
258+
cl_data->sensor_sts[i] = SENSOR_DISABLED;
259+
dev_dbg(&privdata->pdev->dev, "stopping sid 0x%x status 0x%x\n",
260+
cl_data->sensor_idx[i], cl_data->sensor_sts[i]);
261+
}
262+
}
231263

232264
cancel_delayed_work_sync(&cl_data->work);
233265
cancel_delayed_work_sync(&cl_data->work_buffer);

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

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
#include <linux/dmi.h>
1414
#include <linux/interrupt.h>
1515
#include <linux/io-64-nonatomic-lo-hi.h>
16+
#include <linux/iopoll.h>
1617
#include <linux/module.h>
1718
#include <linux/slab.h>
1819

@@ -31,6 +32,20 @@ static int sensor_mask_override = -1;
3132
module_param_named(sensor_mask, sensor_mask_override, int, 0444);
3233
MODULE_PARM_DESC(sensor_mask, "override the detected sensors mask");
3334

35+
static int amd_sfh_wait_response_v2(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts)
36+
{
37+
union cmd_response cmd_resp;
38+
39+
/* Get response with status within a max of 800 ms timeout */
40+
if (!readl_poll_timeout(mp2->mmio + AMD_P2C_MSG(0), cmd_resp.resp,
41+
(cmd_resp.response_v2.response == sensor_sts &&
42+
cmd_resp.response_v2.status == 0 && (sid == 0xff ||
43+
cmd_resp.response_v2.sensor_id == sid)), 500, 800000))
44+
return cmd_resp.response_v2.response;
45+
46+
return SENSOR_DISABLED;
47+
}
48+
3449
static void amd_start_sensor_v2(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info)
3550
{
3651
union sfh_cmd_base cmd_base;
@@ -183,6 +198,7 @@ static const struct amd_mp2_ops amd_sfh_ops_v2 = {
183198
.start = amd_start_sensor_v2,
184199
.stop = amd_stop_sensor_v2,
185200
.stop_all = amd_stop_all_sensor_v2,
201+
.response = amd_sfh_wait_response_v2,
186202
};
187203

188204
static const struct amd_mp2_ops amd_sfh_ops = {
@@ -248,6 +264,58 @@ static int amd_mp2_pci_probe(struct pci_dev *pdev, const struct pci_device_id *i
248264
return amd_sfh_hid_client_init(privdata);
249265
}
250266

267+
static int __maybe_unused amd_mp2_pci_resume(struct device *dev)
268+
{
269+
struct pci_dev *pdev = to_pci_dev(dev);
270+
struct amd_mp2_dev *mp2 = pci_get_drvdata(pdev);
271+
struct amdtp_cl_data *cl_data = mp2->cl_data;
272+
struct amd_mp2_sensor_info info;
273+
int i, status;
274+
275+
for (i = 0; i < cl_data->num_hid_devices; i++) {
276+
if (cl_data->sensor_sts[i] == SENSOR_DISABLED) {
277+
info.period = AMD_SFH_IDLE_LOOP;
278+
info.sensor_idx = cl_data->sensor_idx[i];
279+
info.dma_address = cl_data->sensor_dma_addr[i];
280+
mp2->mp2_ops->start(mp2, info);
281+
status = amd_sfh_wait_for_response
282+
(mp2, cl_data->sensor_idx[i], SENSOR_ENABLED);
283+
if (status == SENSOR_ENABLED)
284+
cl_data->sensor_sts[i] = SENSOR_ENABLED;
285+
dev_dbg(dev, "resume sid 0x%x status 0x%x\n",
286+
cl_data->sensor_idx[i], cl_data->sensor_sts[i]);
287+
}
288+
}
289+
290+
return 0;
291+
}
292+
293+
static int __maybe_unused amd_mp2_pci_suspend(struct device *dev)
294+
{
295+
struct pci_dev *pdev = to_pci_dev(dev);
296+
struct amd_mp2_dev *mp2 = pci_get_drvdata(pdev);
297+
struct amdtp_cl_data *cl_data = mp2->cl_data;
298+
int i, status;
299+
300+
for (i = 0; i < cl_data->num_hid_devices; i++) {
301+
if (cl_data->sensor_idx[i] != HPD_IDX &&
302+
cl_data->sensor_sts[i] == SENSOR_ENABLED) {
303+
mp2->mp2_ops->stop(mp2, cl_data->sensor_idx[i]);
304+
status = amd_sfh_wait_for_response
305+
(mp2, cl_data->sensor_idx[i], SENSOR_DISABLED);
306+
if (status != SENSOR_ENABLED)
307+
cl_data->sensor_sts[i] = SENSOR_DISABLED;
308+
dev_dbg(dev, "suspend sid 0x%x status 0x%x\n",
309+
cl_data->sensor_idx[i], cl_data->sensor_sts[i]);
310+
}
311+
}
312+
313+
return 0;
314+
}
315+
316+
static SIMPLE_DEV_PM_OPS(amd_mp2_pm_ops, amd_mp2_pci_suspend,
317+
amd_mp2_pci_resume);
318+
251319
static const struct pci_device_id amd_mp2_pci_tbl[] = {
252320
{ PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_MP2) },
253321
{ }
@@ -258,6 +326,7 @@ static struct pci_driver amd_mp2_pci_driver = {
258326
.name = DRIVER_NAME,
259327
.id_table = amd_mp2_pci_tbl,
260328
.probe = amd_mp2_pci_probe,
329+
.driver.pm = &amd_mp2_pm_ops,
261330
};
262331
module_pci_driver(amd_mp2_pci_driver);
263332

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

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,20 @@
2424
#define AMD_C2P_MSG2 0x10508
2525

2626
#define AMD_C2P_MSG(regno) (0x10500 + ((regno) * 4))
27+
#define AMD_P2C_MSG(regno) (0x10680 + ((regno) * 4))
2728

2829
/* MP2 P2C Message Registers */
2930
#define AMD_P2C_MSG3 0x1068C /* Supported Sensors info */
3031

3132
#define V2_STATUS 0x2
3233

34+
#define SENSOR_ENABLED 4
35+
#define SENSOR_DISABLED 5
36+
3337
#define HPD_IDX 16
3438

39+
#define AMD_SFH_IDLE_LOOP 200
40+
3541
/* SFH Command register */
3642
union sfh_cmd_base {
3743
u32 ul;
@@ -51,6 +57,19 @@ union sfh_cmd_base {
5157
} cmd_v2;
5258
};
5359

60+
union cmd_response {
61+
u32 resp;
62+
struct {
63+
u32 status : 2;
64+
u32 out_in_c2p : 1;
65+
u32 rsvd1 : 1;
66+
u32 response : 4;
67+
u32 sub_cmd : 8;
68+
u32 sensor_id : 6;
69+
u32 rsvd2 : 10;
70+
} response_v2;
71+
};
72+
5473
union sfh_cmd_param {
5574
u32 ul;
5675
struct {
@@ -112,10 +131,14 @@ void amd_stop_all_sensors(struct amd_mp2_dev *privdata);
112131
int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id);
113132
int amd_sfh_hid_client_init(struct amd_mp2_dev *privdata);
114133
int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata);
134+
u32 amd_sfh_wait_for_response(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts);
135+
void amd_mp2_suspend(struct amd_mp2_dev *mp2);
136+
void amd_mp2_resume(struct amd_mp2_dev *mp2);
115137

116138
struct amd_mp2_ops {
117139
void (*start)(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info);
118140
void (*stop)(struct amd_mp2_dev *privdata, u16 sensor_idx);
119141
void (*stop_all)(struct amd_mp2_dev *privdata);
142+
int (*response)(struct amd_mp2_dev *mp2, u8 sid, u32 sensor_sts);
120143
};
121144
#endif

0 commit comments

Comments
 (0)