1 // SPDX-License-Identifier: GPL-2.0-only
2
3 /* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */
4 /* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. */
5
6 #include <linux/delay.h>
7 #include <linux/err.h>
8 #include <linux/memblock.h>
9 #include <linux/mhi.h>
10 #include <linux/moduleparam.h>
11 #include <linux/pci.h>
12 #include <linux/sizes.h>
13
14 #include "mhi_controller.h"
15 #include "qaic.h"
16
17 #define MAX_RESET_TIME_SEC 25
18
19 static unsigned int mhi_timeout_ms = 2000; /* 2 sec default */
20 module_param(mhi_timeout_ms, uint, 0600);
21 MODULE_PARM_DESC(mhi_timeout_ms, "MHI controller timeout value");
22
23 static const char *fw_image_paths[FAMILY_MAX] = {
24 [FAMILY_AIC100] = "qcom/aic100/sbl.bin",
25 [FAMILY_AIC200] = "qcom/aic200/sbl.bin",
26 };
27
28 static const struct mhi_channel_config aic100_channels[] = {
29 {
30 .name = "QAIC_LOOPBACK",
31 .num = 0,
32 .num_elements = 32,
33 .local_elements = 0,
34 .event_ring = 0,
35 .dir = DMA_TO_DEVICE,
36 .ee_mask = MHI_CH_EE_AMSS,
37 .pollcfg = 0,
38 .doorbell = MHI_DB_BRST_DISABLE,
39 .lpm_notify = false,
40 .offload_channel = false,
41 .doorbell_mode_switch = false,
42 .wake_capable = false,
43 },
44 {
45 .name = "QAIC_LOOPBACK",
46 .num = 1,
47 .num_elements = 32,
48 .local_elements = 0,
49 .event_ring = 0,
50 .dir = DMA_FROM_DEVICE,
51 .ee_mask = MHI_CH_EE_AMSS,
52 .pollcfg = 0,
53 .doorbell = MHI_DB_BRST_DISABLE,
54 .lpm_notify = false,
55 .offload_channel = false,
56 .doorbell_mode_switch = false,
57 .wake_capable = false,
58 },
59 {
60 .name = "QAIC_SAHARA",
61 .num = 2,
62 .num_elements = 32,
63 .local_elements = 0,
64 .event_ring = 0,
65 .dir = DMA_TO_DEVICE,
66 .ee_mask = MHI_CH_EE_SBL,
67 .pollcfg = 0,
68 .doorbell = MHI_DB_BRST_DISABLE,
69 .lpm_notify = false,
70 .offload_channel = false,
71 .doorbell_mode_switch = false,
72 .wake_capable = false,
73 },
74 {
75 .name = "QAIC_SAHARA",
76 .num = 3,
77 .num_elements = 32,
78 .local_elements = 0,
79 .event_ring = 0,
80 .dir = DMA_FROM_DEVICE,
81 .ee_mask = MHI_CH_EE_SBL,
82 .pollcfg = 0,
83 .doorbell = MHI_DB_BRST_DISABLE,
84 .lpm_notify = false,
85 .offload_channel = false,
86 .doorbell_mode_switch = false,
87 .wake_capable = false,
88 },
89 {
90 .name = "QAIC_DIAG",
91 .num = 4,
92 .num_elements = 32,
93 .local_elements = 0,
94 .event_ring = 0,
95 .dir = DMA_TO_DEVICE,
96 .ee_mask = MHI_CH_EE_AMSS,
97 .pollcfg = 0,
98 .doorbell = MHI_DB_BRST_DISABLE,
99 .lpm_notify = false,
100 .offload_channel = false,
101 .doorbell_mode_switch = false,
102 .wake_capable = false,
103 },
104 {
105 .name = "QAIC_DIAG",
106 .num = 5,
107 .num_elements = 32,
108 .local_elements = 0,
109 .event_ring = 0,
110 .dir = DMA_FROM_DEVICE,
111 .ee_mask = MHI_CH_EE_AMSS,
112 .pollcfg = 0,
113 .doorbell = MHI_DB_BRST_DISABLE,
114 .lpm_notify = false,
115 .offload_channel = false,
116 .doorbell_mode_switch = false,
117 .wake_capable = false,
118 },
119 {
120 .name = "QAIC_SSR",
121 .num = 6,
122 .num_elements = 32,
123 .local_elements = 0,
124 .event_ring = 0,
125 .dir = DMA_TO_DEVICE,
126 .ee_mask = MHI_CH_EE_AMSS,
127 .pollcfg = 0,
128 .doorbell = MHI_DB_BRST_DISABLE,
129 .lpm_notify = false,
130 .offload_channel = false,
131 .doorbell_mode_switch = false,
132 .wake_capable = false,
133 },
134 {
135 .name = "QAIC_SSR",
136 .num = 7,
137 .num_elements = 32,
138 .local_elements = 0,
139 .event_ring = 0,
140 .dir = DMA_FROM_DEVICE,
141 .ee_mask = MHI_CH_EE_AMSS,
142 .pollcfg = 0,
143 .doorbell = MHI_DB_BRST_DISABLE,
144 .lpm_notify = false,
145 .offload_channel = false,
146 .doorbell_mode_switch = false,
147 .wake_capable = false,
148 },
149 {
150 .name = "QAIC_QDSS",
151 .num = 8,
152 .num_elements = 32,
153 .local_elements = 0,
154 .event_ring = 0,
155 .dir = DMA_TO_DEVICE,
156 .ee_mask = MHI_CH_EE_AMSS,
157 .pollcfg = 0,
158 .doorbell = MHI_DB_BRST_DISABLE,
159 .lpm_notify = false,
160 .offload_channel = false,
161 .doorbell_mode_switch = false,
162 .wake_capable = false,
163 },
164 {
165 .name = "QAIC_QDSS",
166 .num = 9,
167 .num_elements = 32,
168 .local_elements = 0,
169 .event_ring = 0,
170 .dir = DMA_FROM_DEVICE,
171 .ee_mask = MHI_CH_EE_AMSS,
172 .pollcfg = 0,
173 .doorbell = MHI_DB_BRST_DISABLE,
174 .lpm_notify = false,
175 .offload_channel = false,
176 .doorbell_mode_switch = false,
177 .wake_capable = false,
178 },
179 {
180 .name = "QAIC_CONTROL",
181 .num = 10,
182 .num_elements = 128,
183 .local_elements = 0,
184 .event_ring = 0,
185 .dir = DMA_TO_DEVICE,
186 .ee_mask = MHI_CH_EE_AMSS,
187 .pollcfg = 0,
188 .doorbell = MHI_DB_BRST_DISABLE,
189 .lpm_notify = false,
190 .offload_channel = false,
191 .doorbell_mode_switch = false,
192 .wake_capable = false,
193 },
194 {
195 .name = "QAIC_CONTROL",
196 .num = 11,
197 .num_elements = 128,
198 .local_elements = 0,
199 .event_ring = 0,
200 .dir = DMA_FROM_DEVICE,
201 .ee_mask = MHI_CH_EE_AMSS,
202 .pollcfg = 0,
203 .doorbell = MHI_DB_BRST_DISABLE,
204 .lpm_notify = false,
205 .offload_channel = false,
206 .doorbell_mode_switch = false,
207 .wake_capable = false,
208 },
209 {
210 .name = "QAIC_LOGGING",
211 .num = 12,
212 .num_elements = 32,
213 .local_elements = 0,
214 .event_ring = 0,
215 .dir = DMA_TO_DEVICE,
216 .ee_mask = MHI_CH_EE_SBL,
217 .pollcfg = 0,
218 .doorbell = MHI_DB_BRST_DISABLE,
219 .lpm_notify = false,
220 .offload_channel = false,
221 .doorbell_mode_switch = false,
222 .wake_capable = false,
223 },
224 {
225 .name = "QAIC_LOGGING",
226 .num = 13,
227 .num_elements = 32,
228 .local_elements = 0,
229 .event_ring = 0,
230 .dir = DMA_FROM_DEVICE,
231 .ee_mask = MHI_CH_EE_SBL,
232 .pollcfg = 0,
233 .doorbell = MHI_DB_BRST_DISABLE,
234 .lpm_notify = false,
235 .offload_channel = false,
236 .doorbell_mode_switch = false,
237 .wake_capable = false,
238 },
239 {
240 .name = "QAIC_STATUS",
241 .num = 14,
242 .num_elements = 32,
243 .local_elements = 0,
244 .event_ring = 0,
245 .dir = DMA_TO_DEVICE,
246 .ee_mask = MHI_CH_EE_AMSS,
247 .pollcfg = 0,
248 .doorbell = MHI_DB_BRST_DISABLE,
249 .lpm_notify = false,
250 .offload_channel = false,
251 .doorbell_mode_switch = false,
252 .wake_capable = false,
253 },
254 {
255 .name = "QAIC_STATUS",
256 .num = 15,
257 .num_elements = 32,
258 .local_elements = 0,
259 .event_ring = 0,
260 .dir = DMA_FROM_DEVICE,
261 .ee_mask = MHI_CH_EE_AMSS,
262 .pollcfg = 0,
263 .doorbell = MHI_DB_BRST_DISABLE,
264 .lpm_notify = false,
265 .offload_channel = false,
266 .doorbell_mode_switch = false,
267 .wake_capable = false,
268 },
269 {
270 .name = "QAIC_TELEMETRY",
271 .num = 16,
272 .num_elements = 32,
273 .local_elements = 0,
274 .event_ring = 0,
275 .dir = DMA_TO_DEVICE,
276 .ee_mask = MHI_CH_EE_AMSS,
277 .pollcfg = 0,
278 .doorbell = MHI_DB_BRST_DISABLE,
279 .lpm_notify = false,
280 .offload_channel = false,
281 .doorbell_mode_switch = false,
282 .wake_capable = false,
283 },
284 {
285 .name = "QAIC_TELEMETRY",
286 .num = 17,
287 .num_elements = 32,
288 .local_elements = 0,
289 .event_ring = 0,
290 .dir = DMA_FROM_DEVICE,
291 .ee_mask = MHI_CH_EE_AMSS,
292 .pollcfg = 0,
293 .doorbell = MHI_DB_BRST_DISABLE,
294 .lpm_notify = false,
295 .offload_channel = false,
296 .doorbell_mode_switch = false,
297 .wake_capable = false,
298 },
299 {
300 .name = "QAIC_DEBUG",
301 .num = 18,
302 .num_elements = 32,
303 .local_elements = 0,
304 .event_ring = 0,
305 .dir = DMA_TO_DEVICE,
306 .ee_mask = MHI_CH_EE_AMSS,
307 .pollcfg = 0,
308 .doorbell = MHI_DB_BRST_DISABLE,
309 .lpm_notify = false,
310 .offload_channel = false,
311 .doorbell_mode_switch = false,
312 .wake_capable = false,
313 },
314 {
315 .name = "QAIC_DEBUG",
316 .num = 19,
317 .num_elements = 32,
318 .local_elements = 0,
319 .event_ring = 0,
320 .dir = DMA_FROM_DEVICE,
321 .ee_mask = MHI_CH_EE_AMSS,
322 .pollcfg = 0,
323 .doorbell = MHI_DB_BRST_DISABLE,
324 .lpm_notify = false,
325 .offload_channel = false,
326 .doorbell_mode_switch = false,
327 .wake_capable = false,
328 },
329 {
330 .name = "QAIC_TIMESYNC",
331 .num = 20,
332 .num_elements = 32,
333 .local_elements = 0,
334 .event_ring = 0,
335 .dir = DMA_TO_DEVICE,
336 .ee_mask = MHI_CH_EE_SBL,
337 .pollcfg = 0,
338 .doorbell = MHI_DB_BRST_DISABLE,
339 .lpm_notify = false,
340 .offload_channel = false,
341 .doorbell_mode_switch = false,
342 .wake_capable = false,
343 },
344 {
345 .name = "QAIC_TIMESYNC",
346 .num = 21,
347 .num_elements = 32,
348 .local_elements = 0,
349 .event_ring = 0,
350 .dir = DMA_FROM_DEVICE,
351 .ee_mask = MHI_CH_EE_SBL,
352 .pollcfg = 0,
353 .doorbell = MHI_DB_BRST_DISABLE,
354 .lpm_notify = false,
355 .offload_channel = false,
356 .doorbell_mode_switch = false,
357 .wake_capable = false,
358 },
359 {
360 .name = "QAIC_TIMESYNC_PERIODIC",
361 .num = 22,
362 .num_elements = 32,
363 .local_elements = 0,
364 .event_ring = 0,
365 .dir = DMA_TO_DEVICE,
366 .ee_mask = MHI_CH_EE_AMSS,
367 .pollcfg = 0,
368 .doorbell = MHI_DB_BRST_DISABLE,
369 .lpm_notify = false,
370 .offload_channel = false,
371 .doorbell_mode_switch = false,
372 .wake_capable = false,
373 },
374 {
375 .name = "QAIC_TIMESYNC_PERIODIC",
376 .num = 23,
377 .num_elements = 32,
378 .local_elements = 0,
379 .event_ring = 0,
380 .dir = DMA_FROM_DEVICE,
381 .ee_mask = MHI_CH_EE_AMSS,
382 .pollcfg = 0,
383 .doorbell = MHI_DB_BRST_DISABLE,
384 .lpm_notify = false,
385 .offload_channel = false,
386 .doorbell_mode_switch = false,
387 .wake_capable = false,
388 },
389 {
390 .name = "IPCR",
391 .num = 24,
392 .num_elements = 32,
393 .local_elements = 0,
394 .event_ring = 0,
395 .dir = DMA_TO_DEVICE,
396 .ee_mask = MHI_CH_EE_AMSS,
397 .pollcfg = 0,
398 .doorbell = MHI_DB_BRST_DISABLE,
399 .lpm_notify = false,
400 .offload_channel = false,
401 .doorbell_mode_switch = false,
402 .wake_capable = false,
403 },
404 {
405 .name = "IPCR",
406 .num = 25,
407 .num_elements = 32,
408 .local_elements = 0,
409 .event_ring = 0,
410 .dir = DMA_FROM_DEVICE,
411 .ee_mask = MHI_CH_EE_AMSS,
412 .pollcfg = 0,
413 .doorbell = MHI_DB_BRST_DISABLE,
414 .lpm_notify = false,
415 .offload_channel = false,
416 .doorbell_mode_switch = false,
417 .wake_capable = false,
418 },
419 };
420
421 static const struct mhi_channel_config aic200_channels[] = {
422 {
423 .name = "QAIC_LOOPBACK",
424 .num = 0,
425 .num_elements = 32,
426 .local_elements = 0,
427 .event_ring = 0,
428 .dir = DMA_TO_DEVICE,
429 .ee_mask = MHI_CH_EE_AMSS,
430 .pollcfg = 0,
431 .doorbell = MHI_DB_BRST_DISABLE,
432 .lpm_notify = false,
433 .offload_channel = false,
434 .doorbell_mode_switch = false,
435 .wake_capable = false,
436 },
437 {
438 .name = "QAIC_LOOPBACK",
439 .num = 1,
440 .num_elements = 32,
441 .local_elements = 0,
442 .event_ring = 0,
443 .dir = DMA_FROM_DEVICE,
444 .ee_mask = MHI_CH_EE_AMSS,
445 .pollcfg = 0,
446 .doorbell = MHI_DB_BRST_DISABLE,
447 .lpm_notify = false,
448 .offload_channel = false,
449 .doorbell_mode_switch = false,
450 .wake_capable = false,
451 },
452 {
453 .name = "QAIC_SAHARA",
454 .num = 2,
455 .num_elements = 32,
456 .local_elements = 0,
457 .event_ring = 0,
458 .dir = DMA_TO_DEVICE,
459 .ee_mask = MHI_CH_EE_SBL,
460 .pollcfg = 0,
461 .doorbell = MHI_DB_BRST_DISABLE,
462 .lpm_notify = false,
463 .offload_channel = false,
464 .doorbell_mode_switch = false,
465 .wake_capable = false,
466 },
467 {
468 .name = "QAIC_SAHARA",
469 .num = 3,
470 .num_elements = 32,
471 .local_elements = 0,
472 .event_ring = 0,
473 .dir = DMA_FROM_DEVICE,
474 .ee_mask = MHI_CH_EE_SBL,
475 .pollcfg = 0,
476 .doorbell = MHI_DB_BRST_DISABLE,
477 .lpm_notify = false,
478 .offload_channel = false,
479 .doorbell_mode_switch = false,
480 .wake_capable = false,
481 },
482 {
483 .name = "QAIC_SSR",
484 .num = 6,
485 .num_elements = 32,
486 .local_elements = 0,
487 .event_ring = 0,
488 .dir = DMA_TO_DEVICE,
489 .ee_mask = MHI_CH_EE_AMSS,
490 .pollcfg = 0,
491 .doorbell = MHI_DB_BRST_DISABLE,
492 .lpm_notify = false,
493 .offload_channel = false,
494 .doorbell_mode_switch = false,
495 .wake_capable = false,
496 },
497 {
498 .name = "QAIC_SSR",
499 .num = 7,
500 .num_elements = 32,
501 .local_elements = 0,
502 .event_ring = 0,
503 .dir = DMA_FROM_DEVICE,
504 .ee_mask = MHI_CH_EE_AMSS,
505 .pollcfg = 0,
506 .doorbell = MHI_DB_BRST_DISABLE,
507 .lpm_notify = false,
508 .offload_channel = false,
509 .doorbell_mode_switch = false,
510 .wake_capable = false,
511 },
512 {
513 .name = "QAIC_CONTROL",
514 .num = 10,
515 .num_elements = 128,
516 .local_elements = 0,
517 .event_ring = 0,
518 .dir = DMA_TO_DEVICE,
519 .ee_mask = MHI_CH_EE_AMSS,
520 .pollcfg = 0,
521 .doorbell = MHI_DB_BRST_DISABLE,
522 .lpm_notify = false,
523 .offload_channel = false,
524 .doorbell_mode_switch = false,
525 .wake_capable = false,
526 },
527 {
528 .name = "QAIC_CONTROL",
529 .num = 11,
530 .num_elements = 128,
531 .local_elements = 0,
532 .event_ring = 0,
533 .dir = DMA_FROM_DEVICE,
534 .ee_mask = MHI_CH_EE_AMSS,
535 .pollcfg = 0,
536 .doorbell = MHI_DB_BRST_DISABLE,
537 .lpm_notify = false,
538 .offload_channel = false,
539 .doorbell_mode_switch = false,
540 .wake_capable = false,
541 },
542 {
543 .name = "QAIC_LOGGING",
544 .num = 12,
545 .num_elements = 32,
546 .local_elements = 0,
547 .event_ring = 0,
548 .dir = DMA_TO_DEVICE,
549 .ee_mask = MHI_CH_EE_SBL,
550 .pollcfg = 0,
551 .doorbell = MHI_DB_BRST_DISABLE,
552 .lpm_notify = false,
553 .offload_channel = false,
554 .doorbell_mode_switch = false,
555 .wake_capable = false,
556 },
557 {
558 .name = "QAIC_LOGGING",
559 .num = 13,
560 .num_elements = 32,
561 .local_elements = 0,
562 .event_ring = 0,
563 .dir = DMA_FROM_DEVICE,
564 .ee_mask = MHI_CH_EE_SBL,
565 .pollcfg = 0,
566 .doorbell = MHI_DB_BRST_DISABLE,
567 .lpm_notify = false,
568 .offload_channel = false,
569 .doorbell_mode_switch = false,
570 .wake_capable = false,
571 },
572 {
573 .name = "QAIC_STATUS",
574 .num = 14,
575 .num_elements = 32,
576 .local_elements = 0,
577 .event_ring = 0,
578 .dir = DMA_TO_DEVICE,
579 .ee_mask = MHI_CH_EE_AMSS,
580 .pollcfg = 0,
581 .doorbell = MHI_DB_BRST_DISABLE,
582 .lpm_notify = false,
583 .offload_channel = false,
584 .doorbell_mode_switch = false,
585 .wake_capable = false,
586 },
587 {
588 .name = "QAIC_STATUS",
589 .num = 15,
590 .num_elements = 32,
591 .local_elements = 0,
592 .event_ring = 0,
593 .dir = DMA_FROM_DEVICE,
594 .ee_mask = MHI_CH_EE_AMSS,
595 .pollcfg = 0,
596 .doorbell = MHI_DB_BRST_DISABLE,
597 .lpm_notify = false,
598 .offload_channel = false,
599 .doorbell_mode_switch = false,
600 .wake_capable = false,
601 },
602 {
603 .name = "QAIC_TELEMETRY",
604 .num = 16,
605 .num_elements = 32,
606 .local_elements = 0,
607 .event_ring = 0,
608 .dir = DMA_TO_DEVICE,
609 .ee_mask = MHI_CH_EE_AMSS,
610 .pollcfg = 0,
611 .doorbell = MHI_DB_BRST_DISABLE,
612 .lpm_notify = false,
613 .offload_channel = false,
614 .doorbell_mode_switch = false,
615 .wake_capable = false,
616 },
617 {
618 .name = "QAIC_TELEMETRY",
619 .num = 17,
620 .num_elements = 32,
621 .local_elements = 0,
622 .event_ring = 0,
623 .dir = DMA_FROM_DEVICE,
624 .ee_mask = MHI_CH_EE_AMSS,
625 .pollcfg = 0,
626 .doorbell = MHI_DB_BRST_DISABLE,
627 .lpm_notify = false,
628 .offload_channel = false,
629 .doorbell_mode_switch = false,
630 .wake_capable = false,
631 },
632 {
633 .name = "QAIC_TIMESYNC_PERIODIC",
634 .num = 22,
635 .num_elements = 32,
636 .local_elements = 0,
637 .event_ring = 0,
638 .dir = DMA_TO_DEVICE,
639 .ee_mask = MHI_CH_EE_AMSS,
640 .pollcfg = 0,
641 .doorbell = MHI_DB_BRST_DISABLE,
642 .lpm_notify = false,
643 .offload_channel = false,
644 .doorbell_mode_switch = false,
645 .wake_capable = false,
646 },
647 {
648 .name = "QAIC_TIMESYNC_PERIODIC",
649 .num = 23,
650 .num_elements = 32,
651 .local_elements = 0,
652 .event_ring = 0,
653 .dir = DMA_FROM_DEVICE,
654 .ee_mask = MHI_CH_EE_AMSS,
655 .pollcfg = 0,
656 .doorbell = MHI_DB_BRST_DISABLE,
657 .lpm_notify = false,
658 .offload_channel = false,
659 .doorbell_mode_switch = false,
660 .wake_capable = false,
661 },
662 {
663 .name = "IPCR",
664 .num = 24,
665 .num_elements = 32,
666 .local_elements = 0,
667 .event_ring = 0,
668 .dir = DMA_TO_DEVICE,
669 .ee_mask = MHI_CH_EE_AMSS,
670 .pollcfg = 0,
671 .doorbell = MHI_DB_BRST_DISABLE,
672 .lpm_notify = false,
673 .offload_channel = false,
674 .doorbell_mode_switch = false,
675 .wake_capable = false,
676 },
677 {
678 .name = "IPCR",
679 .num = 25,
680 .num_elements = 32,
681 .local_elements = 0,
682 .event_ring = 0,
683 .dir = DMA_FROM_DEVICE,
684 .ee_mask = MHI_CH_EE_AMSS,
685 .pollcfg = 0,
686 .doorbell = MHI_DB_BRST_DISABLE,
687 .lpm_notify = false,
688 .offload_channel = false,
689 .doorbell_mode_switch = false,
690 .wake_capable = false,
691 },
692 };
693
694 static struct mhi_event_config aic100_events[] = {
695 {
696 .num_elements = 32,
697 .irq_moderation_ms = 0,
698 .irq = 0,
699 .channel = U32_MAX,
700 .priority = 1,
701 .mode = MHI_DB_BRST_DISABLE,
702 .data_type = MHI_ER_CTRL,
703 .hardware_event = false,
704 .client_managed = false,
705 .offload_channel = false,
706 },
707 };
708
709 static struct mhi_event_config aic200_events[] = {
710 {
711 .num_elements = 32,
712 .irq_moderation_ms = 0,
713 .irq = 0,
714 .channel = U32_MAX,
715 .priority = 1,
716 .mode = MHI_DB_BRST_DISABLE,
717 .data_type = MHI_ER_CTRL,
718 .hardware_event = false,
719 .client_managed = false,
720 .offload_channel = false,
721 },
722 };
723
724 static struct mhi_controller_config mhi_cntrl_configs[] = {
725 [FAMILY_AIC100] = {
726 .max_channels = 128,
727 .timeout_ms = 0, /* controlled by mhi_timeout */
728 .buf_len = 0,
729 .num_channels = ARRAY_SIZE(aic100_channels),
730 .ch_cfg = aic100_channels,
731 .num_events = ARRAY_SIZE(aic100_events),
732 .event_cfg = aic100_events,
733 .use_bounce_buf = false,
734 .m2_no_db = false,
735 },
736 [FAMILY_AIC200] = {
737 .max_channels = 128,
738 .timeout_ms = 0, /* controlled by mhi_timeout */
739 .buf_len = 0,
740 .num_channels = ARRAY_SIZE(aic200_channels),
741 .ch_cfg = aic200_channels,
742 .num_events = ARRAY_SIZE(aic200_events),
743 .event_cfg = aic200_events,
744 .use_bounce_buf = false,
745 .m2_no_db = false,
746 },
747 };
748
mhi_read_reg(struct mhi_controller * mhi_cntrl,void __iomem * addr,u32 * out)749 static int mhi_read_reg(struct mhi_controller *mhi_cntrl, void __iomem *addr, u32 *out)
750 {
751 u32 tmp;
752
753 /*
754 * SOC_HW_VERSION quirk
755 * The SOC_HW_VERSION register (offset 0x224) is not reliable and
756 * may contain uninitialized values, including 0xFFFFFFFF. This could
757 * cause a false positive link down error. Instead, intercept any
758 * reads and provide the correct value of the register.
759 */
760 if (addr - mhi_cntrl->regs == 0x224) {
761 *out = 0x60110200;
762 return 0;
763 }
764
765 tmp = readl_relaxed(addr);
766 if (tmp == U32_MAX)
767 return -EIO;
768
769 *out = tmp;
770
771 return 0;
772 }
773
mhi_write_reg(struct mhi_controller * mhi_cntrl,void __iomem * addr,u32 val)774 static void mhi_write_reg(struct mhi_controller *mhi_cntrl, void __iomem *addr, u32 val)
775 {
776 writel_relaxed(val, addr);
777 }
778
mhi_runtime_get(struct mhi_controller * mhi_cntrl)779 static int mhi_runtime_get(struct mhi_controller *mhi_cntrl)
780 {
781 return 0;
782 }
783
mhi_runtime_put(struct mhi_controller * mhi_cntrl)784 static void mhi_runtime_put(struct mhi_controller *mhi_cntrl)
785 {
786 }
787
mhi_status_cb(struct mhi_controller * mhi_cntrl,enum mhi_callback reason)788 static void mhi_status_cb(struct mhi_controller *mhi_cntrl, enum mhi_callback reason)
789 {
790 struct qaic_device *qdev = pci_get_drvdata(to_pci_dev(mhi_cntrl->cntrl_dev));
791
792 /* this event occurs in atomic context */
793 if (reason == MHI_CB_FATAL_ERROR)
794 pci_err(qdev->pdev, "Fatal error received from device. Attempting to recover\n");
795 /* this event occurs in non-atomic context */
796 if (reason == MHI_CB_SYS_ERROR)
797 qaic_dev_reset_clean_local_state(qdev);
798 }
799
mhi_reset_and_async_power_up(struct mhi_controller * mhi_cntrl)800 static int mhi_reset_and_async_power_up(struct mhi_controller *mhi_cntrl)
801 {
802 u8 time_sec = 1;
803 int current_ee;
804 int ret;
805
806 /* Reset the device to bring the device in PBL EE */
807 mhi_soc_reset(mhi_cntrl);
808
809 /*
810 * Keep checking the execution environment(EE) after every 1 second
811 * interval.
812 */
813 do {
814 msleep(1000);
815 current_ee = mhi_get_exec_env(mhi_cntrl);
816 } while (current_ee != MHI_EE_PBL && time_sec++ <= MAX_RESET_TIME_SEC);
817
818 /* If the device is in PBL EE retry power up */
819 if (current_ee == MHI_EE_PBL)
820 ret = mhi_async_power_up(mhi_cntrl);
821 else
822 ret = -EIO;
823
824 return ret;
825 }
826
qaic_mhi_register_controller(struct pci_dev * pci_dev,void __iomem * mhi_bar,int mhi_irq,bool shared_msi,int family)827 struct mhi_controller *qaic_mhi_register_controller(struct pci_dev *pci_dev, void __iomem *mhi_bar,
828 int mhi_irq, bool shared_msi, int family)
829 {
830 struct mhi_controller_config mhi_config = mhi_cntrl_configs[family];
831 struct mhi_controller *mhi_cntrl;
832 int ret;
833
834 mhi_cntrl = devm_kzalloc(&pci_dev->dev, sizeof(*mhi_cntrl), GFP_KERNEL);
835 if (!mhi_cntrl)
836 return ERR_PTR(-ENOMEM);
837
838 mhi_cntrl->cntrl_dev = &pci_dev->dev;
839
840 /*
841 * Covers the entire possible physical ram region. Remote side is
842 * going to calculate a size of this range, so subtract 1 to prevent
843 * rollover.
844 */
845 mhi_cntrl->iova_start = 0;
846 mhi_cntrl->iova_stop = PHYS_ADDR_MAX - 1;
847 mhi_cntrl->status_cb = mhi_status_cb;
848 mhi_cntrl->runtime_get = mhi_runtime_get;
849 mhi_cntrl->runtime_put = mhi_runtime_put;
850 mhi_cntrl->read_reg = mhi_read_reg;
851 mhi_cntrl->write_reg = mhi_write_reg;
852 mhi_cntrl->regs = mhi_bar;
853 mhi_cntrl->reg_len = SZ_4K;
854 mhi_cntrl->nr_irqs = 1;
855 mhi_cntrl->irq = devm_kmalloc(&pci_dev->dev, sizeof(*mhi_cntrl->irq), GFP_KERNEL);
856
857 if (!mhi_cntrl->irq)
858 return ERR_PTR(-ENOMEM);
859
860 mhi_cntrl->irq[0] = mhi_irq;
861
862 if (shared_msi) /* MSI shared with data path, no IRQF_NO_SUSPEND */
863 mhi_cntrl->irq_flags = IRQF_SHARED;
864
865 mhi_cntrl->fw_image = fw_image_paths[family];
866
867 if (family == FAMILY_AIC200) {
868 mhi_cntrl->name = "AIC200";
869 mhi_cntrl->seg_len = SZ_512K;
870 } else {
871 mhi_cntrl->name = "AIC100";
872 }
873
874 /* use latest configured timeout */
875 mhi_config.timeout_ms = mhi_timeout_ms;
876 ret = mhi_register_controller(mhi_cntrl, &mhi_config);
877 if (ret) {
878 pci_err(pci_dev, "mhi_register_controller failed %d\n", ret);
879 return ERR_PTR(ret);
880 }
881
882 ret = mhi_prepare_for_power_up(mhi_cntrl);
883 if (ret) {
884 pci_err(pci_dev, "mhi_prepare_for_power_up failed %d\n", ret);
885 goto prepare_power_up_fail;
886 }
887
888 ret = mhi_async_power_up(mhi_cntrl);
889 /*
890 * If EIO is returned it is possible that device is in SBL EE, which is
891 * undesired. SOC reset the device and try to power up again.
892 */
893 if (ret == -EIO && MHI_EE_SBL == mhi_get_exec_env(mhi_cntrl)) {
894 pci_err(pci_dev, "Found device in SBL at MHI init. Attempting a reset.\n");
895 ret = mhi_reset_and_async_power_up(mhi_cntrl);
896 }
897
898 if (ret) {
899 pci_err(pci_dev, "mhi_async_power_up failed %d\n", ret);
900 goto power_up_fail;
901 }
902
903 return mhi_cntrl;
904
905 power_up_fail:
906 mhi_unprepare_after_power_down(mhi_cntrl);
907 prepare_power_up_fail:
908 mhi_unregister_controller(mhi_cntrl);
909 return ERR_PTR(ret);
910 }
911
qaic_mhi_free_controller(struct mhi_controller * mhi_cntrl,bool link_up)912 void qaic_mhi_free_controller(struct mhi_controller *mhi_cntrl, bool link_up)
913 {
914 mhi_power_down(mhi_cntrl, link_up);
915 mhi_unprepare_after_power_down(mhi_cntrl);
916 mhi_unregister_controller(mhi_cntrl);
917 }
918
qaic_mhi_start_reset(struct mhi_controller * mhi_cntrl)919 void qaic_mhi_start_reset(struct mhi_controller *mhi_cntrl)
920 {
921 mhi_power_down(mhi_cntrl, true);
922 }
923
qaic_mhi_reset_done(struct mhi_controller * mhi_cntrl)924 void qaic_mhi_reset_done(struct mhi_controller *mhi_cntrl)
925 {
926 struct pci_dev *pci_dev = container_of(mhi_cntrl->cntrl_dev, struct pci_dev, dev);
927 int ret;
928
929 ret = mhi_async_power_up(mhi_cntrl);
930 if (ret)
931 pci_err(pci_dev, "mhi_async_power_up failed after reset %d\n", ret);
932 }
933