xref: /linux/drivers/accel/qaic/mhi_controller.c (revision 2b0cfa6e49566c8fa6759734cf821aa6e8271a9e)
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 		.num = 21,
362 		.name = "QAIC_TIMESYNC",
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 		.num = 23,
394 		.name = "QAIC_TIMESYNC_PERIODIC",
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 }
613