1 // SPDX-License-Identifier: GPL-2.0-only
3 /* Copyright (c) 2019-2021, The Linux Foundation. All rights reserved. */
4 /* Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. */
6 #include <linux/delay.h>
8 #include <linux/memblock.h>
10 #include <linux/moduleparam.h>
11 #include <linux/pci.h>
12 #include <linux/sizes.h>
14 #include "mhi_controller.h"
17 #define MAX_RESET_TIME_SEC 25
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");
23 static const struct mhi_channel_config aic100_channels
[] = {
25 .name
= "QAIC_LOOPBACK",
31 .ee_mask
= MHI_CH_EE_AMSS
,
33 .doorbell
= MHI_DB_BRST_DISABLE
,
35 .offload_channel
= false,
36 .doorbell_mode_switch
= false,
38 .wake_capable
= false,
41 .name
= "QAIC_LOOPBACK",
46 .dir
= DMA_FROM_DEVICE
,
47 .ee_mask
= MHI_CH_EE_AMSS
,
49 .doorbell
= MHI_DB_BRST_DISABLE
,
51 .offload_channel
= false,
52 .doorbell_mode_switch
= false,
54 .wake_capable
= false,
57 .name
= "QAIC_SAHARA",
63 .ee_mask
= MHI_CH_EE_SBL
,
65 .doorbell
= MHI_DB_BRST_DISABLE
,
67 .offload_channel
= false,
68 .doorbell_mode_switch
= false,
70 .wake_capable
= false,
73 .name
= "QAIC_SAHARA",
78 .dir
= DMA_FROM_DEVICE
,
79 .ee_mask
= MHI_CH_EE_SBL
,
81 .doorbell
= MHI_DB_BRST_DISABLE
,
83 .offload_channel
= false,
84 .doorbell_mode_switch
= false,
86 .wake_capable
= false,
95 .ee_mask
= MHI_CH_EE_AMSS
,
97 .doorbell
= MHI_DB_BRST_DISABLE
,
99 .offload_channel
= false,
100 .doorbell_mode_switch
= false,
102 .wake_capable
= false,
110 .dir
= DMA_FROM_DEVICE
,
111 .ee_mask
= MHI_CH_EE_AMSS
,
113 .doorbell
= MHI_DB_BRST_DISABLE
,
115 .offload_channel
= false,
116 .doorbell_mode_switch
= false,
118 .wake_capable
= false,
126 .dir
= DMA_TO_DEVICE
,
127 .ee_mask
= MHI_CH_EE_AMSS
,
129 .doorbell
= MHI_DB_BRST_DISABLE
,
131 .offload_channel
= false,
132 .doorbell_mode_switch
= false,
134 .wake_capable
= false,
142 .dir
= DMA_FROM_DEVICE
,
143 .ee_mask
= MHI_CH_EE_AMSS
,
145 .doorbell
= MHI_DB_BRST_DISABLE
,
147 .offload_channel
= false,
148 .doorbell_mode_switch
= false,
150 .wake_capable
= false,
158 .dir
= DMA_TO_DEVICE
,
159 .ee_mask
= MHI_CH_EE_AMSS
,
161 .doorbell
= MHI_DB_BRST_DISABLE
,
163 .offload_channel
= false,
164 .doorbell_mode_switch
= false,
166 .wake_capable
= false,
174 .dir
= DMA_FROM_DEVICE
,
175 .ee_mask
= MHI_CH_EE_AMSS
,
177 .doorbell
= MHI_DB_BRST_DISABLE
,
179 .offload_channel
= false,
180 .doorbell_mode_switch
= false,
182 .wake_capable
= false,
185 .name
= "QAIC_CONTROL",
190 .dir
= DMA_TO_DEVICE
,
191 .ee_mask
= MHI_CH_EE_AMSS
,
193 .doorbell
= MHI_DB_BRST_DISABLE
,
195 .offload_channel
= false,
196 .doorbell_mode_switch
= false,
198 .wake_capable
= false,
201 .name
= "QAIC_CONTROL",
206 .dir
= DMA_FROM_DEVICE
,
207 .ee_mask
= MHI_CH_EE_AMSS
,
209 .doorbell
= MHI_DB_BRST_DISABLE
,
211 .offload_channel
= false,
212 .doorbell_mode_switch
= false,
214 .wake_capable
= false,
217 .name
= "QAIC_LOGGING",
222 .dir
= DMA_TO_DEVICE
,
223 .ee_mask
= MHI_CH_EE_SBL
,
225 .doorbell
= MHI_DB_BRST_DISABLE
,
227 .offload_channel
= false,
228 .doorbell_mode_switch
= false,
230 .wake_capable
= false,
233 .name
= "QAIC_LOGGING",
238 .dir
= DMA_FROM_DEVICE
,
239 .ee_mask
= MHI_CH_EE_SBL
,
241 .doorbell
= MHI_DB_BRST_DISABLE
,
243 .offload_channel
= false,
244 .doorbell_mode_switch
= false,
246 .wake_capable
= false,
249 .name
= "QAIC_STATUS",
254 .dir
= DMA_TO_DEVICE
,
255 .ee_mask
= MHI_CH_EE_AMSS
,
257 .doorbell
= MHI_DB_BRST_DISABLE
,
259 .offload_channel
= false,
260 .doorbell_mode_switch
= false,
262 .wake_capable
= false,
265 .name
= "QAIC_STATUS",
270 .dir
= DMA_FROM_DEVICE
,
271 .ee_mask
= MHI_CH_EE_AMSS
,
273 .doorbell
= MHI_DB_BRST_DISABLE
,
275 .offload_channel
= false,
276 .doorbell_mode_switch
= false,
278 .wake_capable
= false,
281 .name
= "QAIC_TELEMETRY",
286 .dir
= DMA_TO_DEVICE
,
287 .ee_mask
= MHI_CH_EE_AMSS
,
289 .doorbell
= MHI_DB_BRST_DISABLE
,
291 .offload_channel
= false,
292 .doorbell_mode_switch
= false,
294 .wake_capable
= false,
297 .name
= "QAIC_TELEMETRY",
302 .dir
= DMA_FROM_DEVICE
,
303 .ee_mask
= MHI_CH_EE_AMSS
,
305 .doorbell
= MHI_DB_BRST_DISABLE
,
307 .offload_channel
= false,
308 .doorbell_mode_switch
= false,
310 .wake_capable
= false,
313 .name
= "QAIC_DEBUG",
318 .dir
= DMA_TO_DEVICE
,
319 .ee_mask
= MHI_CH_EE_AMSS
,
321 .doorbell
= MHI_DB_BRST_DISABLE
,
323 .offload_channel
= false,
324 .doorbell_mode_switch
= false,
326 .wake_capable
= false,
329 .name
= "QAIC_DEBUG",
334 .dir
= DMA_FROM_DEVICE
,
335 .ee_mask
= MHI_CH_EE_AMSS
,
337 .doorbell
= MHI_DB_BRST_DISABLE
,
339 .offload_channel
= false,
340 .doorbell_mode_switch
= false,
342 .wake_capable
= false,
345 .name
= "QAIC_TIMESYNC",
350 .dir
= DMA_TO_DEVICE
,
351 .ee_mask
= MHI_CH_EE_SBL
,
353 .doorbell
= MHI_DB_BRST_DISABLE
,
355 .offload_channel
= false,
356 .doorbell_mode_switch
= false,
358 .wake_capable
= false,
361 .name
= "QAIC_TIMESYNC",
366 .dir
= DMA_FROM_DEVICE
,
367 .ee_mask
= MHI_CH_EE_SBL
,
369 .doorbell
= MHI_DB_BRST_DISABLE
,
371 .offload_channel
= false,
372 .doorbell_mode_switch
= false,
374 .wake_capable
= false,
377 .name
= "QAIC_TIMESYNC_PERIODIC",
382 .dir
= DMA_TO_DEVICE
,
383 .ee_mask
= MHI_CH_EE_AMSS
,
385 .doorbell
= MHI_DB_BRST_DISABLE
,
387 .offload_channel
= false,
388 .doorbell_mode_switch
= false,
390 .wake_capable
= false,
393 .name
= "QAIC_TIMESYNC_PERIODIC",
398 .dir
= DMA_FROM_DEVICE
,
399 .ee_mask
= MHI_CH_EE_AMSS
,
401 .doorbell
= MHI_DB_BRST_DISABLE
,
403 .offload_channel
= false,
404 .doorbell_mode_switch
= false,
406 .wake_capable
= false,
410 static struct mhi_event_config aic100_events
[] = {
413 .irq_moderation_ms
= 0,
417 .mode
= MHI_DB_BRST_DISABLE
,
418 .data_type
= MHI_ER_CTRL
,
419 .hardware_event
= false,
420 .client_managed
= false,
421 .offload_channel
= false,
425 static struct mhi_controller_config aic100_config
= {
427 .timeout_ms
= 0, /* controlled by mhi_timeout */
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,
437 static int mhi_read_reg(struct mhi_controller
*mhi_cntrl
, void __iomem
*addr
, u32
*out
)
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.
448 if (addr
- mhi_cntrl
->regs
== 0x224) {
453 tmp
= readl_relaxed(addr
);
462 static void mhi_write_reg(struct mhi_controller
*mhi_cntrl
, void __iomem
*addr
, u32 val
)
464 writel_relaxed(val
, addr
);
467 static int mhi_runtime_get(struct mhi_controller
*mhi_cntrl
)
472 static void mhi_runtime_put(struct mhi_controller
*mhi_cntrl
)
476 static void mhi_status_cb(struct mhi_controller
*mhi_cntrl
, enum mhi_callback reason
)
478 struct qaic_device
*qdev
= pci_get_drvdata(to_pci_dev(mhi_cntrl
->cntrl_dev
));
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
);
488 static int mhi_reset_and_async_power_up(struct mhi_controller
*mhi_cntrl
)
494 /* Reset the device to bring the device in PBL EE */
495 mhi_soc_reset(mhi_cntrl
);
498 * Keep checking the execution environment(EE) after every 1 second
503 current_ee
= mhi_get_exec_env(mhi_cntrl
);
504 } while (current_ee
!= MHI_EE_PBL
&& time_sec
++ <= MAX_RESET_TIME_SEC
);
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
);
515 struct mhi_controller
*qaic_mhi_register_controller(struct pci_dev
*pci_dev
, void __iomem
*mhi_bar
,
516 int mhi_irq
, bool shared_msi
)
518 struct mhi_controller
*mhi_cntrl
;
521 mhi_cntrl
= devm_kzalloc(&pci_dev
->dev
, sizeof(*mhi_cntrl
), GFP_KERNEL
);
523 return ERR_PTR(-ENOMEM
);
525 mhi_cntrl
->cntrl_dev
= &pci_dev
->dev
;
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
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
);
545 return ERR_PTR(-ENOMEM
);
547 mhi_cntrl
->irq
[0] = mhi_irq
;
549 if (shared_msi
) /* MSI shared with data path, no IRQF_NO_SUSPEND */
550 mhi_cntrl
->irq_flags
= IRQF_SHARED
;
552 mhi_cntrl
->fw_image
= "qcom/aic100/sbl.bin";
554 /* use latest configured timeout */
555 aic100_config
.timeout_ms
= mhi_timeout_ms
;
556 ret
= mhi_register_controller(mhi_cntrl
, &aic100_config
);
558 pci_err(pci_dev
, "mhi_register_controller failed %d\n", ret
);
562 ret
= mhi_prepare_for_power_up(mhi_cntrl
);
564 pci_err(pci_dev
, "mhi_prepare_for_power_up failed %d\n", ret
);
565 goto prepare_power_up_fail
;
568 ret
= mhi_async_power_up(mhi_cntrl
);
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.
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
);
579 pci_err(pci_dev
, "mhi_async_power_up failed %d\n", ret
);
586 mhi_unprepare_after_power_down(mhi_cntrl
);
587 prepare_power_up_fail
:
588 mhi_unregister_controller(mhi_cntrl
);
592 void qaic_mhi_free_controller(struct mhi_controller
*mhi_cntrl
, bool link_up
)
594 mhi_power_down(mhi_cntrl
, link_up
);
595 mhi_unprepare_after_power_down(mhi_cntrl
);
596 mhi_unregister_controller(mhi_cntrl
);
599 void qaic_mhi_start_reset(struct mhi_controller
*mhi_cntrl
)
601 mhi_power_down(mhi_cntrl
, true);
604 void qaic_mhi_reset_done(struct mhi_controller
*mhi_cntrl
)
606 struct pci_dev
*pci_dev
= container_of(mhi_cntrl
->cntrl_dev
, struct pci_dev
, dev
);
609 ret
= mhi_async_power_up(mhi_cntrl
);
611 pci_err(pci_dev
, "mhi_async_power_up failed after reset %d\n", ret
);