Merge tag 'drm-misc-next-2024-01-11' of git://anongit.freedesktop.org/drm/drm-misc...
[sfrench/cifs-2.6.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 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
410 static struct mhi_event_config aic100_events[] = {
411         {
412                 .num_elements = 32,
413                 .irq_moderation_ms = 0,
414                 .irq = 0,
415                 .channel = U32_MAX,
416                 .priority = 1,
417                 .mode = MHI_DB_BRST_DISABLE,
418                 .data_type = MHI_ER_CTRL,
419                 .hardware_event = false,
420                 .client_managed = false,
421                 .offload_channel = false,
422         },
423 };
424
425 static struct mhi_controller_config aic100_config = {
426         .max_channels = 128,
427         .timeout_ms = 0, /* controlled by mhi_timeout */
428         .buf_len = 0,
429         .num_channels = ARRAY_SIZE(aic100_channels),
430         .ch_cfg = aic100_channels,
431         .num_events = ARRAY_SIZE(aic100_events),
432         .event_cfg = aic100_events,
433         .use_bounce_buf = false,
434         .m2_no_db = false,
435 };
436
437 static int mhi_read_reg(struct mhi_controller *mhi_cntrl, void __iomem *addr, u32 *out)
438 {
439         u32 tmp;
440
441         /*
442          * SOC_HW_VERSION quirk
443          * The SOC_HW_VERSION register (offset 0x224) is not reliable and
444          * may contain uninitialized values, including 0xFFFFFFFF. This could
445          * cause a false positive link down error.  Instead, intercept any
446          * reads and provide the correct value of the register.
447          */
448         if (addr - mhi_cntrl->regs == 0x224) {
449                 *out = 0x60110200;
450                 return 0;
451         }
452
453         tmp = readl_relaxed(addr);
454         if (tmp == U32_MAX)
455                 return -EIO;
456
457         *out = tmp;
458
459         return 0;
460 }
461
462 static void mhi_write_reg(struct mhi_controller *mhi_cntrl, void __iomem *addr, u32 val)
463 {
464         writel_relaxed(val, addr);
465 }
466
467 static int mhi_runtime_get(struct mhi_controller *mhi_cntrl)
468 {
469         return 0;
470 }
471
472 static void mhi_runtime_put(struct mhi_controller *mhi_cntrl)
473 {
474 }
475
476 static void mhi_status_cb(struct mhi_controller *mhi_cntrl, enum mhi_callback reason)
477 {
478         struct qaic_device *qdev = pci_get_drvdata(to_pci_dev(mhi_cntrl->cntrl_dev));
479
480         /* this event occurs in atomic context */
481         if (reason == MHI_CB_FATAL_ERROR)
482                 pci_err(qdev->pdev, "Fatal error received from device. Attempting to recover\n");
483         /* this event occurs in non-atomic context */
484         if (reason == MHI_CB_SYS_ERROR)
485                 qaic_dev_reset_clean_local_state(qdev);
486 }
487
488 static int mhi_reset_and_async_power_up(struct mhi_controller *mhi_cntrl)
489 {
490         u8 time_sec = 1;
491         int current_ee;
492         int ret;
493
494         /* Reset the device to bring the device in PBL EE */
495         mhi_soc_reset(mhi_cntrl);
496
497         /*
498          * Keep checking the execution environment(EE) after every 1 second
499          * interval.
500          */
501         do {
502                 msleep(1000);
503                 current_ee = mhi_get_exec_env(mhi_cntrl);
504         } while (current_ee != MHI_EE_PBL && time_sec++ <= MAX_RESET_TIME_SEC);
505
506         /* If the device is in PBL EE retry power up */
507         if (current_ee == MHI_EE_PBL)
508                 ret = mhi_async_power_up(mhi_cntrl);
509         else
510                 ret = -EIO;
511
512         return ret;
513 }
514
515 struct mhi_controller *qaic_mhi_register_controller(struct pci_dev *pci_dev, void __iomem *mhi_bar,
516                                                     int mhi_irq, bool shared_msi)
517 {
518         struct mhi_controller *mhi_cntrl;
519         int ret;
520
521         mhi_cntrl = devm_kzalloc(&pci_dev->dev, sizeof(*mhi_cntrl), GFP_KERNEL);
522         if (!mhi_cntrl)
523                 return ERR_PTR(-ENOMEM);
524
525         mhi_cntrl->cntrl_dev = &pci_dev->dev;
526
527         /*
528          * Covers the entire possible physical ram region. Remote side is
529          * going to calculate a size of this range, so subtract 1 to prevent
530          * rollover.
531          */
532         mhi_cntrl->iova_start = 0;
533         mhi_cntrl->iova_stop = PHYS_ADDR_MAX - 1;
534         mhi_cntrl->status_cb = mhi_status_cb;
535         mhi_cntrl->runtime_get = mhi_runtime_get;
536         mhi_cntrl->runtime_put = mhi_runtime_put;
537         mhi_cntrl->read_reg = mhi_read_reg;
538         mhi_cntrl->write_reg = mhi_write_reg;
539         mhi_cntrl->regs = mhi_bar;
540         mhi_cntrl->reg_len = SZ_4K;
541         mhi_cntrl->nr_irqs = 1;
542         mhi_cntrl->irq = devm_kmalloc(&pci_dev->dev, sizeof(*mhi_cntrl->irq), GFP_KERNEL);
543
544         if (!mhi_cntrl->irq)
545                 return ERR_PTR(-ENOMEM);
546
547         mhi_cntrl->irq[0] = mhi_irq;
548
549         if (shared_msi) /* MSI shared with data path, no IRQF_NO_SUSPEND */
550                 mhi_cntrl->irq_flags = IRQF_SHARED;
551
552         mhi_cntrl->fw_image = "qcom/aic100/sbl.bin";
553
554         /* use latest configured timeout */
555         aic100_config.timeout_ms = mhi_timeout_ms;
556         ret = mhi_register_controller(mhi_cntrl, &aic100_config);
557         if (ret) {
558                 pci_err(pci_dev, "mhi_register_controller failed %d\n", ret);
559                 return ERR_PTR(ret);
560         }
561
562         ret = mhi_prepare_for_power_up(mhi_cntrl);
563         if (ret) {
564                 pci_err(pci_dev, "mhi_prepare_for_power_up failed %d\n", ret);
565                 goto prepare_power_up_fail;
566         }
567
568         ret = mhi_async_power_up(mhi_cntrl);
569         /*
570          * If EIO is returned it is possible that device is in SBL EE, which is
571          * undesired. SOC reset the device and try to power up again.
572          */
573         if (ret == -EIO && MHI_EE_SBL == mhi_get_exec_env(mhi_cntrl)) {
574                 pci_err(pci_dev, "Found device in SBL at MHI init. Attempting a reset.\n");
575                 ret = mhi_reset_and_async_power_up(mhi_cntrl);
576         }
577
578         if (ret) {
579                 pci_err(pci_dev, "mhi_async_power_up failed %d\n", ret);
580                 goto power_up_fail;
581         }
582
583         return mhi_cntrl;
584
585 power_up_fail:
586         mhi_unprepare_after_power_down(mhi_cntrl);
587 prepare_power_up_fail:
588         mhi_unregister_controller(mhi_cntrl);
589         return ERR_PTR(ret);
590 }
591
592 void qaic_mhi_free_controller(struct mhi_controller *mhi_cntrl, bool link_up)
593 {
594         mhi_power_down(mhi_cntrl, link_up);
595         mhi_unprepare_after_power_down(mhi_cntrl);
596         mhi_unregister_controller(mhi_cntrl);
597 }
598
599 void qaic_mhi_start_reset(struct mhi_controller *mhi_cntrl)
600 {
601         mhi_power_down(mhi_cntrl, true);
602 }
603
604 void qaic_mhi_reset_done(struct mhi_controller *mhi_cntrl)
605 {
606         struct pci_dev *pci_dev = container_of(mhi_cntrl->cntrl_dev, struct pci_dev, dev);
607         int ret;
608
609         ret = mhi_async_power_up(mhi_cntrl);
610         if (ret)
611                 pci_err(pci_dev, "mhi_async_power_up failed after reset %d\n", ret);
612 }