]> Git Repo - J-linux.git/blob - drivers/accel/qaic/mhi_controller.c
Merge tag 'vfs-6.13-rc7.fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs
[J-linux.git] / drivers / accel / qaic / mhi_controller.c
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 struct mhi_channel_config aic100_channels[] = {
24         {
25                 .name = "QAIC_LOOPBACK",
26                 .num = 0,
27                 .num_elements = 32,
28                 .local_elements = 0,
29                 .event_ring = 0,
30                 .dir = DMA_TO_DEVICE,
31                 .ee_mask = MHI_CH_EE_AMSS,
32                 .pollcfg = 0,
33                 .doorbell = MHI_DB_BRST_DISABLE,
34                 .lpm_notify = false,
35                 .offload_channel = false,
36                 .doorbell_mode_switch = false,
37                 .auto_queue = false,
38                 .wake_capable = false,
39         },
40         {
41                 .name = "QAIC_LOOPBACK",
42                 .num = 1,
43                 .num_elements = 32,
44                 .local_elements = 0,
45                 .event_ring = 0,
46                 .dir = DMA_FROM_DEVICE,
47                 .ee_mask = MHI_CH_EE_AMSS,
48                 .pollcfg = 0,
49                 .doorbell = MHI_DB_BRST_DISABLE,
50                 .lpm_notify = false,
51                 .offload_channel = false,
52                 .doorbell_mode_switch = false,
53                 .auto_queue = false,
54                 .wake_capable = false,
55         },
56         {
57                 .name = "QAIC_SAHARA",
58                 .num = 2,
59                 .num_elements = 32,
60                 .local_elements = 0,
61                 .event_ring = 0,
62                 .dir = DMA_TO_DEVICE,
63                 .ee_mask = MHI_CH_EE_SBL,
64                 .pollcfg = 0,
65                 .doorbell = MHI_DB_BRST_DISABLE,
66                 .lpm_notify = false,
67                 .offload_channel = false,
68                 .doorbell_mode_switch = false,
69                 .auto_queue = false,
70                 .wake_capable = false,
71         },
72         {
73                 .name = "QAIC_SAHARA",
74                 .num = 3,
75                 .num_elements = 32,
76                 .local_elements = 0,
77                 .event_ring = 0,
78                 .dir = DMA_FROM_DEVICE,
79                 .ee_mask = MHI_CH_EE_SBL,
80                 .pollcfg = 0,
81                 .doorbell = MHI_DB_BRST_DISABLE,
82                 .lpm_notify = false,
83                 .offload_channel = false,
84                 .doorbell_mode_switch = false,
85                 .auto_queue = false,
86                 .wake_capable = false,
87         },
88         {
89                 .name = "QAIC_DIAG",
90                 .num = 4,
91                 .num_elements = 32,
92                 .local_elements = 0,
93                 .event_ring = 0,
94                 .dir = DMA_TO_DEVICE,
95                 .ee_mask = MHI_CH_EE_AMSS,
96                 .pollcfg = 0,
97                 .doorbell = MHI_DB_BRST_DISABLE,
98                 .lpm_notify = false,
99                 .offload_channel = false,
100                 .doorbell_mode_switch = false,
101                 .auto_queue = 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                 .auto_queue = false,
118                 .wake_capable = false,
119         },
120         {
121                 .name = "QAIC_SSR",
122                 .num = 6,
123                 .num_elements = 32,
124                 .local_elements = 0,
125                 .event_ring = 0,
126                 .dir = DMA_TO_DEVICE,
127                 .ee_mask = MHI_CH_EE_AMSS,
128                 .pollcfg = 0,
129                 .doorbell = MHI_DB_BRST_DISABLE,
130                 .lpm_notify = false,
131                 .offload_channel = false,
132                 .doorbell_mode_switch = false,
133                 .auto_queue = false,
134                 .wake_capable = false,
135         },
136         {
137                 .name = "QAIC_SSR",
138                 .num = 7,
139                 .num_elements = 32,
140                 .local_elements = 0,
141                 .event_ring = 0,
142                 .dir = DMA_FROM_DEVICE,
143                 .ee_mask = MHI_CH_EE_AMSS,
144                 .pollcfg = 0,
145                 .doorbell = MHI_DB_BRST_DISABLE,
146                 .lpm_notify = false,
147                 .offload_channel = false,
148                 .doorbell_mode_switch = false,
149                 .auto_queue = false,
150                 .wake_capable = false,
151         },
152         {
153                 .name = "QAIC_QDSS",
154                 .num = 8,
155                 .num_elements = 32,
156                 .local_elements = 0,
157                 .event_ring = 0,
158                 .dir = DMA_TO_DEVICE,
159                 .ee_mask = MHI_CH_EE_AMSS,
160                 .pollcfg = 0,
161                 .doorbell = MHI_DB_BRST_DISABLE,
162                 .lpm_notify = false,
163                 .offload_channel = false,
164                 .doorbell_mode_switch = false,
165                 .auto_queue = false,
166                 .wake_capable = false,
167         },
168         {
169                 .name = "QAIC_QDSS",
170                 .num = 9,
171                 .num_elements = 32,
172                 .local_elements = 0,
173                 .event_ring = 0,
174                 .dir = DMA_FROM_DEVICE,
175                 .ee_mask = MHI_CH_EE_AMSS,
176                 .pollcfg = 0,
177                 .doorbell = MHI_DB_BRST_DISABLE,
178                 .lpm_notify = false,
179                 .offload_channel = false,
180                 .doorbell_mode_switch = false,
181                 .auto_queue = false,
182                 .wake_capable = false,
183         },
184         {
185                 .name = "QAIC_CONTROL",
186                 .num = 10,
187                 .num_elements = 128,
188                 .local_elements = 0,
189                 .event_ring = 0,
190                 .dir = DMA_TO_DEVICE,
191                 .ee_mask = MHI_CH_EE_AMSS,
192                 .pollcfg = 0,
193                 .doorbell = MHI_DB_BRST_DISABLE,
194                 .lpm_notify = false,
195                 .offload_channel = false,
196                 .doorbell_mode_switch = false,
197                 .auto_queue = false,
198                 .wake_capable = false,
199         },
200         {
201                 .name = "QAIC_CONTROL",
202                 .num = 11,
203                 .num_elements = 128,
204                 .local_elements = 0,
205                 .event_ring = 0,
206                 .dir = DMA_FROM_DEVICE,
207                 .ee_mask = MHI_CH_EE_AMSS,
208                 .pollcfg = 0,
209                 .doorbell = MHI_DB_BRST_DISABLE,
210                 .lpm_notify = false,
211                 .offload_channel = false,
212                 .doorbell_mode_switch = false,
213                 .auto_queue = false,
214                 .wake_capable = false,
215         },
216         {
217                 .name = "QAIC_LOGGING",
218                 .num = 12,
219                 .num_elements = 32,
220                 .local_elements = 0,
221                 .event_ring = 0,
222                 .dir = DMA_TO_DEVICE,
223                 .ee_mask = MHI_CH_EE_SBL,
224                 .pollcfg = 0,
225                 .doorbell = MHI_DB_BRST_DISABLE,
226                 .lpm_notify = false,
227                 .offload_channel = false,
228                 .doorbell_mode_switch = false,
229                 .auto_queue = false,
230                 .wake_capable = false,
231         },
232         {
233                 .name = "QAIC_LOGGING",
234                 .num = 13,
235                 .num_elements = 32,
236                 .local_elements = 0,
237                 .event_ring = 0,
238                 .dir = DMA_FROM_DEVICE,
239                 .ee_mask = MHI_CH_EE_SBL,
240                 .pollcfg = 0,
241                 .doorbell = MHI_DB_BRST_DISABLE,
242                 .lpm_notify = false,
243                 .offload_channel = false,
244                 .doorbell_mode_switch = false,
245                 .auto_queue = false,
246                 .wake_capable = false,
247         },
248         {
249                 .name = "QAIC_STATUS",
250                 .num = 14,
251                 .num_elements = 32,
252                 .local_elements = 0,
253                 .event_ring = 0,
254                 .dir = DMA_TO_DEVICE,
255                 .ee_mask = MHI_CH_EE_AMSS,
256                 .pollcfg = 0,
257                 .doorbell = MHI_DB_BRST_DISABLE,
258                 .lpm_notify = false,
259                 .offload_channel = false,
260                 .doorbell_mode_switch = false,
261                 .auto_queue = false,
262                 .wake_capable = false,
263         },
264         {
265                 .name = "QAIC_STATUS",
266                 .num = 15,
267                 .num_elements = 32,
268                 .local_elements = 0,
269                 .event_ring = 0,
270                 .dir = DMA_FROM_DEVICE,
271                 .ee_mask = MHI_CH_EE_AMSS,
272                 .pollcfg = 0,
273                 .doorbell = MHI_DB_BRST_DISABLE,
274                 .lpm_notify = false,
275                 .offload_channel = false,
276                 .doorbell_mode_switch = false,
277                 .auto_queue = false,
278                 .wake_capable = false,
279         },
280         {
281                 .name = "QAIC_TELEMETRY",
282                 .num = 16,
283                 .num_elements = 32,
284                 .local_elements = 0,
285                 .event_ring = 0,
286                 .dir = DMA_TO_DEVICE,
287                 .ee_mask = MHI_CH_EE_AMSS,
288                 .pollcfg = 0,
289                 .doorbell = MHI_DB_BRST_DISABLE,
290                 .lpm_notify = false,
291                 .offload_channel = false,
292                 .doorbell_mode_switch = false,
293                 .auto_queue = false,
294                 .wake_capable = false,
295         },
296         {
297                 .name = "QAIC_TELEMETRY",
298                 .num = 17,
299                 .num_elements = 32,
300                 .local_elements = 0,
301                 .event_ring = 0,
302                 .dir = DMA_FROM_DEVICE,
303                 .ee_mask = MHI_CH_EE_AMSS,
304                 .pollcfg = 0,
305                 .doorbell = MHI_DB_BRST_DISABLE,
306                 .lpm_notify = false,
307                 .offload_channel = false,
308                 .doorbell_mode_switch = false,
309                 .auto_queue = false,
310                 .wake_capable = false,
311         },
312         {
313                 .name = "QAIC_DEBUG",
314                 .num = 18,
315                 .num_elements = 32,
316                 .local_elements = 0,
317                 .event_ring = 0,
318                 .dir = DMA_TO_DEVICE,
319                 .ee_mask = MHI_CH_EE_AMSS,
320                 .pollcfg = 0,
321                 .doorbell = MHI_DB_BRST_DISABLE,
322                 .lpm_notify = false,
323                 .offload_channel = false,
324                 .doorbell_mode_switch = false,
325                 .auto_queue = false,
326                 .wake_capable = false,
327         },
328         {
329                 .name = "QAIC_DEBUG",
330                 .num = 19,
331                 .num_elements = 32,
332                 .local_elements = 0,
333                 .event_ring = 0,
334                 .dir = DMA_FROM_DEVICE,
335                 .ee_mask = MHI_CH_EE_AMSS,
336                 .pollcfg = 0,
337                 .doorbell = MHI_DB_BRST_DISABLE,
338                 .lpm_notify = false,
339                 .offload_channel = false,
340                 .doorbell_mode_switch = false,
341                 .auto_queue = false,
342                 .wake_capable = false,
343         },
344         {
345                 .name = "QAIC_TIMESYNC",
346                 .num = 20,
347                 .num_elements = 32,
348                 .local_elements = 0,
349                 .event_ring = 0,
350                 .dir = DMA_TO_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                 .auto_queue = false,
358                 .wake_capable = false,
359         },
360         {
361                 .name = "QAIC_TIMESYNC",
362                 .num = 21,
363                 .num_elements = 32,
364                 .local_elements = 0,
365                 .event_ring = 0,
366                 .dir = DMA_FROM_DEVICE,
367                 .ee_mask = MHI_CH_EE_SBL,
368                 .pollcfg = 0,
369                 .doorbell = MHI_DB_BRST_DISABLE,
370                 .lpm_notify = false,
371                 .offload_channel = false,
372                 .doorbell_mode_switch = false,
373                 .auto_queue = false,
374                 .wake_capable = false,
375         },
376         {
377                 .name = "QAIC_TIMESYNC_PERIODIC",
378                 .num = 22,
379                 .num_elements = 32,
380                 .local_elements = 0,
381                 .event_ring = 0,
382                 .dir = DMA_TO_DEVICE,
383                 .ee_mask = MHI_CH_EE_AMSS,
384                 .pollcfg = 0,
385                 .doorbell = MHI_DB_BRST_DISABLE,
386                 .lpm_notify = false,
387                 .offload_channel = false,
388                 .doorbell_mode_switch = false,
389                 .auto_queue = false,
390                 .wake_capable = false,
391         },
392         {
393                 .name = "QAIC_TIMESYNC_PERIODIC",
394                 .num = 23,
395                 .num_elements = 32,
396                 .local_elements = 0,
397                 .event_ring = 0,
398                 .dir = DMA_FROM_DEVICE,
399                 .ee_mask = MHI_CH_EE_AMSS,
400                 .pollcfg = 0,
401                 .doorbell = MHI_DB_BRST_DISABLE,
402                 .lpm_notify = false,
403                 .offload_channel = false,
404                 .doorbell_mode_switch = false,
405                 .auto_queue = false,
406                 .wake_capable = false,
407         },
408         {
409                 .name = "IPCR",
410                 .num = 24,
411                 .num_elements = 32,
412                 .local_elements = 0,
413                 .event_ring = 0,
414                 .dir = DMA_TO_DEVICE,
415                 .ee_mask = MHI_CH_EE_AMSS,
416                 .pollcfg = 0,
417                 .doorbell = MHI_DB_BRST_DISABLE,
418                 .lpm_notify = false,
419                 .offload_channel = false,
420                 .doorbell_mode_switch = false,
421                 .auto_queue = false,
422                 .wake_capable = false,
423         },
424         {
425                 .name = "IPCR",
426                 .num = 25,
427                 .num_elements = 32,
428                 .local_elements = 0,
429                 .event_ring = 0,
430                 .dir = DMA_FROM_DEVICE,
431                 .ee_mask = MHI_CH_EE_AMSS,
432                 .pollcfg = 0,
433                 .doorbell = MHI_DB_BRST_DISABLE,
434                 .lpm_notify = false,
435                 .offload_channel = false,
436                 .doorbell_mode_switch = false,
437                 .auto_queue = true,
438                 .wake_capable = false,
439         },
440 };
441
442 static struct mhi_event_config aic100_events[] = {
443         {
444                 .num_elements = 32,
445                 .irq_moderation_ms = 0,
446                 .irq = 0,
447                 .channel = U32_MAX,
448                 .priority = 1,
449                 .mode = MHI_DB_BRST_DISABLE,
450                 .data_type = MHI_ER_CTRL,
451                 .hardware_event = false,
452                 .client_managed = false,
453                 .offload_channel = false,
454         },
455 };
456
457 static struct mhi_controller_config aic100_config = {
458         .max_channels = 128,
459         .timeout_ms = 0, /* controlled by mhi_timeout */
460         .buf_len = 0,
461         .num_channels = ARRAY_SIZE(aic100_channels),
462         .ch_cfg = aic100_channels,
463         .num_events = ARRAY_SIZE(aic100_events),
464         .event_cfg = aic100_events,
465         .use_bounce_buf = false,
466         .m2_no_db = false,
467 };
468
469 static int mhi_read_reg(struct mhi_controller *mhi_cntrl, void __iomem *addr, u32 *out)
470 {
471         u32 tmp;
472
473         /*
474          * SOC_HW_VERSION quirk
475          * The SOC_HW_VERSION register (offset 0x224) is not reliable and
476          * may contain uninitialized values, including 0xFFFFFFFF. This could
477          * cause a false positive link down error.  Instead, intercept any
478          * reads and provide the correct value of the register.
479          */
480         if (addr - mhi_cntrl->regs == 0x224) {
481                 *out = 0x60110200;
482                 return 0;
483         }
484
485         tmp = readl_relaxed(addr);
486         if (tmp == U32_MAX)
487                 return -EIO;
488
489         *out = tmp;
490
491         return 0;
492 }
493
494 static void mhi_write_reg(struct mhi_controller *mhi_cntrl, void __iomem *addr, u32 val)
495 {
496         writel_relaxed(val, addr);
497 }
498
499 static int mhi_runtime_get(struct mhi_controller *mhi_cntrl)
500 {
501         return 0;
502 }
503
504 static void mhi_runtime_put(struct mhi_controller *mhi_cntrl)
505 {
506 }
507
508 static void mhi_status_cb(struct mhi_controller *mhi_cntrl, enum mhi_callback reason)
509 {
510         struct qaic_device *qdev = pci_get_drvdata(to_pci_dev(mhi_cntrl->cntrl_dev));
511
512         /* this event occurs in atomic context */
513         if (reason == MHI_CB_FATAL_ERROR)
514                 pci_err(qdev->pdev, "Fatal error received from device. Attempting to recover\n");
515         /* this event occurs in non-atomic context */
516         if (reason == MHI_CB_SYS_ERROR)
517                 qaic_dev_reset_clean_local_state(qdev);
518 }
519
520 static int mhi_reset_and_async_power_up(struct mhi_controller *mhi_cntrl)
521 {
522         u8 time_sec = 1;
523         int current_ee;
524         int ret;
525
526         /* Reset the device to bring the device in PBL EE */
527         mhi_soc_reset(mhi_cntrl);
528
529         /*
530          * Keep checking the execution environment(EE) after every 1 second
531          * interval.
532          */
533         do {
534                 msleep(1000);
535                 current_ee = mhi_get_exec_env(mhi_cntrl);
536         } while (current_ee != MHI_EE_PBL && time_sec++ <= MAX_RESET_TIME_SEC);
537
538         /* If the device is in PBL EE retry power up */
539         if (current_ee == MHI_EE_PBL)
540                 ret = mhi_async_power_up(mhi_cntrl);
541         else
542                 ret = -EIO;
543
544         return ret;
545 }
546
547 struct mhi_controller *qaic_mhi_register_controller(struct pci_dev *pci_dev, void __iomem *mhi_bar,
548                                                     int mhi_irq, bool shared_msi)
549 {
550         struct mhi_controller *mhi_cntrl;
551         int ret;
552
553         mhi_cntrl = devm_kzalloc(&pci_dev->dev, sizeof(*mhi_cntrl), GFP_KERNEL);
554         if (!mhi_cntrl)
555                 return ERR_PTR(-ENOMEM);
556
557         mhi_cntrl->cntrl_dev = &pci_dev->dev;
558
559         /*
560          * Covers the entire possible physical ram region. Remote side is
561          * going to calculate a size of this range, so subtract 1 to prevent
562          * rollover.
563          */
564         mhi_cntrl->iova_start = 0;
565         mhi_cntrl->iova_stop = PHYS_ADDR_MAX - 1;
566         mhi_cntrl->status_cb = mhi_status_cb;
567         mhi_cntrl->runtime_get = mhi_runtime_get;
568         mhi_cntrl->runtime_put = mhi_runtime_put;
569         mhi_cntrl->read_reg = mhi_read_reg;
570         mhi_cntrl->write_reg = mhi_write_reg;
571         mhi_cntrl->regs = mhi_bar;
572         mhi_cntrl->reg_len = SZ_4K;
573         mhi_cntrl->nr_irqs = 1;
574         mhi_cntrl->irq = devm_kmalloc(&pci_dev->dev, sizeof(*mhi_cntrl->irq), GFP_KERNEL);
575
576         if (!mhi_cntrl->irq)
577                 return ERR_PTR(-ENOMEM);
578
579         mhi_cntrl->irq[0] = mhi_irq;
580
581         if (shared_msi) /* MSI shared with data path, no IRQF_NO_SUSPEND */
582                 mhi_cntrl->irq_flags = IRQF_SHARED;
583
584         mhi_cntrl->fw_image = "qcom/aic100/sbl.bin";
585
586         /* use latest configured timeout */
587         aic100_config.timeout_ms = mhi_timeout_ms;
588         ret = mhi_register_controller(mhi_cntrl, &aic100_config);
589         if (ret) {
590                 pci_err(pci_dev, "mhi_register_controller failed %d\n", ret);
591                 return ERR_PTR(ret);
592         }
593
594         ret = mhi_prepare_for_power_up(mhi_cntrl);
595         if (ret) {
596                 pci_err(pci_dev, "mhi_prepare_for_power_up failed %d\n", ret);
597                 goto prepare_power_up_fail;
598         }
599
600         ret = mhi_async_power_up(mhi_cntrl);
601         /*
602          * If EIO is returned it is possible that device is in SBL EE, which is
603          * undesired. SOC reset the device and try to power up again.
604          */
605         if (ret == -EIO && MHI_EE_SBL == mhi_get_exec_env(mhi_cntrl)) {
606                 pci_err(pci_dev, "Found device in SBL at MHI init. Attempting a reset.\n");
607                 ret = mhi_reset_and_async_power_up(mhi_cntrl);
608         }
609
610         if (ret) {
611                 pci_err(pci_dev, "mhi_async_power_up failed %d\n", ret);
612                 goto power_up_fail;
613         }
614
615         return mhi_cntrl;
616
617 power_up_fail:
618         mhi_unprepare_after_power_down(mhi_cntrl);
619 prepare_power_up_fail:
620         mhi_unregister_controller(mhi_cntrl);
621         return ERR_PTR(ret);
622 }
623
624 void qaic_mhi_free_controller(struct mhi_controller *mhi_cntrl, bool link_up)
625 {
626         mhi_power_down(mhi_cntrl, link_up);
627         mhi_unprepare_after_power_down(mhi_cntrl);
628         mhi_unregister_controller(mhi_cntrl);
629 }
630
631 void qaic_mhi_start_reset(struct mhi_controller *mhi_cntrl)
632 {
633         mhi_power_down(mhi_cntrl, true);
634 }
635
636 void qaic_mhi_reset_done(struct mhi_controller *mhi_cntrl)
637 {
638         struct pci_dev *pci_dev = container_of(mhi_cntrl->cntrl_dev, struct pci_dev, dev);
639         int ret;
640
641         ret = mhi_async_power_up(mhi_cntrl);
642         if (ret)
643                 pci_err(pci_dev, "mhi_async_power_up failed after reset %d\n", ret);
644 }
This page took 0.06426 seconds and 4 git commands to generate.