Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c
54337 views
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
* AMD MP2 1.1 communication driver
4
*
5
* Copyright (c) 2022, Advanced Micro Devices, Inc.
6
* All Rights Reserved.
7
*
8
* Author: Basavaraj Natikar <[email protected]>
9
*/
10
11
#include <linux/delay.h>
12
#include <linux/hid.h>
13
14
#include "amd_sfh_init.h"
15
#include "amd_sfh_interface.h"
16
#include "../hid_descriptor/amd_sfh_hid_desc.h"
17
18
static int amd_sfh_get_sensor_num(struct amd_mp2_dev *mp2, u8 *sensor_id)
19
{
20
struct sfh_sensor_list *slist;
21
struct sfh_base_info binfo;
22
int num_of_sensors = 0;
23
int i;
24
25
memcpy_fromio(&binfo, mp2->vsbase, sizeof(struct sfh_base_info));
26
slist = &binfo.sbase.s_list;
27
28
for (i = 0; i < MAX_IDX; i++) {
29
switch (i) {
30
case ACCEL_IDX:
31
case GYRO_IDX:
32
case MAG_IDX:
33
case SRA_IDX:
34
case ALS_IDX:
35
case HPD_IDX:
36
if (BIT(i) & slist->sl.sensors)
37
sensor_id[num_of_sensors++] = i;
38
break;
39
}
40
}
41
42
return num_of_sensors;
43
}
44
45
static u32 amd_sfh_wait_for_response(struct amd_mp2_dev *mp2, u8 sid, u32 cmd_id)
46
{
47
if (mp2->mp2_ops->response)
48
return mp2->mp2_ops->response(mp2, sid, cmd_id);
49
50
return 0;
51
}
52
53
static const char *get_sensor_name(int idx)
54
{
55
switch (idx) {
56
case ACCEL_IDX:
57
return "accelerometer";
58
case GYRO_IDX:
59
return "gyroscope";
60
case MAG_IDX:
61
return "magnetometer";
62
case SRA_IDX:
63
return "SRA";
64
case ALS_IDX:
65
return "ALS";
66
case HPD_IDX:
67
return "HPD";
68
default:
69
return "unknown sensor type";
70
}
71
}
72
73
static int amd_sfh_hid_client_deinit(struct amd_mp2_dev *privdata)
74
{
75
struct amdtp_cl_data *cl_data = privdata->cl_data;
76
int i, status;
77
78
for (i = 0; i < cl_data->num_hid_devices; i++) {
79
switch (cl_data->sensor_idx[i]) {
80
case HPD_IDX:
81
privdata->dev_en.is_hpd_present = false;
82
break;
83
case ALS_IDX:
84
privdata->dev_en.is_als_present = false;
85
break;
86
case SRA_IDX:
87
privdata->dev_en.is_sra_present = false;
88
break;
89
}
90
91
if (cl_data->sensor_sts[i] == SENSOR_ENABLED) {
92
privdata->mp2_ops->stop(privdata, cl_data->sensor_idx[i]);
93
status = amd_sfh_wait_for_response
94
(privdata, cl_data->sensor_idx[i], DISABLE_SENSOR);
95
if (status == 0)
96
cl_data->sensor_sts[i] = SENSOR_DISABLED;
97
dev_dbg(&privdata->pdev->dev, "stopping sid 0x%x (%s) status 0x%x\n",
98
cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
99
cl_data->sensor_sts[i]);
100
}
101
}
102
103
cancel_delayed_work_sync(&cl_data->work);
104
cancel_delayed_work_sync(&cl_data->work_buffer);
105
amdtp_hid_remove(cl_data);
106
107
return 0;
108
}
109
110
static int amd_sfh1_1_hid_client_init(struct amd_mp2_dev *privdata)
111
{
112
struct amd_input_data *in_data = &privdata->in_data;
113
struct amdtp_cl_data *cl_data = privdata->cl_data;
114
struct amd_mp2_ops *mp2_ops = privdata->mp2_ops;
115
struct amd_mp2_sensor_info info;
116
struct request_list *req_list;
117
u32 feature_report_size;
118
u32 input_report_size;
119
struct device *dev;
120
int rc, i, status;
121
u8 cl_idx;
122
123
req_list = &cl_data->req_list;
124
dev = &privdata->pdev->dev;
125
amd_sfh1_1_set_desc_ops(mp2_ops);
126
127
cl_data->num_hid_devices = amd_sfh_get_sensor_num(privdata, &cl_data->sensor_idx[0]);
128
if (cl_data->num_hid_devices == 0)
129
return -ENODEV;
130
cl_data->is_any_sensor_enabled = false;
131
132
INIT_DELAYED_WORK(&cl_data->work, amd_sfh_work);
133
INIT_DELAYED_WORK(&cl_data->work_buffer, amd_sfh_work_buffer);
134
INIT_LIST_HEAD(&req_list->list);
135
cl_data->in_data = in_data;
136
137
for (i = 0; i < cl_data->num_hid_devices; i++) {
138
cl_data->sensor_sts[i] = SENSOR_DISABLED;
139
140
if (cl_data->sensor_idx[i] == SRA_IDX) {
141
info.sensor_idx = cl_data->sensor_idx[i];
142
writel(0, privdata->mmio + amd_get_p2c_val(privdata, 0));
143
mp2_ops->start(privdata, info);
144
status = amd_sfh_wait_for_response
145
(privdata, cl_data->sensor_idx[i], ENABLE_SENSOR);
146
147
cl_data->sensor_sts[i] = (status == 0) ? SENSOR_ENABLED : SENSOR_DISABLED;
148
if (cl_data->sensor_sts[i] == SENSOR_ENABLED) {
149
cl_data->is_any_sensor_enabled = true;
150
privdata->dev_en.is_sra_present = true;
151
}
152
continue;
153
}
154
155
cl_data->sensor_requested_cnt[i] = 0;
156
cl_data->cur_hid_dev = i;
157
cl_idx = cl_data->sensor_idx[i];
158
159
cl_data->report_descr_sz[i] = mp2_ops->get_desc_sz(cl_idx, descr_size);
160
if (!cl_data->report_descr_sz[i]) {
161
rc = -EINVAL;
162
goto cleanup;
163
}
164
feature_report_size = mp2_ops->get_desc_sz(cl_idx, feature_size);
165
if (!feature_report_size) {
166
rc = -EINVAL;
167
goto cleanup;
168
}
169
input_report_size = mp2_ops->get_desc_sz(cl_idx, input_size);
170
if (!input_report_size) {
171
rc = -EINVAL;
172
goto cleanup;
173
}
174
cl_data->feature_report[i] = devm_kzalloc(dev, feature_report_size, GFP_KERNEL);
175
if (!cl_data->feature_report[i]) {
176
rc = -ENOMEM;
177
goto cleanup;
178
}
179
in_data->input_report[i] = devm_kzalloc(dev, input_report_size, GFP_KERNEL);
180
if (!in_data->input_report[i]) {
181
rc = -ENOMEM;
182
goto cleanup;
183
}
184
185
info.sensor_idx = cl_idx;
186
187
cl_data->report_descr[i] =
188
devm_kzalloc(dev, cl_data->report_descr_sz[i], GFP_KERNEL);
189
if (!cl_data->report_descr[i]) {
190
rc = -ENOMEM;
191
goto cleanup;
192
}
193
rc = mp2_ops->get_rep_desc(cl_idx, cl_data->report_descr[i]);
194
if (rc)
195
goto cleanup;
196
197
mp2_ops->stop(privdata, cl_data->sensor_idx[i]);
198
amd_sfh_wait_for_response(privdata, cl_data->sensor_idx[i], DISABLE_SENSOR);
199
writel(0, privdata->mmio + amd_get_p2c_val(privdata, 0));
200
mp2_ops->start(privdata, info);
201
status = amd_sfh_wait_for_response
202
(privdata, cl_data->sensor_idx[i], ENABLE_SENSOR);
203
204
cl_data->sensor_sts[i] = (status == 0) ? SENSOR_ENABLED : SENSOR_DISABLED;
205
}
206
207
for (i = 0; i < cl_data->num_hid_devices; i++) {
208
if (cl_data->sensor_idx[i] == SRA_IDX)
209
continue;
210
cl_data->cur_hid_dev = i;
211
if (cl_data->sensor_sts[i] == SENSOR_ENABLED) {
212
cl_data->is_any_sensor_enabled = true;
213
rc = amdtp_hid_probe(i, cl_data);
214
if (rc)
215
goto cleanup;
216
switch (cl_data->sensor_idx[i]) {
217
case HPD_IDX:
218
privdata->dev_en.is_hpd_present = true;
219
privdata->dev_en.is_hpd_enabled = true;
220
amd_sfh_toggle_hpd(privdata, false);
221
break;
222
case ALS_IDX:
223
privdata->dev_en.is_als_present = true;
224
break;
225
}
226
}
227
dev_dbg(dev, "sid 0x%x (%s) status 0x%x\n",
228
cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
229
cl_data->sensor_sts[i]);
230
}
231
232
if (!cl_data->is_any_sensor_enabled) {
233
dev_warn(dev, "No sensor registered, sensors not enabled is %d\n",
234
cl_data->is_any_sensor_enabled);
235
rc = -EOPNOTSUPP;
236
goto cleanup;
237
}
238
239
schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
240
return 0;
241
242
cleanup:
243
amd_sfh_hid_client_deinit(privdata);
244
for (i = 0; i < cl_data->num_hid_devices; i++) {
245
if (cl_data->sensor_idx[i] == SRA_IDX)
246
continue;
247
devm_kfree(dev, cl_data->feature_report[i]);
248
devm_kfree(dev, in_data->input_report[i]);
249
devm_kfree(dev, cl_data->report_descr[i]);
250
}
251
return rc;
252
}
253
254
static void amd_sfh_resume(struct amd_mp2_dev *mp2)
255
{
256
struct amdtp_cl_data *cl_data = mp2->cl_data;
257
struct amd_mp2_sensor_info info;
258
int i, status;
259
260
if (!cl_data->is_any_sensor_enabled) {
261
amd_sfh_clear_intr(mp2);
262
return;
263
}
264
265
for (i = 0; i < cl_data->num_hid_devices; i++) {
266
/* leave HPD alone; policy is controlled by sysfs */
267
if (cl_data->sensor_idx[i] == HPD_IDX)
268
continue;
269
270
if (cl_data->sensor_sts[i] == SENSOR_DISABLED) {
271
info.sensor_idx = cl_data->sensor_idx[i];
272
mp2->mp2_ops->start(mp2, info);
273
status = amd_sfh_wait_for_response
274
(mp2, cl_data->sensor_idx[i], ENABLE_SENSOR);
275
if (status == 0)
276
status = SENSOR_ENABLED;
277
if (status == SENSOR_ENABLED)
278
cl_data->sensor_sts[i] = SENSOR_ENABLED;
279
dev_dbg(&mp2->pdev->dev, "resume sid 0x%x (%s) status 0x%x\n",
280
cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
281
cl_data->sensor_sts[i]);
282
}
283
}
284
285
schedule_delayed_work(&cl_data->work_buffer, msecs_to_jiffies(AMD_SFH_IDLE_LOOP));
286
amd_sfh_clear_intr(mp2);
287
}
288
289
static void amd_sfh_suspend(struct amd_mp2_dev *mp2)
290
{
291
struct amdtp_cl_data *cl_data = mp2->cl_data;
292
int i, status;
293
294
if (!cl_data->is_any_sensor_enabled) {
295
amd_sfh_clear_intr(mp2);
296
return;
297
}
298
299
for (i = 0; i < cl_data->num_hid_devices; i++) {
300
/* leave HPD alone; policy is controlled by sysfs */
301
if (cl_data->sensor_idx[i] == HPD_IDX)
302
continue;
303
if (cl_data->sensor_sts[i] == SENSOR_ENABLED) {
304
mp2->mp2_ops->stop(mp2, cl_data->sensor_idx[i]);
305
status = amd_sfh_wait_for_response
306
(mp2, cl_data->sensor_idx[i], DISABLE_SENSOR);
307
if (status == 0)
308
status = SENSOR_DISABLED;
309
if (status != SENSOR_ENABLED)
310
cl_data->sensor_sts[i] = SENSOR_DISABLED;
311
dev_dbg(&mp2->pdev->dev, "suspend sid 0x%x (%s) status 0x%x\n",
312
cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
313
cl_data->sensor_sts[i]);
314
}
315
}
316
317
cancel_delayed_work_sync(&cl_data->work_buffer);
318
amd_sfh_clear_intr(mp2);
319
}
320
321
void amd_sfh_toggle_hpd(struct amd_mp2_dev *mp2, bool enabled)
322
{
323
struct amdtp_cl_data *cl_data = mp2->cl_data;
324
struct amd_mp2_sensor_info info;
325
int i, status;
326
327
if (mp2->dev_en.is_hpd_enabled == enabled)
328
return;
329
330
for (i = 0; i < cl_data->num_hid_devices; i++) {
331
if (cl_data->sensor_idx[i] != HPD_IDX)
332
continue;
333
info.sensor_idx = cl_data->sensor_idx[i];
334
if (enabled) {
335
mp2->mp2_ops->start(mp2, info);
336
status = amd_sfh_wait_for_response
337
(mp2, cl_data->sensor_idx[i], ENABLE_SENSOR);
338
if (status == 0)
339
status = SENSOR_ENABLED;
340
if (status == SENSOR_ENABLED)
341
cl_data->sensor_sts[i] = SENSOR_ENABLED;
342
} else {
343
mp2->mp2_ops->stop(mp2, cl_data->sensor_idx[i]);
344
status = amd_sfh_wait_for_response
345
(mp2, cl_data->sensor_idx[i], DISABLE_SENSOR);
346
if (status == 0)
347
status = SENSOR_DISABLED;
348
if (status != SENSOR_ENABLED)
349
cl_data->sensor_sts[i] = SENSOR_DISABLED;
350
}
351
dev_dbg(&mp2->pdev->dev, "toggle sid 0x%x (%s) status 0x%x\n",
352
cl_data->sensor_idx[i], get_sensor_name(cl_data->sensor_idx[i]),
353
cl_data->sensor_sts[i]);
354
break;
355
}
356
mp2->dev_en.is_hpd_enabled = enabled;
357
}
358
359
static void amd_mp2_pci_remove(void *privdata)
360
{
361
struct amd_mp2_dev *mp2 = privdata;
362
363
sfh_deinit_emp2();
364
amd_sfh_hid_client_deinit(privdata);
365
mp2->mp2_ops->stop_all(mp2);
366
pcim_intx(mp2->pdev, false);
367
amd_sfh_clear_intr(mp2);
368
}
369
370
static void amd_sfh_set_ops(struct amd_mp2_dev *mp2)
371
{
372
struct amd_mp2_ops *mp2_ops;
373
374
sfh_interface_init(mp2);
375
mp2_ops = mp2->mp2_ops;
376
mp2_ops->clear_intr = amd_sfh_clear_intr_v2;
377
mp2_ops->init_intr = amd_sfh_irq_init_v2;
378
mp2_ops->suspend = amd_sfh_suspend;
379
mp2_ops->resume = amd_sfh_resume;
380
mp2_ops->remove = amd_mp2_pci_remove;
381
}
382
383
int amd_sfh1_1_init(struct amd_mp2_dev *mp2)
384
{
385
u32 phy_base = readl(mp2->mmio + amd_get_c2p_val(mp2, 22));
386
struct device *dev = &mp2->pdev->dev;
387
struct sfh_base_info binfo;
388
int rc;
389
390
phy_base <<= 21;
391
if (!devm_request_mem_region(dev, phy_base, 128 * 1024, "amd_sfh")) {
392
dev_dbg(dev, "can't reserve mmio registers\n");
393
return -ENOMEM;
394
}
395
396
mp2->vsbase = devm_ioremap(dev, phy_base, 128 * 1024);
397
if (!mp2->vsbase) {
398
dev_dbg(dev, "failed to remap vsbase\n");
399
return -ENOMEM;
400
}
401
402
/* Before accessing give time for SFH firmware for processing configuration */
403
msleep(5000);
404
405
memcpy_fromio(&binfo, mp2->vsbase, sizeof(struct sfh_base_info));
406
if (binfo.sbase.fw_info.fw_ver == 0 || binfo.sbase.s_list.sl.sensors == 0) {
407
dev_dbg(dev, "No sensor registered\n");
408
return -EOPNOTSUPP;
409
}
410
dev_dbg(dev, "firmware version 0x%x\n", binfo.sbase.fw_info.fw_ver);
411
412
amd_sfh_set_ops(mp2);
413
414
rc = amd_sfh_irq_init(mp2);
415
if (rc) {
416
sfh_deinit_emp2();
417
dev_err(dev, "amd_sfh_irq_init failed\n");
418
return rc;
419
}
420
421
rc = amd_sfh1_1_hid_client_init(mp2);
422
if (rc) {
423
sfh_deinit_emp2();
424
if ((rc != -ENODEV) && (rc != -EOPNOTSUPP))
425
dev_err(dev, "amd_sfh1_1_hid_client_init failed\n");
426
return rc;
427
}
428
429
return rc;
430
}
431
432