xref: /wlan-dirver/qca-wifi-host-cmn/hif/src/usb/if_usb.c (revision 45a38684b07295822dc8eba39e293408f203eec8)
1 /*
2  * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for
5  * any purpose with or without fee is hereby granted, provided that the
6  * above copyright notice and this permission notice appear in all
7  * copies.
8  *
9  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16  * PERFORMANCE OF THIS SOFTWARE.
17  */
18 
19 #include <linux/usb.h>
20 #include <linux/usb/hcd.h>
21 #include "if_usb.h"
22 #include "hif_usb_internal.h"
23 #include "target_type.h"		/* TARGET_TYPE_ */
24 #include "regtable_usb.h"
25 #include "ol_fw.h"
26 #include "hif_debug.h"
27 #include "epping_main.h"
28 #include "hif_main.h"
29 #include "usb_api.h"
30 #ifdef CONFIG_PLD_USB_CNSS
31 #include "pld_common.h"
32 #endif
33 
34 #define DELAY_FOR_TARGET_READY 200	/* 200ms */
35 
36 /* Save memory addresses where we save FW ram dump, and then we could obtain
37  * them by symbol table.
38  */
39 uint32_t fw_stack_addr;
40 void *fw_ram_seg_addr[FW_RAM_SEG_CNT];
41 
42 
43 
44 static int hif_usb_unload_dev_num = -1;
45 struct hif_usb_softc *g_usb_sc;
46 
47 /**
48  * hif_usb_diag_write_cold_reset() - reset SOC by sending a diag command
49  * @scn: pointer to ol_softc structure
50  *
51  * Return: QDF_STATUS_SUCCESS if success else an appropriate QDF_STATUS error
52  */
53 static inline QDF_STATUS
54 hif_usb_diag_write_cold_reset(struct hif_softc *scn)
55 {
56 	struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(scn);
57 	struct hif_target_info *tgt_info = &scn->target_info;
58 
59 	/* For Genoa, chip-reset is handled in CNSS driver */
60 	if (tgt_info->target_type == TARGET_TYPE_QCN7605)
61 		return QDF_STATUS_SUCCESS;
62 
63 	HIF_DBG("%s: resetting SOC", __func__);
64 
65 	return hif_diag_write_access(hif_hdl,
66 				(ROME_USB_SOC_RESET_CONTROL_COLD_RST_LSB |
67 				ROME_USB_RTC_SOC_BASE_ADDRESS),
68 				SOC_RESET_CONTROL_COLD_RST_SET(1));
69 }
70 
71 /**
72  * hif_usb_procfs_init() - create init procfs
73  * @scn: pointer to hif_usb_softc structure
74  *
75  * Return: int 0 if success else an appropriate error number
76  */
77 static int
78 hif_usb_procfs_init(struct hif_softc *scn)
79 {
80 	int ret = 0;
81 
82 	HIF_ENTER();
83 
84 	if (athdiag_procfs_init(scn) != 0) {
85 		HIF_ERROR("athdiag_procfs_init failed");
86 		ret = A_ERROR;
87 	}
88 
89 	scn->athdiag_procfs_inited = true;
90 
91 	HIF_EXIT();
92 	return ret;
93 }
94 
95 /**
96  * hif_nointrs(): disable IRQ
97  * @scn: pointer to struct hif_softc
98  *
99  * This function stops interrupt(s)
100  *
101  * Return: none
102  */
103 void hif_usb_nointrs(struct hif_softc *scn)
104 {
105 
106 }
107 
108 /**
109  * hif_usb_reboot() - called at reboot time to reset WLAN SOC
110  * @nb: pointer to notifier_block registered during register_reboot_notifier
111  * @val: code indicating reboot reason
112  * @v: unused pointer
113  *
114  * Return: int 0 if success else an appropriate error number
115  */
116 static int hif_usb_reboot(struct notifier_block *nb, unsigned long val,
117 				void *v)
118 {
119 	struct hif_usb_softc *sc;
120 
121 	HIF_ENTER();
122 	sc = container_of(nb, struct hif_usb_softc, reboot_notifier);
123 	/* do cold reset */
124 	hif_usb_diag_write_cold_reset(HIF_GET_SOFTC(sc));
125 	HIF_EXIT();
126 	return NOTIFY_DONE;
127 }
128 
129 /**
130  * hif_usb_disable_lpm() - Disable lpm feature of usb2.0
131  * @udev: pointer to usb_device for which LPM is to be disabled
132  *
133  * LPM needs to be disabled to avoid usb2.0 probe timeout
134  *
135  * Return: int 0 if success else an appropriate error number
136  */
137 static int hif_usb_disable_lpm(struct usb_device *udev)
138 {
139 	struct usb_hcd *hcd;
140 	int ret = -EPERM;
141 
142 	HIF_ENTER();
143 
144 	if (!udev || !udev->bus) {
145 		HIF_ERROR("Invalid input parameters");
146 		goto exit;
147 	}
148 
149 	hcd = bus_to_hcd(udev->bus);
150 	if (udev->usb2_hw_lpm_enabled) {
151 		if (hcd->driver->set_usb2_hw_lpm) {
152 			ret = hcd->driver->set_usb2_hw_lpm(hcd, udev, false);
153 			if (!ret) {
154 				udev->usb2_hw_lpm_enabled = false;
155 				udev->usb2_hw_lpm_capable = false;
156 				HIF_TRACE("%s: LPM is disabled", __func__);
157 			} else {
158 				HIF_TRACE("%s: Fail to disable LPM",
159 						__func__);
160 			}
161 		} else {
162 			HIF_TRACE("%s: hcd doesn't support LPM",
163 						__func__);
164 		}
165 	} else {
166 		HIF_TRACE("%s: LPM isn't enabled", __func__);
167 	}
168 exit:
169 	HIF_EXIT();
170 	return ret;
171 }
172 
173 /**
174  * hif_usb_enable_bus() - enable usb bus
175  * @ol_sc: hif_softc struct
176  * @dev: device pointer
177  * @bdev: bus dev pointer
178  * @bid: bus id pointer
179  * @type: enum hif_enable_type such as HIF_ENABLE_TYPE_PROBE
180  *
181  * Return: QDF_STATUS_SUCCESS on success and error QDF status on failure
182  */
183 QDF_STATUS hif_usb_enable_bus(struct hif_softc *scn,
184 			struct device *dev, void *bdev,
185 			const struct hif_bus_id *bid,
186 			enum hif_enable_type type)
187 
188 {
189 	struct usb_interface *interface = (struct usb_interface *)bdev;
190 	struct usb_device_id *id = (struct usb_device_id *)bid;
191 	QDF_STATUS ret = QDF_STATUS_SUCCESS;
192 	struct hif_usb_softc *sc;
193 	struct usb_device *usbdev = interface_to_usbdev(interface);
194 	int vendor_id, product_id;
195 	struct hif_target_info *tgt_info;
196 	struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(scn);
197 	u32 hif_type;
198 	u32 target_type;
199 
200 	if (!scn) {
201 		HIF_ERROR("%s: hif_ctx is NULL", __func__);
202 		goto err_usb;
203 	}
204 
205 	sc = HIF_GET_USB_SOFTC(scn);
206 
207 	HIF_INFO("%s hif_softc %pK usbdev %pK interface %pK\n",
208 		__func__,
209 		scn,
210 		usbdev,
211 		interface);
212 
213 	vendor_id = qdf_le16_to_cpu(usbdev->descriptor.idVendor);
214 	product_id = qdf_le16_to_cpu(usbdev->descriptor.idProduct);
215 
216 	HIF_ERROR("%s: con_mode = 0x%x, vendor_id = 0x%x product_id = 0x%x",
217 		__func__, hif_get_conparam(scn), vendor_id, product_id);
218 
219 	sc->pdev = (void *)usbdev;
220 	sc->dev = &usbdev->dev;
221 	sc->devid = id->idProduct;
222 
223 	hif_get_device_type(product_id, 0, &hif_type, &target_type);
224 	tgt_info = hif_get_target_info_handle(hif_hdl);
225 	if (target_type == TARGET_TYPE_QCN7605)
226 		tgt_info->target_type = TARGET_TYPE_QCN7605;
227 
228 	/*
229 	 * For Genoa, skip set_configuration, since it is handled
230 	 * by CNSS driver.
231 	 */
232 	if (target_type != TARGET_TYPE_QCN7605) {
233 		usb_get_dev(usbdev);
234 		if ((usb_control_msg(usbdev, usb_sndctrlpipe(usbdev, 0),
235 				     USB_REQ_SET_CONFIGURATION, 0, 1, 0,
236 				     NULL, 0, HZ)) < 0) {
237 			HIF_ERROR("%s[%d]", __func__, __LINE__);
238 			goto err_usb;
239 		}
240 		usb_set_interface(usbdev, 0, 0);
241 		sc->reboot_notifier.notifier_call = hif_usb_reboot;
242 		register_reboot_notifier(&sc->reboot_notifier);
243 	}
244 
245 	/* disable lpm to avoid usb2.0 probe timeout */
246 	hif_usb_disable_lpm(usbdev);
247 
248 	/* params need to be added - TODO
249 	 * scn->enableuartprint = 1;
250 	 * scn->enablefwlog = 0;
251 	 * scn->max_no_of_peers = 1;
252 	 */
253 
254 	sc->interface = interface;
255 	if (hif_usb_device_init(sc) != QDF_STATUS_SUCCESS) {
256 		HIF_ERROR("ath: %s: hif_usb_device_init failed", __func__);
257 		goto err_reset;
258 	}
259 
260 	if (hif_usb_procfs_init(scn))
261 		goto err_reset;
262 
263 	hif_usb_unload_dev_num = usbdev->devnum;
264 	g_usb_sc = sc;
265 	HIF_EXIT();
266 	return QDF_STATUS_SUCCESS;
267 
268 err_reset:
269 	hif_usb_diag_write_cold_reset(scn);
270 	g_usb_sc = NULL;
271 	hif_usb_unload_dev_num = -1;
272 	if (target_type != TARGET_TYPE_QCN7605)
273 		unregister_reboot_notifier(&sc->reboot_notifier);
274 err_usb:
275 	ret = QDF_STATUS_E_FAILURE;
276 	if (target_type != TARGET_TYPE_QCN7605)
277 		usb_put_dev(usbdev);
278 	return ret;
279 }
280 
281 
282 /**
283  * hif_usb_close(): close bus, delete hif_sc
284  * @ol_sc: soft_sc struct
285  *
286  * Return: none
287  */
288 void hif_usb_close(struct hif_softc *scn)
289 {
290 	g_usb_sc = NULL;
291 }
292 
293 /**
294  * hif_usb_disable_bus(): This function disables usb bus
295  * @hif_ctx: pointer to struct hif_softc
296  *
297  * Return: none
298  */
299 void hif_usb_disable_bus(struct hif_softc *hif_ctx)
300 {
301 	struct hif_usb_softc *sc = HIF_GET_USB_SOFTC(hif_ctx);
302 	struct usb_interface *interface = sc->interface;
303 	struct usb_device *udev = interface_to_usbdev(interface);
304 	struct hif_target_info *tgt_info = &hif_ctx->target_info;
305 
306 	HIF_TRACE("%s: trying to remove hif_usb!", __func__);
307 
308 	/* disable lpm to avoid following cold reset will
309 	 * cause xHCI U1/U2 timeout
310 	 */
311 	if (tgt_info->target_type != TARGET_TYPE_QCN7605)
312 		usb_disable_lpm(udev);
313 
314 	/* wait for disable lpm */
315 	set_current_state(TASK_INTERRUPTIBLE);
316 	schedule_timeout(msecs_to_jiffies(DELAY_FOR_TARGET_READY));
317 	set_current_state(TASK_RUNNING);
318 
319 	/* do cold reset */
320 	hif_usb_diag_write_cold_reset(hif_ctx);
321 
322 	if (g_usb_sc->suspend_state)
323 		hif_bus_resume(GET_HIF_OPAQUE_HDL(hif_ctx));
324 
325 	if (tgt_info->target_type != TARGET_TYPE_QCN7605) {
326 		unregister_reboot_notifier(&sc->reboot_notifier);
327 		usb_put_dev(udev);
328 	}
329 
330 	hif_usb_device_deinit(sc);
331 
332 	HIF_TRACE("%s hif_usb removed !!!!!!", __func__);
333 }
334 
335 /**
336  * hif_usb_bus_suspend() - suspend the bus
337  * @hif_ctx: hif_ctx
338  *
339  * This function suspends the bus, but usb doesn't need to suspend.
340  * Therefore just remove all the pending urb transactions
341  *
342  * Return: 0 for success and non-zero for failure
343  */
344 int hif_usb_bus_suspend(struct hif_softc *hif_ctx)
345 {
346 	struct hif_usb_softc *sc = HIF_GET_USB_SOFTC(hif_ctx);
347 	struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(hif_ctx);
348 
349 	HIF_ENTER();
350 	sc->suspend_state = 1;
351 	usb_hif_flush_all(device);
352 	HIF_EXIT();
353 	return 0;
354 }
355 
356 /**
357  * hif_usb_bus_resume() - hif resume API
358  * @hif_ctx: struct hif_opaque_softc
359  *
360  * This function resumes the bus. but usb doesn't need to resume.
361  * Post recv urbs for RX data pipe
362  *
363  * Return: 0 for success and non-zero for failure
364  */
365 int hif_usb_bus_resume(struct hif_softc *hif_ctx)
366 {
367 	struct hif_usb_softc *sc = HIF_GET_USB_SOFTC(hif_ctx);
368 	struct HIF_DEVICE_USB *device = HIF_GET_USB_DEVICE(hif_ctx);
369 
370 	HIF_ENTER();
371 	sc->suspend_state = 0;
372 	usb_hif_start_recv_pipes(device);
373 
374 	HIF_EXIT();
375 	return 0;
376 }
377 
378 /**
379  * hif_usb_bus_reset_resume() - resume the bus after reset
380  * @scn: struct hif_opaque_softc
381  *
382  * This function is called to tell the driver that USB device has been resumed
383  * and it has also been reset. The driver should redo any necessary
384  * initialization. This function resets WLAN SOC.
385  *
386  * Return: int 0 for success, non zero for failure
387  */
388 int hif_usb_bus_reset_resume(struct hif_softc *hif_ctx)
389 {
390 	int ret = 0;
391 
392 	HIF_ENTER();
393 	if (hif_usb_diag_write_cold_reset(hif_ctx) != QDF_STATUS_SUCCESS)
394 		ret = 1;
395 
396 	HIF_EXIT();
397 	return ret;
398 }
399 
400 /**
401  * hif_usb_open()- initialization routine for usb bus
402  * @ol_sc: ol_sc
403  * @bus_type: bus type
404  *
405  * Return: QDF_STATUS_SUCCESS on success and error QDF status on failure
406  */
407 QDF_STATUS hif_usb_open(struct hif_softc *hif_ctx,
408 		enum qdf_bus_type bus_type)
409 {
410 	hif_ctx->bus_type = bus_type;
411 	return QDF_STATUS_SUCCESS;
412 }
413 
414 /**
415  * hif_usb_disable_isr(): disable isr
416  * @hif_ctx: struct hif_softc
417  *
418  * Return: void
419  */
420 void hif_usb_disable_isr(struct hif_softc *hif_ctx)
421 {
422 	/* TODO */
423 }
424 
425 /**
426  * hif_usb_reg_tbl_attach()- attach hif, target register tables
427  * @scn: pointer to ol_softc structure
428  *
429  * Attach host and target register tables based on target_type, target_version
430  *
431  * Return: none
432  */
433 void hif_usb_reg_tbl_attach(struct hif_softc *scn)
434 {
435 	u_int32_t hif_type, target_type;
436 	int32_t ret = 0;
437 	uint32_t chip_id;
438 	QDF_STATUS rv;
439 	struct hif_target_info *tgt_info = &scn->target_info;
440 	struct hif_opaque_softc *hif_hdl = GET_HIF_OPAQUE_HDL(scn);
441 
442 	if (!scn->hostdef && !scn->targetdef) {
443 		switch (tgt_info->target_type) {
444 		case TARGET_TYPE_AR6320:
445 			switch (tgt_info->target_version) {
446 			case AR6320_REV1_VERSION:
447 			case AR6320_REV1_1_VERSION:
448 			case AR6320_REV1_3_VERSION:
449 				hif_type = HIF_TYPE_AR6320;
450 				target_type = TARGET_TYPE_AR6320;
451 				break;
452 			case AR6320_REV2_1_VERSION:
453 			case AR6320_REV3_VERSION:
454 			case QCA9377_REV1_1_VERSION:
455 			case QCA9379_REV1_VERSION:
456 				hif_type = HIF_TYPE_AR6320V2;
457 				target_type = TARGET_TYPE_AR6320V2;
458 				break;
459 			default:
460 				ret = -1;
461 				break;
462 			}
463 			break;
464 		default:
465 			ret = -1;
466 			break;
467 		}
468 
469 		if (ret)
470 			return;
471 
472 		/* assign target register table if we find
473 		 * corresponding type
474 		 */
475 		hif_register_tbl_attach(scn, hif_type);
476 		target_register_tbl_attach(scn, target_type);
477 		/* read the chip revision*/
478 		rv = hif_diag_read_access(hif_hdl,
479 					(CHIP_ID_ADDRESS |
480 					RTC_SOC_BASE_ADDRESS),
481 					&chip_id);
482 		if (rv != QDF_STATUS_SUCCESS) {
483 			HIF_ERROR("%s: get chip id val (%d)", __func__,
484 				rv);
485 		}
486 		tgt_info->target_revision =
487 				CHIP_ID_REVISION_GET(chip_id);
488 	}
489 }
490 
491 /**
492  * hif_usb_get_hw_info()- attach register table for USB
493  * @hif_ctx: pointer to hif_softc structure
494 
495  * This function is used to attach the host and target register tables.
496  * Ideally, we should not attach register tables as a part of this function.
497  * There is scope of cleanup to move register table attach during
498  * initialization for USB bus.
499  *
500  * The reason we are doing register table attach for USB here is that, it relies
501  * on target_info->target_type and target_info->target_version,
502  * which get populated during bmi_firmware_download. "hif_get_fw_info" is the
503  * only initialization related call into HIF there after.
504  *
505  * To fix this, we can move the "get target info, functionality currently in
506  * bmi_firmware_download into hif initialization functions. This change will
507  * affect all buses. Can be taken up as a part of convergence.
508  *
509  * Return: none
510  */
511 void hif_usb_get_hw_info(struct hif_softc *hif_ctx)
512 {
513 	hif_usb_reg_tbl_attach(hif_ctx);
514 }
515 
516 #if defined(CONFIG_PLD_USB_CNSS) && !defined(CONFIG_BYPASS_QMI)
517 /**
518  * hif_bus_configure() - configure the bus
519  * @scn: pointer to the hif context.
520  *
521  * return: 0 for success. nonzero for failure.
522  */
523 int hif_usb_bus_configure(struct hif_softc *scn)
524 {
525 	struct pld_wlan_enable_cfg cfg;
526 	enum pld_driver_mode mode;
527 	uint32_t con_mode = hif_get_conparam(scn);
528 
529 	if (QDF_GLOBAL_FTM_MODE == con_mode)
530 		mode = PLD_FTM;
531 	else if (QDF_GLOBAL_COLDBOOT_CALIB_MODE == con_mode)
532 		mode = PLD_COLDBOOT_CALIBRATION;
533 	else if (QDF_IS_EPPING_ENABLED(con_mode))
534 		mode = PLD_EPPING;
535 	else
536 		mode = PLD_MISSION;
537 
538 	return pld_wlan_enable(scn->qdf_dev->dev, &cfg, mode);
539 }
540 #else
541 /**
542  * hif_bus_configure() - configure the bus
543  * @scn: pointer to the hif context.
544  *
545  * return: 0 for success. nonzero for failure.
546  */
547 int hif_usb_bus_configure(struct hif_softc *scn)
548 {
549 	return 0;
550 }
551 #endif
552 
553 /**
554  * hif_usb_irq_enable() - hif_usb_irq_enable
555  * @scn: hif_softc
556  * @ce_id: ce_id
557  *
558  * Return: void
559  */
560 void hif_usb_irq_enable(struct hif_softc *scn, int ce_id)
561 {
562 }
563 
564 /**
565  * hif_usb_irq_disable() - hif_usb_irq_disable
566  * @scn: hif_softc
567  * @ce_id: ce_id
568  *
569  * Return: void
570  */
571 void hif_usb_irq_disable(struct hif_softc *scn, int ce_id)
572 {
573 }
574 
575 /**
576  * hif_usb_shutdown_bus_device() - This function shuts down the device
577  * @scn: hif opaque pointer
578  *
579  * Return: void
580  */
581 void hif_usb_shutdown_bus_device(struct hif_softc *scn)
582 {
583 }
584 
585 /**
586  * hif_trigger_dump() - trigger various dump cmd
587  * @scn: struct hif_opaque_softc
588  * @cmd_id: dump command id
589  * @start: start/stop dump
590  *
591  * Return: None
592  */
593 void hif_trigger_dump(struct hif_opaque_softc *scn, uint8_t cmd_id, bool start)
594 {
595 }
596 
597 /**
598  * hif_wlan_disable() - call the platform driver to disable wlan
599  * @scn: scn
600  *
601  * Return: void
602  */
603 void hif_wlan_disable(struct hif_softc *scn)
604 {
605 }
606 
607 /**
608  * hif_fw_assert_ramdump_pattern() - handle firmware assert with ramdump pattern
609  * @sc: pointer to hif_usb_softc structure
610  *
611  * Return: void
612  */
613 
614 void hif_fw_assert_ramdump_pattern(struct hif_usb_softc *sc)
615 {
616 	uint32_t *reg, pattern, i = 0;
617 	uint32_t len;
618 	uint8_t *data;
619 	uint8_t *ram_ptr = NULL;
620 	char *fw_ram_seg_name[FW_RAM_SEG_CNT] = {"DRAM", "IRAM", "AXI"};
621 	size_t fw_ram_reg_size[FW_RAM_SEG_CNT] = {
622 				  FW_RAMDUMP_DRAMSIZE,
623 				  FW_RAMDUMP_IRAMSIZE,
624 				  FW_RAMDUMP_AXISIZE };
625 
626 	data = sc->fw_data;
627 	len = sc->fw_data_len;
628 	pattern = *((uint32_t *) data);
629 
630 	qdf_assert(sc->ramdump_index < FW_RAM_SEG_CNT);
631 	i = sc->ramdump_index;
632 	reg = (uint32_t *) (data + 4);
633 	if (sc->fw_ram_dumping == 0) {
634 		sc->fw_ram_dumping = 1;
635 		HIF_ERROR("Firmware %s dump:\n", fw_ram_seg_name[i]);
636 		sc->ramdump[i] =
637 			qdf_mem_malloc(sizeof(struct fw_ramdump) +
638 					fw_ram_reg_size[i]);
639 		if (!sc->ramdump[i])
640 			QDF_BUG(0);
641 
642 		(sc->ramdump[i])->mem = (uint8_t *) (sc->ramdump[i] + 1);
643 		fw_ram_seg_addr[i] = (sc->ramdump[i])->mem;
644 		HIF_ERROR("FW %s start addr = %#08x\n",
645 			fw_ram_seg_name[i], *reg);
646 		HIF_ERROR("Memory addr for %s = %pK\n",
647 			fw_ram_seg_name[i],
648 			(sc->ramdump[i])->mem);
649 		(sc->ramdump[i])->start_addr = *reg;
650 		(sc->ramdump[i])->length = 0;
651 	}
652 	reg++;
653 	ram_ptr = (sc->ramdump[i])->mem + (sc->ramdump[i])->length;
654 	(sc->ramdump[i])->length += (len - 8);
655 	if (sc->ramdump[i]->length <= fw_ram_reg_size[i]) {
656 		qdf_mem_copy(ram_ptr, (uint8_t *) reg, len - 8);
657 	} else {
658 		HIF_ERROR("memory copy overlap\n");
659 		QDF_BUG(0);
660 	}
661 
662 	if (pattern == FW_RAMDUMP_END_PATTERN) {
663 		HIF_ERROR("%s memory size = %d\n", fw_ram_seg_name[i],
664 				(sc->ramdump[i])->length);
665 		if (i == (FW_RAM_SEG_CNT - 1))
666 			QDF_BUG(0);
667 
668 		sc->ramdump_index++;
669 		sc->fw_ram_dumping = 0;
670 	}
671 }
672 
673 /**
674  * hif_usb_ramdump_handler(): dump bus debug registers
675  * @scn: struct hif_opaque_softc
676  *
677  * This function is to receive information of firmware crash dump, and
678  * save it in host memory. It consists of 5 parts: registers, call stack,
679  * DRAM dump, IRAM dump, and AXI dump, and they are reported to host in order.
680  *
681  * registers: wrapped in a USB packet by starting as FW_ASSERT_PATTERN and
682  *            60 registers.
683  * call stack: wrapped in multiple USB packets, and each of them starts as
684  *             FW_REG_PATTERN and contains multiple double-words. The tail
685  *             of the last packet is FW_REG_END_PATTERN.
686  * DRAM dump: wrapped in multiple USB pakcets, and each of them start as
687  *            FW_RAMDUMP_PATTERN and contains multiple double-wors. The tail
688  *            of the last packet is FW_RAMDUMP_END_PATTERN;
689  * IRAM dump and AXI dump are with the same format as DRAM dump.
690  *
691  * Return: 0 for success or error code
692  */
693 
694 void hif_usb_ramdump_handler(struct hif_opaque_softc *scn)
695 {
696 	uint32_t *reg, pattern, i, start_addr = 0;
697 	uint32_t len;
698 	uint8_t *data;
699 	uint8_t str_buf[128];
700 	uint32_t remaining;
701 	struct hif_usb_softc *sc = HIF_GET_USB_SOFTC(scn);
702 	struct hif_softc *hif_ctx = HIF_GET_SOFTC(scn);
703 	struct hif_target_info *tgt_info = &hif_ctx->target_info;
704 
705 	data = sc->fw_data;
706 	len = sc->fw_data_len;
707 	pattern = *((uint32_t *) data);
708 
709 	if (pattern == FW_ASSERT_PATTERN) {
710 		HIF_ERROR("Firmware crash detected...\n");
711 		HIF_ERROR("target_type: %d.target_version %d. target_revision%d.",
712 			tgt_info->target_type,
713 			tgt_info->target_version,
714 			tgt_info->target_revision);
715 
716 		reg = (uint32_t *) (data + 4);
717 		print_hex_dump(KERN_DEBUG, " ", DUMP_PREFIX_OFFSET, 16, 4, reg,
718 				min_t(uint32_t, len - 4, FW_REG_DUMP_CNT * 4),
719 				false);
720 		sc->fw_ram_dumping = 0;
721 
722 	} else if (pattern == FW_REG_PATTERN) {
723 		reg = (uint32_t *) (data + 4);
724 		start_addr = *reg++;
725 		if (sc->fw_ram_dumping == 0) {
726 			qdf_nofl_err("Firmware stack dump:");
727 			sc->fw_ram_dumping = 1;
728 			fw_stack_addr = start_addr;
729 		}
730 		remaining = len - 8;
731 		/* len is in byte, but it's printed in double-word. */
732 		for (i = 0; i < (len - 8); i += 16) {
733 			if ((*reg == FW_REG_END_PATTERN) && (i == len - 12)) {
734 				sc->fw_ram_dumping = 0;
735 				qdf_nofl_err("Stack start address = %#08x",
736 					     fw_stack_addr);
737 				break;
738 			}
739 			hex_dump_to_buffer(reg, remaining, 16, 4, str_buf,
740 						sizeof(str_buf), false);
741 			qdf_nofl_err("%#08x: %s", start_addr + i, str_buf);
742 			remaining -= 16;
743 			reg += 4;
744 		}
745 	} else if ((!sc->enable_self_recovery) &&
746 			((pattern & FW_RAMDUMP_PATTERN_MASK) ==
747 						FW_RAMDUMP_PATTERN)) {
748 		hif_fw_assert_ramdump_pattern(sc);
749 	}
750 }
751 
752 #ifndef QCA_WIFI_3_0
753 /**
754  * hif_check_fw_reg(): hif_check_fw_reg
755  * @scn: scn
756  * @state:
757  *
758  * Return: int
759  */
760 int hif_check_fw_reg(struct hif_opaque_softc *scn)
761 {
762 	return 0;
763 }
764 #endif
765 
766 /**
767  * hif_usb_needs_bmi() - return true if the soc needs bmi through the driver
768  * @scn: hif context
769  *
770  * Return: true if soc needs driver bmi otherwise false
771  */
772 bool hif_usb_needs_bmi(struct hif_softc *scn)
773 {
774 	struct hif_target_info *tgt_info = &scn->target_info;
775 
776 	/* BMI is not supported in Genoa */
777 	if (tgt_info->target_type == TARGET_TYPE_QCN7605)
778 		return false;
779 
780 	return true;
781 }
782