Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/athk/ath12k/mhi.c
48378 views
1
// SPDX-License-Identifier: BSD-3-Clause-Clear
2
/*
3
* Copyright (c) 2020-2021 The Linux Foundation. All rights reserved.
4
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
5
*/
6
7
#include <linux/msi.h>
8
#include <linux/pci.h>
9
#if defined(__FreeBSD__)
10
#include <linux/delay.h>
11
#endif
12
13
#include "core.h"
14
#include "debug.h"
15
#include "mhi.h"
16
#include "pci.h"
17
18
#define MHI_TIMEOUT_DEFAULT_MS 90000
19
20
static const struct mhi_channel_config ath12k_mhi_channels_qcn9274[] = {
21
{
22
.num = 0,
23
.name = "LOOPBACK",
24
.num_elements = 32,
25
.event_ring = 1,
26
.dir = DMA_TO_DEVICE,
27
.ee_mask = 0x4,
28
.pollcfg = 0,
29
.doorbell = MHI_DB_BRST_DISABLE,
30
.lpm_notify = false,
31
.offload_channel = false,
32
.doorbell_mode_switch = false,
33
.auto_queue = false,
34
},
35
{
36
.num = 1,
37
.name = "LOOPBACK",
38
.num_elements = 32,
39
.event_ring = 1,
40
.dir = DMA_FROM_DEVICE,
41
.ee_mask = 0x4,
42
.pollcfg = 0,
43
.doorbell = MHI_DB_BRST_DISABLE,
44
.lpm_notify = false,
45
.offload_channel = false,
46
.doorbell_mode_switch = false,
47
.auto_queue = false,
48
},
49
{
50
.num = 20,
51
.name = "IPCR",
52
.num_elements = 32,
53
.event_ring = 1,
54
.dir = DMA_TO_DEVICE,
55
.ee_mask = 0x4,
56
.pollcfg = 0,
57
.doorbell = MHI_DB_BRST_DISABLE,
58
.lpm_notify = false,
59
.offload_channel = false,
60
.doorbell_mode_switch = false,
61
.auto_queue = false,
62
},
63
{
64
.num = 21,
65
.name = "IPCR",
66
.num_elements = 32,
67
.event_ring = 1,
68
.dir = DMA_FROM_DEVICE,
69
.ee_mask = 0x4,
70
.pollcfg = 0,
71
.doorbell = MHI_DB_BRST_DISABLE,
72
.lpm_notify = false,
73
.offload_channel = false,
74
.doorbell_mode_switch = false,
75
.auto_queue = true,
76
},
77
};
78
79
static struct mhi_event_config ath12k_mhi_events_qcn9274[] = {
80
{
81
.num_elements = 32,
82
.irq_moderation_ms = 0,
83
.irq = 1,
84
.data_type = MHI_ER_CTRL,
85
.mode = MHI_DB_BRST_DISABLE,
86
.hardware_event = false,
87
.client_managed = false,
88
.offload_channel = false,
89
},
90
{
91
.num_elements = 256,
92
.irq_moderation_ms = 1,
93
.irq = 2,
94
.mode = MHI_DB_BRST_DISABLE,
95
.priority = 1,
96
.hardware_event = false,
97
.client_managed = false,
98
.offload_channel = false,
99
},
100
};
101
102
const struct mhi_controller_config ath12k_mhi_config_qcn9274 = {
103
.max_channels = 30,
104
.timeout_ms = 10000,
105
.use_bounce_buf = false,
106
.buf_len = 0,
107
.num_channels = ARRAY_SIZE(ath12k_mhi_channels_qcn9274),
108
.ch_cfg = ath12k_mhi_channels_qcn9274,
109
.num_events = ARRAY_SIZE(ath12k_mhi_events_qcn9274),
110
.event_cfg = ath12k_mhi_events_qcn9274,
111
};
112
113
static const struct mhi_channel_config ath12k_mhi_channels_wcn7850[] = {
114
{
115
.num = 0,
116
.name = "LOOPBACK",
117
.num_elements = 32,
118
.event_ring = 0,
119
.dir = DMA_TO_DEVICE,
120
.ee_mask = 0x4,
121
.pollcfg = 0,
122
.doorbell = MHI_DB_BRST_DISABLE,
123
.lpm_notify = false,
124
.offload_channel = false,
125
.doorbell_mode_switch = false,
126
.auto_queue = false,
127
},
128
{
129
.num = 1,
130
.name = "LOOPBACK",
131
.num_elements = 32,
132
.event_ring = 0,
133
.dir = DMA_FROM_DEVICE,
134
.ee_mask = 0x4,
135
.pollcfg = 0,
136
.doorbell = MHI_DB_BRST_DISABLE,
137
.lpm_notify = false,
138
.offload_channel = false,
139
.doorbell_mode_switch = false,
140
.auto_queue = false,
141
},
142
{
143
.num = 20,
144
.name = "IPCR",
145
.num_elements = 64,
146
.event_ring = 1,
147
.dir = DMA_TO_DEVICE,
148
.ee_mask = 0x4,
149
.pollcfg = 0,
150
.doorbell = MHI_DB_BRST_DISABLE,
151
.lpm_notify = false,
152
.offload_channel = false,
153
.doorbell_mode_switch = false,
154
.auto_queue = false,
155
},
156
{
157
.num = 21,
158
.name = "IPCR",
159
.num_elements = 64,
160
.event_ring = 1,
161
.dir = DMA_FROM_DEVICE,
162
.ee_mask = 0x4,
163
.pollcfg = 0,
164
.doorbell = MHI_DB_BRST_DISABLE,
165
.lpm_notify = false,
166
.offload_channel = false,
167
.doorbell_mode_switch = false,
168
.auto_queue = true,
169
},
170
};
171
172
static struct mhi_event_config ath12k_mhi_events_wcn7850[] = {
173
{
174
.num_elements = 32,
175
.irq_moderation_ms = 0,
176
.irq = 1,
177
.mode = MHI_DB_BRST_DISABLE,
178
.data_type = MHI_ER_CTRL,
179
.hardware_event = false,
180
.client_managed = false,
181
.offload_channel = false,
182
},
183
{
184
.num_elements = 256,
185
.irq_moderation_ms = 1,
186
.irq = 2,
187
.mode = MHI_DB_BRST_DISABLE,
188
.priority = 1,
189
.hardware_event = false,
190
.client_managed = false,
191
.offload_channel = false,
192
},
193
};
194
195
const struct mhi_controller_config ath12k_mhi_config_wcn7850 = {
196
.max_channels = 128,
197
.timeout_ms = 2000,
198
.use_bounce_buf = false,
199
.buf_len = 0,
200
.num_channels = ARRAY_SIZE(ath12k_mhi_channels_wcn7850),
201
.ch_cfg = ath12k_mhi_channels_wcn7850,
202
.num_events = ARRAY_SIZE(ath12k_mhi_events_wcn7850),
203
.event_cfg = ath12k_mhi_events_wcn7850,
204
};
205
206
void ath12k_mhi_set_mhictrl_reset(struct ath12k_base *ab)
207
{
208
u32 val;
209
210
val = ath12k_pci_read32(ab, MHISTATUS);
211
212
ath12k_dbg(ab, ATH12K_DBG_PCI, "MHISTATUS 0x%x\n", val);
213
214
/* Observed on some targets that after SOC_GLOBAL_RESET, MHISTATUS
215
* has SYSERR bit set and thus need to set MHICTRL_RESET
216
* to clear SYSERR.
217
*/
218
ath12k_pci_write32(ab, MHICTRL, MHICTRL_RESET_MASK);
219
220
mdelay(10);
221
}
222
223
static void ath12k_mhi_reset_txvecdb(struct ath12k_base *ab)
224
{
225
ath12k_pci_write32(ab, PCIE_TXVECDB, 0);
226
}
227
228
static void ath12k_mhi_reset_txvecstatus(struct ath12k_base *ab)
229
{
230
ath12k_pci_write32(ab, PCIE_TXVECSTATUS, 0);
231
}
232
233
static void ath12k_mhi_reset_rxvecdb(struct ath12k_base *ab)
234
{
235
ath12k_pci_write32(ab, PCIE_RXVECDB, 0);
236
}
237
238
static void ath12k_mhi_reset_rxvecstatus(struct ath12k_base *ab)
239
{
240
ath12k_pci_write32(ab, PCIE_RXVECSTATUS, 0);
241
}
242
243
void ath12k_mhi_clear_vector(struct ath12k_base *ab)
244
{
245
ath12k_mhi_reset_txvecdb(ab);
246
ath12k_mhi_reset_txvecstatus(ab);
247
ath12k_mhi_reset_rxvecdb(ab);
248
ath12k_mhi_reset_rxvecstatus(ab);
249
}
250
251
static int ath12k_mhi_get_msi(struct ath12k_pci *ab_pci)
252
{
253
struct ath12k_base *ab = ab_pci->ab;
254
u32 user_base_data, base_vector;
255
int ret, num_vectors, i;
256
int *irq;
257
258
ret = ath12k_pci_get_user_msi_assignment(ab,
259
"MHI", &num_vectors,
260
&user_base_data, &base_vector);
261
if (ret)
262
return ret;
263
264
ath12k_dbg(ab, ATH12K_DBG_PCI, "Number of assigned MSI for MHI is %d, base vector is %d\n",
265
num_vectors, base_vector);
266
267
irq = kcalloc(num_vectors, sizeof(*irq), GFP_KERNEL);
268
if (!irq)
269
return -ENOMEM;
270
271
for (i = 0; i < num_vectors; i++)
272
irq[i] = ath12k_pci_get_msi_irq(ab->dev,
273
base_vector + i);
274
275
ab_pci->mhi_ctrl->irq = irq;
276
ab_pci->mhi_ctrl->nr_irqs = num_vectors;
277
278
return 0;
279
}
280
281
static int ath12k_mhi_op_runtime_get(struct mhi_controller *mhi_cntrl)
282
{
283
return 0;
284
}
285
286
static void ath12k_mhi_op_runtime_put(struct mhi_controller *mhi_cntrl)
287
{
288
}
289
290
static char *ath12k_mhi_op_callback_to_str(enum mhi_callback reason)
291
{
292
switch (reason) {
293
case MHI_CB_IDLE:
294
return "MHI_CB_IDLE";
295
case MHI_CB_PENDING_DATA:
296
return "MHI_CB_PENDING_DATA";
297
case MHI_CB_LPM_ENTER:
298
return "MHI_CB_LPM_ENTER";
299
case MHI_CB_LPM_EXIT:
300
return "MHI_CB_LPM_EXIT";
301
case MHI_CB_EE_RDDM:
302
return "MHI_CB_EE_RDDM";
303
case MHI_CB_EE_MISSION_MODE:
304
return "MHI_CB_EE_MISSION_MODE";
305
case MHI_CB_SYS_ERROR:
306
return "MHI_CB_SYS_ERROR";
307
case MHI_CB_FATAL_ERROR:
308
return "MHI_CB_FATAL_ERROR";
309
case MHI_CB_BW_REQ:
310
return "MHI_CB_BW_REQ";
311
default:
312
return "UNKNOWN";
313
}
314
}
315
316
static void ath12k_mhi_op_status_cb(struct mhi_controller *mhi_cntrl,
317
enum mhi_callback cb)
318
{
319
struct ath12k_base *ab = dev_get_drvdata(mhi_cntrl->cntrl_dev);
320
321
ath12k_dbg(ab, ATH12K_DBG_BOOT, "mhi notify status reason %s\n",
322
ath12k_mhi_op_callback_to_str(cb));
323
324
switch (cb) {
325
case MHI_CB_SYS_ERROR:
326
ath12k_warn(ab, "firmware crashed: MHI_CB_SYS_ERROR\n");
327
break;
328
case MHI_CB_EE_RDDM:
329
if (!(test_bit(ATH12K_FLAG_UNREGISTERING, &ab->dev_flags)))
330
queue_work(ab->workqueue_aux, &ab->reset_work);
331
break;
332
default:
333
break;
334
}
335
}
336
337
static int ath12k_mhi_op_read_reg(struct mhi_controller *mhi_cntrl,
338
void __iomem *addr,
339
u32 *out)
340
{
341
*out = readl(addr);
342
343
return 0;
344
}
345
346
static void ath12k_mhi_op_write_reg(struct mhi_controller *mhi_cntrl,
347
void __iomem *addr,
348
u32 val)
349
{
350
writel(val, addr);
351
}
352
353
int ath12k_mhi_register(struct ath12k_pci *ab_pci)
354
{
355
struct ath12k_base *ab = ab_pci->ab;
356
struct mhi_controller *mhi_ctrl;
357
int ret;
358
359
mhi_ctrl = mhi_alloc_controller();
360
if (!mhi_ctrl)
361
return -ENOMEM;
362
363
ath12k_core_create_firmware_path(ab, ATH12K_AMSS_FILE,
364
ab_pci->amss_path,
365
sizeof(ab_pci->amss_path));
366
367
ab_pci->mhi_ctrl = mhi_ctrl;
368
mhi_ctrl->cntrl_dev = ab->dev;
369
mhi_ctrl->fw_image = ab_pci->amss_path;
370
mhi_ctrl->regs = ab->mem;
371
mhi_ctrl->reg_len = ab->mem_len;
372
373
ret = ath12k_mhi_get_msi(ab_pci);
374
if (ret) {
375
ath12k_err(ab, "failed to get msi for mhi\n");
376
mhi_free_controller(mhi_ctrl);
377
return ret;
378
}
379
380
mhi_ctrl->iova_start = 0;
381
mhi_ctrl->iova_stop = 0xffffffff;
382
mhi_ctrl->sbl_size = SZ_512K;
383
mhi_ctrl->seg_len = SZ_512K;
384
mhi_ctrl->fbc_download = true;
385
mhi_ctrl->runtime_get = ath12k_mhi_op_runtime_get;
386
mhi_ctrl->runtime_put = ath12k_mhi_op_runtime_put;
387
mhi_ctrl->status_cb = ath12k_mhi_op_status_cb;
388
mhi_ctrl->read_reg = ath12k_mhi_op_read_reg;
389
mhi_ctrl->write_reg = ath12k_mhi_op_write_reg;
390
391
ret = mhi_register_controller(mhi_ctrl, ab->hw_params->mhi_config);
392
if (ret) {
393
ath12k_err(ab, "failed to register to mhi bus, err = %d\n", ret);
394
mhi_free_controller(mhi_ctrl);
395
return ret;
396
}
397
398
return 0;
399
}
400
401
void ath12k_mhi_unregister(struct ath12k_pci *ab_pci)
402
{
403
struct mhi_controller *mhi_ctrl = ab_pci->mhi_ctrl;
404
405
mhi_unregister_controller(mhi_ctrl);
406
kfree(mhi_ctrl->irq);
407
mhi_free_controller(mhi_ctrl);
408
ab_pci->mhi_ctrl = NULL;
409
}
410
411
static char *ath12k_mhi_state_to_str(enum ath12k_mhi_state mhi_state)
412
{
413
switch (mhi_state) {
414
case ATH12K_MHI_INIT:
415
return "INIT";
416
case ATH12K_MHI_DEINIT:
417
return "DEINIT";
418
case ATH12K_MHI_POWER_ON:
419
return "POWER_ON";
420
case ATH12K_MHI_POWER_OFF:
421
return "POWER_OFF";
422
case ATH12K_MHI_FORCE_POWER_OFF:
423
return "FORCE_POWER_OFF";
424
case ATH12K_MHI_SUSPEND:
425
return "SUSPEND";
426
case ATH12K_MHI_RESUME:
427
return "RESUME";
428
case ATH12K_MHI_TRIGGER_RDDM:
429
return "TRIGGER_RDDM";
430
case ATH12K_MHI_RDDM_DONE:
431
return "RDDM_DONE";
432
default:
433
return "UNKNOWN";
434
}
435
};
436
437
static void ath12k_mhi_set_state_bit(struct ath12k_pci *ab_pci,
438
enum ath12k_mhi_state mhi_state)
439
{
440
struct ath12k_base *ab = ab_pci->ab;
441
442
switch (mhi_state) {
443
case ATH12K_MHI_INIT:
444
set_bit(ATH12K_MHI_INIT, &ab_pci->mhi_state);
445
break;
446
case ATH12K_MHI_DEINIT:
447
clear_bit(ATH12K_MHI_INIT, &ab_pci->mhi_state);
448
break;
449
case ATH12K_MHI_POWER_ON:
450
set_bit(ATH12K_MHI_POWER_ON, &ab_pci->mhi_state);
451
break;
452
case ATH12K_MHI_POWER_OFF:
453
case ATH12K_MHI_FORCE_POWER_OFF:
454
clear_bit(ATH12K_MHI_POWER_ON, &ab_pci->mhi_state);
455
clear_bit(ATH12K_MHI_TRIGGER_RDDM, &ab_pci->mhi_state);
456
clear_bit(ATH12K_MHI_RDDM_DONE, &ab_pci->mhi_state);
457
break;
458
case ATH12K_MHI_SUSPEND:
459
set_bit(ATH12K_MHI_SUSPEND, &ab_pci->mhi_state);
460
break;
461
case ATH12K_MHI_RESUME:
462
clear_bit(ATH12K_MHI_SUSPEND, &ab_pci->mhi_state);
463
break;
464
case ATH12K_MHI_TRIGGER_RDDM:
465
set_bit(ATH12K_MHI_TRIGGER_RDDM, &ab_pci->mhi_state);
466
break;
467
case ATH12K_MHI_RDDM_DONE:
468
set_bit(ATH12K_MHI_RDDM_DONE, &ab_pci->mhi_state);
469
break;
470
default:
471
ath12k_err(ab, "unhandled mhi state (%d)\n", mhi_state);
472
}
473
}
474
475
static int ath12k_mhi_check_state_bit(struct ath12k_pci *ab_pci,
476
enum ath12k_mhi_state mhi_state)
477
{
478
struct ath12k_base *ab = ab_pci->ab;
479
480
switch (mhi_state) {
481
case ATH12K_MHI_INIT:
482
if (!test_bit(ATH12K_MHI_INIT, &ab_pci->mhi_state))
483
return 0;
484
break;
485
case ATH12K_MHI_DEINIT:
486
case ATH12K_MHI_POWER_ON:
487
if (test_bit(ATH12K_MHI_INIT, &ab_pci->mhi_state) &&
488
!test_bit(ATH12K_MHI_POWER_ON, &ab_pci->mhi_state))
489
return 0;
490
break;
491
case ATH12K_MHI_FORCE_POWER_OFF:
492
if (test_bit(ATH12K_MHI_POWER_ON, &ab_pci->mhi_state))
493
return 0;
494
break;
495
case ATH12K_MHI_POWER_OFF:
496
case ATH12K_MHI_SUSPEND:
497
if (test_bit(ATH12K_MHI_POWER_ON, &ab_pci->mhi_state) &&
498
!test_bit(ATH12K_MHI_SUSPEND, &ab_pci->mhi_state))
499
return 0;
500
break;
501
case ATH12K_MHI_RESUME:
502
if (test_bit(ATH12K_MHI_SUSPEND, &ab_pci->mhi_state))
503
return 0;
504
break;
505
case ATH12K_MHI_TRIGGER_RDDM:
506
if (test_bit(ATH12K_MHI_POWER_ON, &ab_pci->mhi_state) &&
507
!test_bit(ATH12K_MHI_TRIGGER_RDDM, &ab_pci->mhi_state))
508
return 0;
509
break;
510
case ATH12K_MHI_RDDM_DONE:
511
return 0;
512
default:
513
ath12k_err(ab, "unhandled mhi state: %s(%d)\n",
514
ath12k_mhi_state_to_str(mhi_state), mhi_state);
515
}
516
517
ath12k_err(ab, "failed to set mhi state %s(%d) in current mhi state (0x%lx)\n",
518
ath12k_mhi_state_to_str(mhi_state), mhi_state,
519
ab_pci->mhi_state);
520
521
return -EINVAL;
522
}
523
524
static int ath12k_mhi_set_state(struct ath12k_pci *ab_pci,
525
enum ath12k_mhi_state mhi_state)
526
{
527
struct ath12k_base *ab = ab_pci->ab;
528
int ret;
529
530
ret = ath12k_mhi_check_state_bit(ab_pci, mhi_state);
531
if (ret)
532
goto out;
533
534
ath12k_dbg(ab, ATH12K_DBG_PCI, "setting mhi state: %s(%d)\n",
535
ath12k_mhi_state_to_str(mhi_state), mhi_state);
536
537
switch (mhi_state) {
538
case ATH12K_MHI_INIT:
539
ret = mhi_prepare_for_power_up(ab_pci->mhi_ctrl);
540
break;
541
case ATH12K_MHI_DEINIT:
542
mhi_unprepare_after_power_down(ab_pci->mhi_ctrl);
543
ret = 0;
544
break;
545
case ATH12K_MHI_POWER_ON:
546
ret = mhi_async_power_up(ab_pci->mhi_ctrl);
547
break;
548
case ATH12K_MHI_POWER_OFF:
549
mhi_power_down(ab_pci->mhi_ctrl, true);
550
ret = 0;
551
break;
552
case ATH12K_MHI_FORCE_POWER_OFF:
553
mhi_power_down(ab_pci->mhi_ctrl, false);
554
ret = 0;
555
break;
556
case ATH12K_MHI_SUSPEND:
557
ret = mhi_pm_suspend(ab_pci->mhi_ctrl);
558
break;
559
case ATH12K_MHI_RESUME:
560
ret = mhi_pm_resume(ab_pci->mhi_ctrl);
561
break;
562
case ATH12K_MHI_TRIGGER_RDDM:
563
ret = mhi_force_rddm_mode(ab_pci->mhi_ctrl);
564
break;
565
case ATH12K_MHI_RDDM_DONE:
566
break;
567
default:
568
ath12k_err(ab, "unhandled MHI state (%d)\n", mhi_state);
569
ret = -EINVAL;
570
}
571
572
if (ret)
573
goto out;
574
575
ath12k_mhi_set_state_bit(ab_pci, mhi_state);
576
577
return 0;
578
579
out:
580
ath12k_err(ab, "failed to set mhi state: %s(%d)\n",
581
ath12k_mhi_state_to_str(mhi_state), mhi_state);
582
return ret;
583
}
584
585
int ath12k_mhi_start(struct ath12k_pci *ab_pci)
586
{
587
int ret;
588
589
ab_pci->mhi_ctrl->timeout_ms = MHI_TIMEOUT_DEFAULT_MS;
590
591
ret = ath12k_mhi_set_state(ab_pci, ATH12K_MHI_INIT);
592
if (ret)
593
goto out;
594
595
ret = ath12k_mhi_set_state(ab_pci, ATH12K_MHI_POWER_ON);
596
if (ret)
597
goto out;
598
599
return 0;
600
601
out:
602
return ret;
603
}
604
605
void ath12k_mhi_stop(struct ath12k_pci *ab_pci)
606
{
607
ath12k_mhi_set_state(ab_pci, ATH12K_MHI_POWER_OFF);
608
ath12k_mhi_set_state(ab_pci, ATH12K_MHI_DEINIT);
609
}
610
611
void ath12k_mhi_suspend(struct ath12k_pci *ab_pci)
612
{
613
ath12k_mhi_set_state(ab_pci, ATH12K_MHI_SUSPEND);
614
}
615
616
void ath12k_mhi_resume(struct ath12k_pci *ab_pci)
617
{
618
ath12k_mhi_set_state(ab_pci, ATH12K_MHI_RESUME);
619
}
620
621