xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/nxp/mlinux/moal_sdio_mmc.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /** @file moal_sdio_mmc.c
2  *
3  *  @brief This file contains SDIO MMC IF (interface) module
4  *  related functions.
5  *
6  *
7  * Copyright 2008-2022 NXP
8  *
9  * This software file (the File) is distributed by NXP
10  * under the terms of the GNU General Public License Version 2, June 1991
11  * (the License).  You may use, redistribute and/or modify the File in
12  * accordance with the terms and conditions of the License, a copy of which
13  * is available by writing to the Free Software Foundation, Inc.,
14  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
15  * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
16  *
17  * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
19  * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
20  * this warranty disclaimer.
21  *
22  */
23 /****************************************************
24 Change log:
25 	02/25/09: Initial creation -
26 		  This file supports SDIO MMC only
27 ****************************************************/
28 
29 #include <linux/firmware.h>
30 
31 #include "moal_sdio.h"
32 
33 /** define nxp vendor id */
34 #define NXP_VENDOR_ID 0x0471
35 #define MRVL_VENDOR_ID 0x02df
36 
37 /********************************************************
38 		Local Variables
39 ********************************************************/
40 /* moal interface ops */
41 static moal_if_ops sdiommc_ops;
42 /********************************************************
43 		Global Variables
44 ********************************************************/
45 
46 #ifdef SD8887
47 /** Device ID for SD8887 */
48 #define SD_DEVICE_ID_8887 (0x9135)
49 #endif
50 #ifdef SD8801
51 /** Device ID for SD8801 FN1 */
52 #define SD_DEVICE_ID_8801 (0x9139)
53 #endif
54 #ifdef SD8897
55 /** Device ID for SD8897 */
56 #define SD_DEVICE_ID_8897 (0x912d)
57 #endif
58 #ifdef SD8977
59 /** Device ID for SD8977 */
60 #define SD_DEVICE_ID_8977 (0x9145)
61 #endif
62 #ifdef SD8978
63 /** Device ID for SD8978 */
64 #define SD_DEVICE_ID_8978 (0x9159)
65 #endif
66 #ifdef SD8997
67 /** Device ID for SD8997 */
68 #define SD_DEVICE_ID_8997 (0x9141)
69 #endif
70 #ifdef SD8987
71 /** Device ID for SD8987 */
72 #define SD_DEVICE_ID_8987 (0x9149)
73 #endif
74 #ifdef SD9098
75 /** Device ID for SD9098 */
76 #define SD_DEVICE_ID_9098_FN1 (0x914D)
77 /** Device ID for SD9098 */
78 #define SD_DEVICE_ID_9098_FN2 (0x914E)
79 #endif
80 #ifdef SD9097
81 /** Device ID for SD9097 */
82 #define SD_DEVICE_ID_9097 (0x9155)
83 #endif
84 #ifdef SD9177
85 /** Device ID for SD9177 */
86 #define SD_DEVICE_ID_9177 (0x0205)
87 #endif
88 #ifdef SDNW62X
89 /** Device ID for SDNW62X */
90 #define SD_DEVICE_ID_NW62X (0x020D)
91 #endif
92 
93 /** WLAN IDs */
94 static const struct sdio_device_id wlan_ids[] = {
95 #ifdef SD8887
96 	{SDIO_DEVICE(MRVL_VENDOR_ID, SD_DEVICE_ID_8887)},
97 #endif
98 #ifdef SD8801
99 	{SDIO_DEVICE(MRVL_VENDOR_ID, SD_DEVICE_ID_8801)},
100 #endif
101 #ifdef SD8897
102 	{SDIO_DEVICE(MRVL_VENDOR_ID, SD_DEVICE_ID_8897)},
103 #endif
104 #ifdef SD8977
105 	{SDIO_DEVICE(MRVL_VENDOR_ID, SD_DEVICE_ID_8977)},
106 #endif
107 #ifdef SD8978
108 	{SDIO_DEVICE(MRVL_VENDOR_ID, SD_DEVICE_ID_8978)},
109 #endif
110 #ifdef SD8997
111 	{SDIO_DEVICE(MRVL_VENDOR_ID, SD_DEVICE_ID_8997)},
112 #endif
113 #ifdef SD8987
114 	{SDIO_DEVICE(MRVL_VENDOR_ID, SD_DEVICE_ID_8987)},
115 #endif
116 #ifdef SD9098
117 	{SDIO_DEVICE(MRVL_VENDOR_ID, SD_DEVICE_ID_9098_FN1)},
118 	{SDIO_DEVICE(MRVL_VENDOR_ID, SD_DEVICE_ID_9098_FN2)},
119 #endif
120 #ifdef SD9097
121 	{SDIO_DEVICE(MRVL_VENDOR_ID, SD_DEVICE_ID_9097)},
122 #endif
123 #ifdef SD9177
124 	{SDIO_DEVICE(NXP_VENDOR_ID, SD_DEVICE_ID_9177)},
125 #endif
126 #ifdef SDNW62X
127 	{SDIO_DEVICE(NXP_VENDOR_ID, SD_DEVICE_ID_NW62X)},
128 #endif
129 	{},
130 };
131 
132 int woal_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id);
133 void woal_sdio_remove(struct sdio_func *func);
134 #ifdef SDIO
135 static void woal_sdiommc_reg_dbg(pmoal_handle handle);
136 #endif
137 
138 #ifdef SDIO_SUSPEND_RESUME
139 #ifdef MMC_PM_KEEP_POWER
140 int woal_sdio_suspend(struct device *dev);
141 int woal_sdio_resume(struct device *dev);
142 
143 static struct dev_pm_ops wlan_sdio_pm_ops = {
144 	.suspend = woal_sdio_suspend,
145 	.resume = woal_sdio_resume,
146 };
147 
148 void woal_sdio_shutdown(struct device *dev);
149 #endif
150 #endif
151 
152 // clang-format off
153 static struct sdio_driver REFDATA wlan_sdio = {
154 	.name = "wlan_sdio",
155 	.id_table = wlan_ids,
156 	.probe = woal_sdio_probe,
157 	.remove = woal_sdio_remove,
158 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 29)
159 	.drv = {
160 		.owner = THIS_MODULE,
161 #ifdef SDIO_SUSPEND_RESUME
162 #ifdef MMC_PM_KEEP_POWER
163 		.pm = &wlan_sdio_pm_ops,
164 		.shutdown = woal_sdio_shutdown,
165 #endif
166 #endif
167 
168 	}
169 #else
170 #ifdef SDIO_SUSPEND_RESUME
171 #ifdef MMC_PM_KEEP_POWER
172 	.drv = {
173 		.pm = &wlan_sdio_pm_ops,
174 		.shutdown = woal_sdio_shutdown,
175 	}
176 #endif
177 #endif
178 #endif
179 };
180 // clang-format on
181 
182 /********************************************************
183 		Local Functions
184 ********************************************************/
185 static void woal_sdiommc_dump_fw_info(moal_handle *phandle);
186 #if 0
187 /**  @brief This function dump the sdio register
188  *
189  *  @param handle   A Pointer to the moal_handle structure
190  *  @return         N/A
191  */
192 static void woal_dump_sdio_reg(moal_handle *handle)
193 {
194 	int ret = 0;
195 	t_u8 data, i;
196 	int fun0_reg[] = {0x05, 0x04};
197 	t_u8 array_size = 0;
198 #ifdef SD8897
199 	int fun1_reg_8897[] = {0x03, 0x04, 0x05, 0x06, 0x07, 0xC0, 0xC1};
200 #endif
201 	int fun1_reg_other[] = {0x03, 0x04, 0x05, 0x60, 0x61};
202 	int *fun1_reg = NULL;
203 
204 	for (i = 0; i < ARRAY_SIZE(fun0_reg); i++) {
205 		data = sdio_f0_readb(
206 			((struct sdio_mmc_card *)handle->card)->func,
207 			fun0_reg[i], &ret);
208 		PRINTM(MMSG, "fun0: reg 0x%02x=0x%02x ret=%d\n", fun0_reg[i],
209 		       data, ret);
210 	}
211 
212 #ifdef SD8897
213 	if (IS_SD8897(handle->card_type)) {
214 		fun1_reg = fun1_reg_8897;
215 		array_size = sizeof(fun1_reg_8897) / sizeof(int);
216 	} else {
217 #endif
218 		fun1_reg = fun1_reg_other;
219 		array_size = sizeof(fun1_reg_other) / sizeof(int);
220 #ifdef SD8897
221 	}
222 #endif
223 	for (i = 0; i < array_size; i++) {
224 		data = sdio_readb(((struct sdio_mmc_card *)handle->card)->func,
225 				  fun1_reg[i], &ret);
226 		PRINTM(MMSG, "fun1: reg 0x%02x=0x%02x ret=%d\n", fun1_reg[i],
227 		       data, ret);
228 	}
229 	return;
230 }
231 #endif
232 /********************************************************
233 		Global Functions
234 ********************************************************/
235 /**
236  *  @brief This function handles the interrupt.
237  *
238  *  @param func     A pointer to the sdio_func structure
239  *  @return         N/A
240  */
woal_sdio_interrupt(struct sdio_func * func)241 static void woal_sdio_interrupt(struct sdio_func *func)
242 {
243 	moal_handle *handle;
244 	struct sdio_mmc_card *card;
245 
246 	ENTER();
247 
248 	card = sdio_get_drvdata(func);
249 	if (!card || !card->handle) {
250 		PRINTM(MINFO,
251 		       "sdio_mmc_interrupt(func = %p) card or handle is NULL, card=%p\n",
252 		       func, card);
253 		LEAVE();
254 		return;
255 	}
256 	handle = card->handle;
257 	if (handle->surprise_removed == MTRUE) {
258 		LEAVE();
259 		return;
260 	}
261 	handle->main_state = MOAL_RECV_INT;
262 	PRINTM(MINFO, "*** IN SDIO IRQ ***\n");
263 	PRINTM(MINTR, "*\n");
264 
265 	/* call mlan_interrupt to read int status */
266 	mlan_interrupt(0, handle->pmlan_adapter);
267 #ifdef SDIO_SUSPEND_RESUME
268 	if (handle->is_suspended) {
269 		PRINTM(MINTR, "Receive interrupt in hs_suspended\n");
270 		LEAVE();
271 		return;
272 	}
273 #endif
274 	handle->main_state = MOAL_START_MAIN_PROCESS;
275 	/* Call MLAN main process */
276 	mlan_main_process(handle->pmlan_adapter);
277 	handle->main_state = MOAL_END_MAIN_PROCESS;
278 	LEAVE();
279 }
280 
281 /**  @brief This function updates the card types
282  *
283  *  @param handle   A Pointer to the moal_handle structure
284  *  @param card     A Pointer to card
285  *
286  *  @return         N/A
287  */
woal_update_card_type(t_void * card)288 static t_u16 woal_update_card_type(t_void *card)
289 {
290 	struct sdio_mmc_card *cardp_sd = (struct sdio_mmc_card *)card;
291 	t_u16 card_type = 0;
292 
293 	/* Update card type */
294 #ifdef SD8887
295 	if (cardp_sd->func->device == SD_DEVICE_ID_8887) {
296 		card_type = CARD_TYPE_SD8887;
297 		moal_memcpy_ext(NULL, driver_version, CARD_SD8887,
298 				strlen(CARD_SD8887), strlen(driver_version));
299 		moal_memcpy_ext(
300 			NULL,
301 			driver_version + strlen(INTF_CARDTYPE) +
302 				strlen(KERN_VERSION),
303 			V15, strlen(V15),
304 			strlen(driver_version) -
305 				(strlen(INTF_CARDTYPE) + strlen(KERN_VERSION)));
306 	}
307 #endif
308 #ifdef SD8801
309 	if (cardp_sd->func->device == SD_DEVICE_ID_8801) {
310 		card_type = CARD_TYPE_SD8801;
311 		moal_memcpy_ext(NULL, driver_version, CARD_SD8801,
312 				strlen(CARD_SD8801), strlen(driver_version));
313 		moal_memcpy_ext(
314 			NULL,
315 			driver_version + strlen(INTF_CARDTYPE) +
316 				strlen(KERN_VERSION),
317 			V14, strlen(V14),
318 			strlen(driver_version) -
319 				(strlen(INTF_CARDTYPE) + strlen(KERN_VERSION)));
320 	}
321 #endif
322 
323 #ifdef SD8897
324 	if (cardp_sd->func->device == SD_DEVICE_ID_8897) {
325 		card_type = CARD_TYPE_SD8897;
326 		moal_memcpy_ext(NULL, driver_version, CARD_SD8897,
327 				strlen(CARD_SD8897), strlen(driver_version));
328 		moal_memcpy_ext(
329 			NULL,
330 			driver_version + strlen(INTF_CARDTYPE) +
331 				strlen(KERN_VERSION),
332 			V15, strlen(V15),
333 			strlen(driver_version) -
334 				(strlen(INTF_CARDTYPE) + strlen(KERN_VERSION)));
335 	}
336 #endif
337 #ifdef SD8977
338 	if (cardp_sd->func->device == SD_DEVICE_ID_8977) {
339 		card_type = CARD_TYPE_SD8977;
340 		moal_memcpy_ext(NULL, driver_version, CARD_SD8977,
341 				strlen(CARD_SD8977), strlen(driver_version));
342 		moal_memcpy_ext(
343 			NULL,
344 			driver_version + strlen(INTF_CARDTYPE) +
345 				strlen(KERN_VERSION),
346 			V16, strlen(V16),
347 			strlen(driver_version) -
348 				(strlen(INTF_CARDTYPE) + strlen(KERN_VERSION)));
349 	}
350 #endif
351 #ifdef SD8978
352 	if (cardp_sd->func->device == SD_DEVICE_ID_8978) {
353 		card_type = CARD_TYPE_SD8978;
354 		moal_memcpy_ext(NULL, driver_version, "SDIW416",
355 				strlen("SDIW416"), strlen(driver_version));
356 		moal_memcpy_ext(
357 			NULL,
358 			driver_version + strlen(INTF_CARDTYPE) +
359 				strlen(KERN_VERSION),
360 			V16, strlen(V16),
361 			strlen(driver_version) -
362 				(strlen(INTF_CARDTYPE) + strlen(KERN_VERSION)));
363 	}
364 #endif
365 #ifdef SD8997
366 	if (cardp_sd->func->device == SD_DEVICE_ID_8997) {
367 		card_type = CARD_TYPE_SD8997;
368 		moal_memcpy_ext(NULL, driver_version, CARD_SD8997,
369 				strlen(CARD_SD8997), strlen(driver_version));
370 		moal_memcpy_ext(
371 			NULL,
372 			driver_version + strlen(INTF_CARDTYPE) +
373 				strlen(KERN_VERSION),
374 			V16, strlen(V16),
375 			strlen(driver_version) -
376 				(strlen(INTF_CARDTYPE) + strlen(KERN_VERSION)));
377 	}
378 #endif
379 #ifdef SD8987
380 	if (cardp_sd->func->device == SD_DEVICE_ID_8987) {
381 		card_type = CARD_TYPE_SD8987;
382 		moal_memcpy_ext(NULL, driver_version, CARD_SD8987,
383 				strlen(CARD_SD8987), strlen(driver_version));
384 		moal_memcpy_ext(
385 			NULL,
386 			driver_version + strlen(INTF_CARDTYPE) +
387 				strlen(KERN_VERSION),
388 			V16, strlen(V16),
389 			strlen(driver_version) -
390 				(strlen(INTF_CARDTYPE) + strlen(KERN_VERSION)));
391 	}
392 #endif
393 #ifdef SDNW62X
394 	if (cardp_sd->func->device == SD_DEVICE_ID_NW62X) {
395 		card_type = CARD_TYPE_SDNW62X;
396 		moal_memcpy_ext(NULL, driver_version, CARD_SDNW62X,
397 				strlen(CARD_SDNW62X), strlen(driver_version));
398 		moal_memcpy_ext(
399 			NULL,
400 			driver_version + strlen(INTF_CARDTYPE) +
401 				strlen(KERN_VERSION),
402 			V17, strlen(V17),
403 			strlen(driver_version) -
404 				(strlen(INTF_CARDTYPE) + strlen(KERN_VERSION)));
405 	}
406 #endif
407 #ifdef SD9097
408 	if (cardp_sd->func->device == SD_DEVICE_ID_9097) {
409 		card_type = CARD_TYPE_SD9097;
410 		moal_memcpy_ext(NULL, driver_version, CARD_SD9097,
411 				strlen(CARD_SD9097), strlen(driver_version));
412 		moal_memcpy_ext(
413 			NULL,
414 			driver_version + strlen(INTF_CARDTYPE) +
415 				strlen(KERN_VERSION),
416 			V17, strlen(V17),
417 			strlen(driver_version) -
418 				(strlen(INTF_CARDTYPE) + strlen(KERN_VERSION)));
419 	}
420 #endif
421 #ifdef SD9098
422 	if (cardp_sd->func->device == SD_DEVICE_ID_9098_FN1 ||
423 	    cardp_sd->func->device == SD_DEVICE_ID_9098_FN2) {
424 		card_type = CARD_TYPE_SD9098;
425 		moal_memcpy_ext(NULL, driver_version, CARD_SD9098,
426 				strlen(CARD_SD9098), strlen(driver_version));
427 		moal_memcpy_ext(
428 			NULL,
429 			driver_version + strlen(INTF_CARDTYPE) +
430 				strlen(KERN_VERSION),
431 			V17, strlen(V17),
432 			strlen(driver_version) -
433 				(strlen(INTF_CARDTYPE) + strlen(KERN_VERSION)));
434 	}
435 #endif
436 #ifdef SD9177
437 	if (cardp_sd->func->device == SD_DEVICE_ID_9177) {
438 		card_type = CARD_TYPE_SD9177;
439 		moal_memcpy_ext(NULL, driver_version, CARD_SD9177,
440 				strlen(CARD_SD9177), strlen(driver_version));
441 		moal_memcpy_ext(
442 			NULL,
443 			driver_version + strlen(INTF_CARDTYPE) +
444 				strlen(KERN_VERSION),
445 			V18, strlen(V18),
446 			strlen(driver_version) -
447 				(strlen(INTF_CARDTYPE) + strlen(KERN_VERSION)));
448 	}
449 #endif
450 	return card_type;
451 }
452 
453 /**  @brief This function handles client driver probe.
454  *
455  *  @param func     A pointer to sdio_func structure.
456  *  @param id       A pointer to sdio_device_id structure.
457  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE/error code
458  */
woal_sdio_probe(struct sdio_func * func,const struct sdio_device_id * id)459 int woal_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
460 {
461 	int ret = MLAN_STATUS_SUCCESS;
462 	struct sdio_mmc_card *card = NULL;
463 	t_u16 card_type = 0;
464 
465 	ENTER();
466 
467 	PRINTM(MMSG, "vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n",
468 	       func->vendor, func->device, func->class, func->num);
469 
470 	card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL);
471 	if (!card) {
472 		PRINTM(MFATAL,
473 		       "Failed to allocate memory in probe function!\n");
474 		LEAVE();
475 		return -ENOMEM;
476 	}
477 
478 	card->func = func;
479 
480 #ifdef MMC_QUIRK_BLKSZ_FOR_BYTE_MODE
481 	/* The byte mode patch is available in kernel MMC driver
482 	 * which fixes one issue in MP-A transfer.
483 	 * bit1: use func->cur_blksize for byte mode
484 	 */
485 	func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
486 #endif
487 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
488 	func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
489 #endif
490 
491 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
492 	/* wait for chip fully wake up */
493 	if (!func->enable_timeout)
494 		func->enable_timeout = 200;
495 #endif
496 	sdio_claim_host(func);
497 	ret = sdio_enable_func(func);
498 	if (ret) {
499 		sdio_release_host(func);
500 		PRINTM(MFATAL, "sdio_enable_func() failed: ret=%d\n", ret);
501 		ret = -EIO;
502 		goto err;
503 	}
504 	sdio_release_host(func);
505 
506 	card_type = woal_update_card_type(card);
507 	if (!card_type) {
508 		PRINTM(MERROR, "sdmmc probe: woal_update_card_type() failed\n");
509 		ret = MLAN_STATUS_FAILURE;
510 		goto err;
511 	}
512 
513 	if (NULL ==
514 	    woal_add_card(card, &card->func->dev, &sdiommc_ops, card_type)) {
515 		PRINTM(MMSG, "woal_add_card failed\n");
516 		ret = MLAN_STATUS_FAILURE;
517 		goto err;
518 	}
519 
520 #ifdef IMX_SUPPORT
521 	woal_regist_oob_wakeup_irq(card->handle);
522 #endif /* IMX_SUPPORT */
523 
524 	LEAVE();
525 	return ret;
526 err:
527 	kfree(card);
528 	sdio_claim_host(func);
529 	sdio_disable_func(func);
530 	sdio_release_host(func);
531 
532 	LEAVE();
533 	return ret;
534 }
535 
536 /**  @brief This function handles client driver remove.
537  *
538  *  @param func     A pointer to sdio_func structure.
539  *  @return         N/A
540  */
woal_sdio_remove(struct sdio_func * func)541 void woal_sdio_remove(struct sdio_func *func)
542 {
543 	struct sdio_mmc_card *card;
544 
545 	ENTER();
546 
547 	if (func) {
548 		PRINTM(MINFO, "SDIO func=%d\n", func->num);
549 		card = sdio_get_drvdata(func);
550 		if (card) {
551 #ifdef IMX_SUPPORT
552 			woal_unregist_oob_wakeup_irq(card->handle);
553 #endif /* IMX_SUPPORT */
554 			woal_remove_card(card);
555 			kfree(card);
556 		}
557 	}
558 
559 	LEAVE();
560 }
561 
562 #ifdef SDIO_SUSPEND_RESUME
563 #ifdef MMC_PM_KEEP_POWER
564 #ifdef MMC_PM_FUNC_SUSPENDED
565 /**  @brief This function tells lower driver that WLAN is suspended
566  *
567  *  @param handle   A Pointer to the moal_handle structure
568  *  @return         N/A
569  */
woal_wlan_is_suspended(moal_handle * handle)570 void woal_wlan_is_suspended(moal_handle *handle)
571 {
572 	ENTER();
573 	if (handle->suspend_notify_req == MTRUE) {
574 		handle->is_suspended = MTRUE;
575 		sdio_func_suspended(
576 			((struct sdio_mmc_card *)handle->card)->func);
577 	}
578 	LEAVE();
579 }
580 #endif
581 
582 /**  @brief This function handles client driver shutdown
583  *
584  *  @param dev      A pointer to device structure
585  *  @return         N/A
586  */
woal_sdio_shutdown(struct device * dev)587 void woal_sdio_shutdown(struct device *dev)
588 {
589 	struct sdio_func *func = dev_to_sdio_func(dev);
590 	moal_handle *handle = NULL;
591 	struct sdio_mmc_card *cardp;
592 	mlan_ds_ps_info pm_info;
593 	int i, retry_num = 8;
594 
595 	ENTER();
596 	PRINTM(MCMND, "<--- Enter woal_sdio_shutdown --->\n");
597 	cardp = sdio_get_drvdata(func);
598 	if (!cardp || !cardp->handle) {
599 		PRINTM(MERROR, "Card or moal_handle structure is not valid\n");
600 		LEAVE();
601 		return;
602 	}
603 	handle = cardp->handle;
604 	for (i = 0; i < handle->priv_num; i++)
605 		netif_device_detach(handle->priv[i]->netdev);
606 
607 	if (moal_extflg_isset(handle, EXT_SHUTDOWN_HS)) {
608 		handle->shutdown_hs_in_process = MTRUE;
609 		memset(&pm_info, 0, sizeof(pm_info));
610 		for (i = 0; i < retry_num; i++) {
611 			if (MLAN_STATUS_SUCCESS ==
612 			    woal_get_pm_info(woal_get_priv(handle,
613 							   MLAN_BSS_ROLE_ANY),
614 					     &pm_info)) {
615 				if (pm_info.is_suspend_allowed == MTRUE)
616 					break;
617 				else
618 					PRINTM(MMSG,
619 					       "Shutdown not allowed and retry again\n");
620 			}
621 			woal_sched_timeout(100);
622 		}
623 		if (pm_info.is_suspend_allowed == MFALSE) {
624 			PRINTM(MMSG, "Shutdown not allowed\n");
625 			goto done;
626 		}
627 		woal_enable_hs(woal_get_priv(handle, MLAN_BSS_ROLE_ANY));
628 
629 		wait_event_interruptible_timeout(
630 			handle->hs_activate_wait_q,
631 			handle->hs_activate_wait_q_woken, HS_ACTIVE_TIMEOUT);
632 		if (handle->hs_activated == MTRUE)
633 			PRINTM(MMSG, "HS actived in shutdown\n");
634 		else
635 			PRINTM(MMSG, "Fail to enable HS in shutdown\n");
636 	} else {
637 		for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
638 			if (handle->priv[i]) {
639 				if (handle->priv[i]->media_connected == MTRUE
640 #ifdef UAP_SUPPORT
641 				    || (GET_BSS_ROLE(handle->priv[i]) ==
642 					MLAN_BSS_ROLE_UAP)
643 #endif
644 				) {
645 					PRINTM(MIOCTL,
646 					       "disconnect on suspend\n");
647 					woal_disconnect(handle->priv[i],
648 							MOAL_NO_WAIT, NULL,
649 							DEF_DEAUTH_REASON_CODE);
650 				}
651 			}
652 		}
653 	}
654 
655 done:
656 	PRINTM(MCMND, "<--- Leave woal_sdio_shutdown --->\n");
657 	LEAVE();
658 	return;
659 }
660 
661 /**  @brief This function handles client driver suspend
662  *
663  *  @param dev      A pointer to device structure
664  *  @return         MLAN_STATUS_SUCCESS or error code
665  */
woal_sdio_suspend(struct device * dev)666 int woal_sdio_suspend(struct device *dev)
667 {
668 	struct sdio_func *func = dev_to_sdio_func(dev);
669 	mmc_pm_flag_t pm_flags = 0;
670 	moal_handle *handle = NULL;
671 	struct sdio_mmc_card *cardp;
672 	int i, retry_num = 8;
673 	int ret = MLAN_STATUS_SUCCESS;
674 	int hs_actived = 0;
675 	mlan_ds_ps_info pm_info;
676 
677 	ENTER();
678 	PRINTM(MCMND, "<--- Enter woal_sdio_suspend --->\n");
679 	pm_flags = sdio_get_host_pm_caps(func);
680 	PRINTM(MCMND, "%s: suspend: PM flags = 0x%x\n", sdio_func_id(func),
681 	       pm_flags);
682 	cardp = sdio_get_drvdata(func);
683 	if (!cardp || !cardp->handle) {
684 		PRINTM(MERROR, "Card or moal_handle structure is not valid\n");
685 		LEAVE();
686 		return MLAN_STATUS_SUCCESS;
687 	}
688 
689 	handle = cardp->handle;
690 
691 	if (moal_extflg_isset(handle, EXT_PM_KEEP_POWER) &&
692 	    !(pm_flags & MMC_PM_KEEP_POWER)) {
693 		PRINTM(MERROR,
694 		       "%s: cannot remain alive while host is suspended\n",
695 		       sdio_func_id(func));
696 		LEAVE();
697 		return -ENOSYS;
698 	}
699 	if (handle->is_suspended == MTRUE) {
700 		PRINTM(MWARN, "Device already suspended\n");
701 		LEAVE();
702 		return MLAN_STATUS_SUCCESS;
703 	}
704 	if (handle->fw_dump) {
705 		PRINTM(MMSG, "suspend not allowed while FW dump!");
706 		ret = -EBUSY;
707 		goto done;
708 	}
709 #ifdef STA_SUPPORT
710 	for (i = 0; i < MIN(handle->priv_num, MLAN_MAX_BSS_NUM); i++) {
711 		if (handle->priv[i] &&
712 		    (GET_BSS_ROLE(handle->priv[i]) == MLAN_BSS_ROLE_STA))
713 			woal_cancel_scan(handle->priv[i], MOAL_IOCTL_WAIT);
714 	}
715 #endif
716 	handle->suspend_fail = MFALSE;
717 	memset(&pm_info, 0, sizeof(pm_info));
718 	for (i = 0; i < retry_num; i++) {
719 		if (MLAN_STATUS_SUCCESS ==
720 		    woal_get_pm_info(woal_get_priv(handle, MLAN_BSS_ROLE_ANY),
721 				     &pm_info)) {
722 			if (pm_info.is_suspend_allowed == MTRUE)
723 				break;
724 			else
725 				PRINTM(MMSG,
726 				       "Suspend not allowed and retry again\n");
727 		}
728 		woal_sched_timeout(100);
729 	}
730 	if (pm_info.is_suspend_allowed == MFALSE) {
731 		PRINTM(MMSG, "Suspend not allowed\n");
732 		ret = -EBUSY;
733 		goto done;
734 	}
735 
736 	for (i = 0; i < handle->priv_num; i++)
737 		netif_device_detach(handle->priv[i]->netdev);
738 
739 	if (moal_extflg_isset(handle, EXT_PM_KEEP_POWER)) {
740 		/* Enable the Host Sleep */
741 #ifdef MMC_PM_FUNC_SUSPENDED
742 		handle->suspend_notify_req = MTRUE;
743 #endif
744 		hs_actived = woal_enable_hs(
745 			woal_get_priv(handle, MLAN_BSS_ROLE_ANY));
746 #ifdef MMC_PM_FUNC_SUSPENDED
747 		handle->suspend_notify_req = MFALSE;
748 #endif
749 		if (hs_actived) {
750 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 3, 4)
751 			if (pm_flags & MMC_PM_WAKE_SDIO_IRQ) {
752 				ret = sdio_set_host_pm_flags(
753 					func, MMC_PM_WAKE_SDIO_IRQ);
754 				PRINTM(MCMND,
755 				       "suspend with MMC_PM_WAKE_SDIO_IRQ ret=%d\n",
756 				       ret);
757 			}
758 #endif
759 #ifdef MMC_PM_SKIP_RESUME_PROBE
760 			PRINTM(MCMND,
761 			       "suspend with MMC_PM_KEEP_POWER and MMC_PM_SKIP_RESUME_PROBE\n");
762 			ret = sdio_set_host_pm_flags(
763 				func,
764 				MMC_PM_KEEP_POWER | MMC_PM_SKIP_RESUME_PROBE);
765 #else
766 			PRINTM(MCMND, "suspend with MMC_PM_KEEP_POWER\n");
767 			ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER);
768 #endif
769 		} else {
770 			PRINTM(MMSG, "HS not actived, suspend fail!");
771 			handle->suspend_fail = MTRUE;
772 			for (i = 0; i < handle->priv_num; i++)
773 				netif_device_attach(handle->priv[i]->netdev);
774 			ret = -EBUSY;
775 			goto done;
776 		}
777 	}
778 
779 	/* Indicate device suspended */
780 	handle->is_suspended = MTRUE;
781 #ifdef IMX_SUPPORT
782 	woal_enable_oob_wakeup_irq(handle);
783 #endif /* IMX_SUPPORT */
784 done:
785 	PRINTM(MCMND, "<--- Leave woal_sdio_suspend --->\n");
786 	LEAVE();
787 	return ret;
788 }
789 
790 /**  @brief This function handles client driver resume
791  *
792  *  @param dev      A pointer to device structure
793  *  @return         MLAN_STATUS_SUCCESS
794  */
woal_sdio_resume(struct device * dev)795 int woal_sdio_resume(struct device *dev)
796 {
797 	struct sdio_func *func = dev_to_sdio_func(dev);
798 	mmc_pm_flag_t pm_flags = 0;
799 	moal_handle *handle = NULL;
800 	struct sdio_mmc_card *cardp;
801 	int i;
802 
803 	ENTER();
804 	PRINTM(MCMND, "<--- Enter woal_sdio_resume --->\n");
805 	pm_flags = sdio_get_host_pm_caps(func);
806 	PRINTM(MCMND, "%s: resume: PM flags = 0x%x\n", sdio_func_id(func),
807 	       pm_flags);
808 	cardp = sdio_get_drvdata(func);
809 	if (!cardp || !cardp->handle) {
810 		PRINTM(MERROR, "Card or moal_handle structure is not valid\n");
811 		LEAVE();
812 		return MLAN_STATUS_SUCCESS;
813 	}
814 	handle = cardp->handle;
815 
816 	if (handle->is_suspended == MFALSE) {
817 		PRINTM(MWARN, "Device already resumed\n");
818 		LEAVE();
819 		return MLAN_STATUS_SUCCESS;
820 	}
821 	handle->is_suspended = MFALSE;
822 	if (woal_check_driver_status(handle)) {
823 		PRINTM(MERROR, "Resuem, device is in hang state\n");
824 		LEAVE();
825 		return MLAN_STATUS_SUCCESS;
826 	}
827 	for (i = 0; i < handle->priv_num; i++)
828 		netif_device_attach(handle->priv[i]->netdev);
829 
830 	/* Disable Host Sleep */
831 	woal_cancel_hs(woal_get_priv(handle, MLAN_BSS_ROLE_ANY), MOAL_NO_WAIT);
832 #ifdef IMX_SUPPORT
833 	woal_disable_oob_wakeup_irq(handle);
834 #endif /* IMX_SUPPORT */
835 	PRINTM(MCMND, "<--- Leave woal_sdio_resume --->\n");
836 	LEAVE();
837 	return MLAN_STATUS_SUCCESS;
838 }
839 #endif
840 #endif /* SDIO_SUSPEND_RESUME */
841 
842 /**
843  *  @brief This function writes data into card register
844  *
845  *  @param handle   A Pointer to the moal_handle structure
846  *  @param reg      Register offset
847  *  @param data     Value
848  *
849  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
850  */
woal_sdiommc_write_reg(moal_handle * handle,t_u32 reg,t_u32 data)851 static mlan_status woal_sdiommc_write_reg(moal_handle *handle, t_u32 reg,
852 					  t_u32 data)
853 {
854 	mlan_status ret = MLAN_STATUS_FAILURE;
855 	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
856 	sdio_writeb(((struct sdio_mmc_card *)handle->card)->func, (t_u8)data,
857 		    reg, (int *)&ret);
858 	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
859 	return ret;
860 }
861 
862 /**
863  *  @brief This function reads data from card register
864  *
865  *  @param handle   A Pointer to the moal_handle structure
866  *  @param reg      Register offset
867  *  @param data     Value
868  *
869  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
870  */
woal_sdiommc_read_reg(moal_handle * handle,t_u32 reg,t_u32 * data)871 static mlan_status woal_sdiommc_read_reg(moal_handle *handle, t_u32 reg,
872 					 t_u32 *data)
873 {
874 	mlan_status ret = MLAN_STATUS_FAILURE;
875 	t_u8 val;
876 	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
877 	val = sdio_readb(((struct sdio_mmc_card *)handle->card)->func, reg,
878 			 (int *)&ret);
879 	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
880 	*data = val;
881 
882 	return ret;
883 }
884 
885 /**
886  *  @brief This function writes data into card register
887  *
888  *  @param handle   A Pointer to the moal_handle structure
889  *  @param reg      Register offset
890  *  @param data     Value
891  *
892  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
893  */
woal_sdio_writeb(moal_handle * handle,t_u32 reg,t_u8 data)894 static mlan_status woal_sdio_writeb(moal_handle *handle, t_u32 reg, t_u8 data)
895 {
896 	mlan_status ret = MLAN_STATUS_FAILURE;
897 	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
898 	sdio_writeb(((struct sdio_mmc_card *)handle->card)->func, (t_u8)data,
899 		    reg, (int *)&ret);
900 	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
901 	return ret;
902 }
903 
904 /**
905  *  @brief This function reads data from card register
906  *
907  *  @param handle   A Pointer to the moal_handle structure
908  *  @param reg      Register offset
909  *  @param data     Value
910  *
911  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
912  */
woal_sdio_readb(moal_handle * handle,t_u32 reg,t_u8 * data)913 static mlan_status woal_sdio_readb(moal_handle *handle, t_u32 reg, t_u8 *data)
914 {
915 	mlan_status ret = MLAN_STATUS_FAILURE;
916 	t_u8 val;
917 	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
918 	val = sdio_readb(((struct sdio_mmc_card *)handle->card)->func, reg,
919 			 (int *)&ret);
920 	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
921 	*data = val;
922 
923 	return ret;
924 }
925 
926 /**
927  *  @brief This function reads data from card register FN0
928  *
929  *  @param handle   A Pointer to the moal_handle structure
930  *  @param reg      Register offset
931  *  @param data     Value
932  *
933  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
934  */
woal_sdio_f0_readb(moal_handle * handle,t_u32 reg,t_u8 * data)935 static mlan_status woal_sdio_f0_readb(moal_handle *handle, t_u32 reg,
936 				      t_u8 *data)
937 {
938 	mlan_status ret = MLAN_STATUS_FAILURE;
939 	t_u8 val;
940 	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
941 	val = sdio_f0_readb(((struct sdio_mmc_card *)handle->card)->func, reg,
942 			    (int *)&ret);
943 	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
944 	*data = val;
945 
946 	return ret;
947 }
948 
949 /**
950  *  @brief This function use SG mode to read/write data into card memory
951  *
952  *  @param handle   A Pointer to the moal_handle structure
953  *  @param pmbuf_list   Pointer to a linked list of mlan_buffer structure
954  *  @param port     Port
955  *  @param write    write flag
956  *
957  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
958  */
woal_sdio_rw_mb(moal_handle * handle,pmlan_buffer pmbuf_list,t_u32 port,t_u8 write)959 static mlan_status woal_sdio_rw_mb(moal_handle *handle, pmlan_buffer pmbuf_list,
960 				   t_u32 port, t_u8 write)
961 {
962 	struct scatterlist sg_list[SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX];
963 	int num_sg = pmbuf_list->use_count;
964 	int i = 0;
965 	mlan_buffer *pmbuf = NULL;
966 	struct mmc_request mmc_req;
967 	struct mmc_command mmc_cmd;
968 	struct mmc_data mmc_dat;
969 	struct sdio_func *func = ((struct sdio_mmc_card *)handle->card)->func;
970 	t_u32 ioport = (port & MLAN_SDIO_IO_PORT_MASK);
971 	t_u32 blkcnt = pmbuf_list->data_len / MLAN_SDIO_BLOCK_SIZE;
972 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
973 	int status;
974 #endif
975 
976 	if (num_sg > SDIO_MP_AGGR_DEF_PKT_LIMIT_MAX) {
977 		PRINTM(MERROR, "ERROR: num_sg=%d", num_sg);
978 		return MLAN_STATUS_FAILURE;
979 	}
980 	sg_init_table(sg_list, num_sg);
981 	pmbuf = pmbuf_list->pnext;
982 	for (i = 0; i < num_sg; i++) {
983 		if (pmbuf == pmbuf_list)
984 			break;
985 		sg_set_buf(&sg_list[i], pmbuf->pbuf + pmbuf->data_offset,
986 			   pmbuf->data_len);
987 		pmbuf = pmbuf->pnext;
988 	}
989 	memset(&mmc_req, 0, sizeof(struct mmc_request));
990 	memset(&mmc_cmd, 0, sizeof(struct mmc_command));
991 	memset(&mmc_dat, 0, sizeof(struct mmc_data));
992 
993 	mmc_dat.sg = sg_list;
994 	mmc_dat.sg_len = num_sg;
995 	mmc_dat.blksz = MLAN_SDIO_BLOCK_SIZE;
996 	mmc_dat.blocks = blkcnt;
997 	mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ;
998 
999 	mmc_cmd.opcode = SD_IO_RW_EXTENDED;
1000 	mmc_cmd.arg = write ? 1 << 31 : 0;
1001 	mmc_cmd.arg |= (func->num & 0x7) << 28;
1002 	mmc_cmd.arg |= 1 << 27; /* block basic */
1003 	mmc_cmd.arg |= 0; /* fix address */
1004 	mmc_cmd.arg |= (ioport & 0x1FFFF) << 9;
1005 	mmc_cmd.arg |= blkcnt & 0x1FF;
1006 	mmc_cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
1007 
1008 	mmc_req.cmd = &mmc_cmd;
1009 	mmc_req.data = &mmc_dat;
1010 
1011 	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
1012 	mmc_set_data_timeout(
1013 		&mmc_dat, ((struct sdio_mmc_card *)handle->card)->func->card);
1014 	mmc_wait_for_req(
1015 		((struct sdio_mmc_card *)handle->card)->func->card->host,
1016 		&mmc_req);
1017 
1018 	if (mmc_cmd.error || mmc_dat.error) {
1019 		PRINTM(MERROR, "CMD53 %s cmd_error = %d data_error=%d\n",
1020 		       write ? "write" : "read", mmc_cmd.error, mmc_dat.error);
1021 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
1022 		/* issue abort cmd52 command through F0*/
1023 		sdio_f0_writeb(((struct sdio_mmc_card *)handle->card)->func,
1024 			       0x01, SDIO_CCCR_ABORT, &status);
1025 #endif
1026 		sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
1027 		return MLAN_STATUS_FAILURE;
1028 	}
1029 	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
1030 	return MLAN_STATUS_SUCCESS;
1031 }
1032 
1033 /**
1034  *  @brief This function writes multiple bytes into card memory
1035  *
1036  *  @param handle   A Pointer to the moal_handle structure
1037  *  @param pmbuf    Pointer to mlan_buffer structure
1038  *  @param port     Port
1039  *  @param timeout  Time out value
1040  *
1041  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1042  */
woal_sdiommc_write_data_sync(moal_handle * handle,mlan_buffer * pmbuf,t_u32 port,t_u32 timeout)1043 static mlan_status woal_sdiommc_write_data_sync(moal_handle *handle,
1044 						mlan_buffer *pmbuf, t_u32 port,
1045 						t_u32 timeout)
1046 {
1047 	mlan_status ret = MLAN_STATUS_FAILURE;
1048 	t_u8 *buffer = (t_u8 *)(pmbuf->pbuf + pmbuf->data_offset);
1049 	t_u8 blkmode =
1050 		(port & MLAN_SDIO_BYTE_MODE_MASK) ? BYTE_MODE : BLOCK_MODE;
1051 	t_u32 blksz = (blkmode == BLOCK_MODE) ? MLAN_SDIO_BLOCK_SIZE : 1;
1052 	t_u32 blkcnt = (blkmode == BLOCK_MODE) ?
1053 			       (pmbuf->data_len / MLAN_SDIO_BLOCK_SIZE) :
1054 			       pmbuf->data_len;
1055 	t_u32 ioport = (port & MLAN_SDIO_IO_PORT_MASK);
1056 	int status = 0;
1057 	if (pmbuf->use_count > 1)
1058 		return woal_sdio_rw_mb(handle, pmbuf, port, MTRUE);
1059 #ifdef SDIO_MMC_DEBUG
1060 	handle->cmd53w = 1;
1061 #endif
1062 	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
1063 	status = sdio_writesb(((struct sdio_mmc_card *)handle->card)->func,
1064 			      ioport, buffer, blkcnt * blksz);
1065 	if (!status)
1066 		ret = MLAN_STATUS_SUCCESS;
1067 	else {
1068 		PRINTM(MERROR, "cmd53 write error=%d\n", status);
1069 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
1070 		/* issue abort cmd52 command through F0*/
1071 		sdio_f0_writeb(((struct sdio_mmc_card *)handle->card)->func,
1072 			       0x01, SDIO_CCCR_ABORT, &status);
1073 #endif
1074 	}
1075 	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
1076 #ifdef SDIO_MMC_DEBUG
1077 	handle->cmd53w = 2;
1078 #endif
1079 	return ret;
1080 }
1081 
1082 /**
1083  *  @brief This function reads multiple bytes from card memory
1084  *
1085  *  @param handle   A Pointer to the moal_handle structure
1086  *  @param pmbuf    Pointer to mlan_buffer structure
1087  *  @param port     Port
1088  *  @param timeout  Time out value
1089  *
1090  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1091  */
woal_sdiommc_read_data_sync(moal_handle * handle,mlan_buffer * pmbuf,t_u32 port,t_u32 timeout)1092 static mlan_status woal_sdiommc_read_data_sync(moal_handle *handle,
1093 					       mlan_buffer *pmbuf, t_u32 port,
1094 					       t_u32 timeout)
1095 {
1096 	mlan_status ret = MLAN_STATUS_FAILURE;
1097 	t_u8 *buffer = (t_u8 *)(pmbuf->pbuf + pmbuf->data_offset);
1098 	t_u8 blkmode =
1099 		(port & MLAN_SDIO_BYTE_MODE_MASK) ? BYTE_MODE : BLOCK_MODE;
1100 	t_u32 blksz = (blkmode == BLOCK_MODE) ? MLAN_SDIO_BLOCK_SIZE : 1;
1101 	t_u32 blkcnt = (blkmode == BLOCK_MODE) ?
1102 			       (pmbuf->data_len / MLAN_SDIO_BLOCK_SIZE) :
1103 			       pmbuf->data_len;
1104 	t_u32 ioport = (port & MLAN_SDIO_IO_PORT_MASK);
1105 	int status = 0;
1106 	if (pmbuf->use_count > 1)
1107 		return woal_sdio_rw_mb(handle, pmbuf, port, MFALSE);
1108 #ifdef SDIO_MMC_DEBUG
1109 	handle->cmd53r = 1;
1110 #endif
1111 	sdio_claim_host(((struct sdio_mmc_card *)handle->card)->func);
1112 	status = sdio_readsb(((struct sdio_mmc_card *)handle->card)->func,
1113 			     buffer, ioport, blkcnt * blksz);
1114 	if (!status) {
1115 		ret = MLAN_STATUS_SUCCESS;
1116 	} else {
1117 		PRINTM(MERROR, "cmd53 read error=%d\n", status);
1118 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
1119 		/* issue abort cmd52 command through F0*/
1120 		sdio_f0_writeb(((struct sdio_mmc_card *)handle->card)->func,
1121 			       0x01, SDIO_CCCR_ABORT, &status);
1122 #endif
1123 	}
1124 	sdio_release_host(((struct sdio_mmc_card *)handle->card)->func);
1125 #ifdef SDIO_MMC_DEBUG
1126 	handle->cmd53r = 2;
1127 #endif
1128 	return ret;
1129 }
1130 
1131 /**
1132  *  @brief This function registers the IF module in bus driver
1133  *
1134  *  @return    MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1135  */
woal_sdiommc_bus_register(void)1136 mlan_status woal_sdiommc_bus_register(void)
1137 {
1138 	mlan_status ret = MLAN_STATUS_SUCCESS;
1139 
1140 	ENTER();
1141 
1142 	/* SDIO Driver Registration */
1143 	if (sdio_register_driver(&wlan_sdio)) {
1144 		PRINTM(MFATAL, "SDIO Driver Registration Failed \n");
1145 		LEAVE();
1146 		return MLAN_STATUS_FAILURE;
1147 	}
1148 
1149 	LEAVE();
1150 	return ret;
1151 }
1152 
1153 /**
1154  *  @brief This function de-registers the IF module in bus driver
1155  *
1156  *  @return         N/A
1157  */
woal_sdiommc_bus_unregister(void)1158 void woal_sdiommc_bus_unregister(void)
1159 {
1160 	ENTER();
1161 
1162 	/* SDIO Driver Unregistration */
1163 	sdio_unregister_driver(&wlan_sdio);
1164 
1165 	LEAVE();
1166 }
1167 
1168 /**
1169  *  @brief This function de-registers the device
1170  *
1171  *  @param handle A pointer to moal_handle structure
1172  *  @return         N/A
1173  */
woal_sdiommc_unregister_dev(moal_handle * handle)1174 static void woal_sdiommc_unregister_dev(moal_handle *handle)
1175 {
1176 	ENTER();
1177 	if (handle->card) {
1178 		struct sdio_mmc_card *card = handle->card;
1179 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
1180 		struct sdio_func *func = card->func;
1181 #endif
1182 		/* Release the SDIO IRQ */
1183 		sdio_claim_host(card->func);
1184 		sdio_release_irq(card->func);
1185 		sdio_disable_func(card->func);
1186 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
1187 		if (handle->driver_status)
1188 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)
1189 			mmc_hw_reset(func->card);
1190 #else
1191 			mmc_hw_reset(func->card->host);
1192 #endif
1193 #endif
1194 		sdio_release_host(card->func);
1195 
1196 		sdio_set_drvdata(card->func, NULL);
1197 
1198 		PRINTM(MWARN, "Making the sdio dev card as NULL\n");
1199 		card->handle = NULL;
1200 	}
1201 
1202 	LEAVE();
1203 }
1204 
1205 /**
1206  *  @brief This function registers the device
1207  *
1208  *  @param handle  A pointer to moal_handle structure
1209  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1210  */
woal_sdiommc_register_dev(moal_handle * handle)1211 static mlan_status woal_sdiommc_register_dev(moal_handle *handle)
1212 {
1213 	int ret = MLAN_STATUS_SUCCESS;
1214 	struct sdio_mmc_card *card = handle->card;
1215 	struct sdio_func *func;
1216 
1217 	ENTER();
1218 
1219 	/* save adapter pointer in card */
1220 	card->handle = handle;
1221 	func = card->func;
1222 	sdio_claim_host(func);
1223 	/* Request the SDIO IRQ */
1224 	ret = sdio_claim_irq(func, woal_sdio_interrupt);
1225 	if (ret) {
1226 		PRINTM(MFATAL, "sdio_claim_irq failed: ret=%d\n", ret);
1227 		goto release_host;
1228 	}
1229 
1230 	/* Set block size */
1231 	ret = sdio_set_block_size(card->func, MLAN_SDIO_BLOCK_SIZE);
1232 	if (ret) {
1233 		PRINTM(MERROR,
1234 		       "sdio_set_block_seize(): cannot set SDIO block size\n");
1235 		ret = MLAN_STATUS_FAILURE;
1236 		goto release_irq;
1237 	}
1238 
1239 	sdio_release_host(func);
1240 	sdio_set_drvdata(func, card);
1241 
1242 	LEAVE();
1243 	return MLAN_STATUS_SUCCESS;
1244 
1245 release_irq:
1246 	sdio_release_irq(func);
1247 release_host:
1248 	sdio_release_host(func);
1249 	handle->card = NULL;
1250 
1251 	LEAVE();
1252 	return MLAN_STATUS_FAILURE;
1253 }
1254 
1255 /**
1256  *  @brief This function set bus clock on/off
1257  *
1258  *  @param handle   A pointer to moal_handle structure
1259  *  @param option   TRUE--on , FALSE--off
1260  *  @return         MLAN_STATUS_SUCCESS
1261  */
woal_sdio_set_bus_clock(moal_handle * handle,t_u8 option)1262 int woal_sdio_set_bus_clock(moal_handle *handle, t_u8 option)
1263 {
1264 	struct sdio_mmc_card *cardp = (struct sdio_mmc_card *)handle->card;
1265 	struct mmc_host *host = cardp->func->card->host;
1266 
1267 	ENTER();
1268 	if (option == MTRUE) {
1269 		/* restore value if non-zero */
1270 		if (cardp->host_clock)
1271 			host->ios.clock = cardp->host_clock;
1272 	} else {
1273 		/* backup value if non-zero, then clear */
1274 		if (host->ios.clock)
1275 			cardp->host_clock = host->ios.clock;
1276 		host->ios.clock = 0;
1277 	}
1278 
1279 	host->ops->set_ios(host, &host->ios);
1280 	LEAVE();
1281 	return MLAN_STATUS_SUCCESS;
1282 }
1283 
1284 /**
1285  *  @brief This function updates card reg based on the Cmd52 value in dev
1286  * structure
1287  *
1288  *  @param handle   A pointer to moal_handle structure
1289  *  @param func     A pointer to store func variable
1290  *  @param reg      A pointer to store reg variable
1291  *  @param val      A pointer to store val variable
1292  *  @return         MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1293  */
woal_sdio_read_write_cmd52(moal_handle * handle,int func,int reg,int val)1294 int woal_sdio_read_write_cmd52(moal_handle *handle, int func, int reg, int val)
1295 {
1296 	int ret = MLAN_STATUS_SUCCESS;
1297 	struct sdio_mmc_card *card = (struct sdio_mmc_card *)handle->card;
1298 
1299 	ENTER();
1300 	/* Save current func and reg for read */
1301 	handle->cmd52_func = func;
1302 	handle->cmd52_reg = reg;
1303 	sdio_claim_host(card->func);
1304 	if (val >= 0) {
1305 		/* Perform actual write only if val is provided */
1306 		if (func)
1307 			sdio_writeb(card->func, val, reg, &ret);
1308 		else
1309 			sdio_f0_writeb(card->func, val, reg, &ret);
1310 		if (ret) {
1311 			PRINTM(MERROR,
1312 			       "Cannot write value (0x%x) to func %d reg 0x%x\n",
1313 			       val, func, reg);
1314 		} else {
1315 			PRINTM(MMSG, "write value (0x%x) to func %d reg 0x%x\n",
1316 			       (u8)val, func, reg);
1317 			handle->cmd52_val = val;
1318 		}
1319 	} else {
1320 		if (func)
1321 			val = sdio_readb(card->func, reg, &ret);
1322 		else
1323 			val = sdio_f0_readb(card->func, reg, &ret);
1324 		if (ret) {
1325 			PRINTM(MERROR,
1326 			       "Cannot read value from func %d reg 0x%x\n",
1327 			       func, reg);
1328 		} else {
1329 			PRINTM(MMSG,
1330 			       "read value (0x%x) from func %d reg 0x%x\n",
1331 			       (u8)val, func, reg);
1332 			handle->cmd52_val = val;
1333 		}
1334 	}
1335 	sdio_release_host(card->func);
1336 	LEAVE();
1337 	return ret;
1338 }
1339 
1340 /**
1341  *  @brief This function check if this is second mac
1342  *
1343  *  @param handle   A pointer to moal_handle structure
1344  *  @return         MTRUE/MFALSE
1345  *
1346  */
woal_sdiommc_is_second_mac(moal_handle * handle)1347 static t_u8 woal_sdiommc_is_second_mac(moal_handle *handle)
1348 {
1349 #ifdef SD9098
1350 	struct sdio_mmc_card *card = (struct sdio_mmc_card *)handle->card;
1351 	if (card->func->device == SD_DEVICE_ID_9098_FN2)
1352 		return MTRUE;
1353 #endif
1354 	return MFALSE;
1355 }
1356 
woal_sdiommc_get_fw_name(moal_handle * handle)1357 static mlan_status woal_sdiommc_get_fw_name(moal_handle *handle)
1358 {
1359 	mlan_status ret = MLAN_STATUS_SUCCESS;
1360 #ifdef SD9098
1361 	struct sdio_mmc_card *card = (struct sdio_mmc_card *)handle->card;
1362 #endif
1363 	t_u32 revision_id = 0;
1364 	t_u32 rev_id_reg = handle->card_info->rev_id_reg;
1365 
1366 #if defined(SD8987) || defined(SD8997) || defined(SD9098) ||                   \
1367 	defined(SD9097) || defined(SDNW62X) || defined(SD8978) ||              \
1368 	defined(SD9177)
1369 	t_u32 magic_reg = handle->card_info->magic_reg;
1370 	t_u32 magic = 0;
1371 	t_u32 host_strap_reg = handle->card_info->host_strap_reg;
1372 	t_u32 strap = 0;
1373 #endif
1374 
1375 	ENTER();
1376 
1377 	if (handle->params.fw_name)
1378 		goto done;
1379 #ifdef SD8801
1380 	if (IS_SD8801(handle->card_type))
1381 		goto done;
1382 #endif
1383 	/** Revision ID register */
1384 	woal_sdiommc_read_reg(handle, rev_id_reg, &revision_id);
1385 	PRINTM(MCMND, "revision_id=0x%x\n", revision_id);
1386 
1387 #if defined(SD8987) || defined(SD8997) || defined(SD9098) ||                   \
1388 	defined(SD9097) || defined(SDNW62X) || defined(SD8978) ||              \
1389 	defined(SD9177)
1390 	/** Revision ID register */
1391 	woal_sdiommc_read_reg(handle, magic_reg, &magic);
1392 	/** Revision ID register */
1393 	woal_sdiommc_read_reg(handle, host_strap_reg, &strap);
1394 	strap &= 0x1;
1395 	magic &= 0xFF;
1396 	/* 1 = SDSD, 0 --SD UART */
1397 	PRINTM(MCMND, "magic=0x%x strap=0x%x\n", magic, strap);
1398 #endif
1399 #if defined(SD8977)
1400 	if (IS_SD8977(handle->card_type)) {
1401 		switch (revision_id) {
1402 		case SD8977_V0:
1403 			strcpy(handle->card_info->fw_name, SD8977_V0_FW_NAME);
1404 			strcpy(handle->card_info->fw_name_wlan,
1405 			       SD8977_WLAN_V0_FW_NAME);
1406 			break;
1407 		case SD8977_V1:
1408 			strcpy(handle->card_info->fw_name, SD8977_V1_FW_NAME);
1409 			strcpy(handle->card_info->fw_name_wlan,
1410 			       SD8977_WLAN_V1_FW_NAME);
1411 			break;
1412 		case SD8977_V2:
1413 			strcpy(handle->card_info->fw_name, SD8977_V2_FW_NAME);
1414 			strcpy(handle->card_info->fw_name_wlan,
1415 			       SD8977_WLAN_V2_FW_NAME);
1416 			break;
1417 		default:
1418 			break;
1419 		}
1420 	}
1421 #endif
1422 #if defined(SD8887)
1423 	if (IS_SD8887(handle->card_type)) {
1424 		/* Check revision ID */
1425 		switch (revision_id) {
1426 		case SD8887_A0:
1427 			strcpy(handle->card_info->fw_name, SD8887_A0_FW_NAME);
1428 			strcpy(handle->card_info->fw_name_wlan,
1429 			       SD8887_WLAN_A0_FW_NAME);
1430 			break;
1431 		case SD8887_A2:
1432 			strcpy(handle->card_info->fw_name, SD8887_A2_FW_NAME);
1433 			strcpy(handle->card_info->fw_name_wlan,
1434 			       SD8887_WLAN_A2_FW_NAME);
1435 			break;
1436 		default:
1437 			break;
1438 		}
1439 	}
1440 #endif
1441 
1442 #ifdef SD8997
1443 	if (IS_SD8997(handle->card_type)) {
1444 		if (magic == CHIP_MAGIC_VALUE) {
1445 			if (strap == CARD_TYPE_SD_UART)
1446 				strcpy(handle->card_info->fw_name,
1447 				       SDUART8997_DEFAULT_COMBO_FW_NAME);
1448 			else
1449 				strcpy(handle->card_info->fw_name,
1450 				       SDSD8997_DEFAULT_COMBO_FW_NAME);
1451 		}
1452 	}
1453 #endif
1454 
1455 #ifdef SD8987
1456 	if (IS_SD8987(handle->card_type)) {
1457 		if (magic == CHIP_MAGIC_VALUE) {
1458 			if (strap == CARD_TYPE_SD_UART)
1459 				strcpy(handle->card_info->fw_name,
1460 				       SDUART8987_DEFAULT_COMBO_FW_NAME);
1461 			else
1462 				strcpy(handle->card_info->fw_name,
1463 				       SDSD8987_DEFAULT_COMBO_FW_NAME);
1464 		}
1465 	}
1466 #endif
1467 
1468 #ifdef SD8978
1469 	if (IS_SD8978(handle->card_type)) {
1470 		if (magic == CHIP_MAGIC_VALUE) {
1471 			if (strap == CARD_TYPE_SD_UART)
1472 				strcpy(handle->card_info->fw_name,
1473 				       SDUART8978_DEFAULT_COMBO_FW_NAME);
1474 			else
1475 				strcpy(handle->card_info->fw_name,
1476 				       SDSD8978_DEFAULT_COMBO_FW_NAME);
1477 		}
1478 	}
1479 #endif
1480 
1481 #ifdef SD9098
1482 	if (IS_SD9098(handle->card_type) &&
1483 	    (card->func->device == SD_DEVICE_ID_9098_FN1)) {
1484 		switch (revision_id) {
1485 		case SD9098_Z1Z2:
1486 			if (magic == CHIP_MAGIC_VALUE) {
1487 				if (strap == CARD_TYPE_SD_UART)
1488 					strcpy(handle->card_info->fw_name,
1489 					       SDUART9098_DEFAULT_COMBO_FW_NAME);
1490 				else
1491 					strcpy(handle->card_info->fw_name,
1492 					       SDSD9098_DEFAULT_COMBO_FW_NAME);
1493 			}
1494 			strcpy(handle->card_info->fw_name_wlan,
1495 			       SD9098_DEFAULT_WLAN_FW_NAME);
1496 			break;
1497 		case SD9098_A0:
1498 		case SD9098_A1:
1499 		case SD9098_A2:
1500 			if (magic == CHIP_MAGIC_VALUE) {
1501 				if (strap == CARD_TYPE_SD_UART)
1502 					strcpy(handle->card_info->fw_name,
1503 					       SDUART9098_COMBO_V1_FW_NAME);
1504 				else
1505 					strcpy(handle->card_info->fw_name,
1506 					       SDSD9098_COMBO_V1_FW_NAME);
1507 			}
1508 			strcpy(handle->card_info->fw_name_wlan,
1509 			       SD9098_WLAN_V1_FW_NAME);
1510 			break;
1511 		default:
1512 			break;
1513 		}
1514 	}
1515 #endif
1516 #ifdef SD9097
1517 	if (IS_SD9097(handle->card_type)) {
1518 		switch (revision_id) {
1519 		case SD9097_B0:
1520 		case SD9097_B1:
1521 			if (magic == CHIP_MAGIC_VALUE) {
1522 				if (strap == CARD_TYPE_SD_UART)
1523 					strcpy(handle->card_info->fw_name,
1524 					       SDUART9097_COMBO_V1_FW_NAME);
1525 				else
1526 					strcpy(handle->card_info->fw_name,
1527 					       SDSD9097_COMBO_V1_FW_NAME);
1528 			}
1529 			strcpy(handle->card_info->fw_name_wlan,
1530 			       SD9097_WLAN_V1_FW_NAME);
1531 			break;
1532 		default:
1533 			break;
1534 		}
1535 	}
1536 #endif
1537 #ifdef SDNW62X
1538 	if (IS_SDNW62X(handle->card_type)) {
1539 		if (magic == CHIP_MAGIC_VALUE) {
1540 			if (strap == CARD_TYPE_SD_UART)
1541 				strcpy(handle->card_info->fw_name,
1542 				       SDUARTNW62X_COMBO_FW_NAME);
1543 			else
1544 				strcpy(handle->card_info->fw_name,
1545 				       SDSDNW62X_COMBO_FW_NAME);
1546 		}
1547 	}
1548 #endif
1549 
1550 #ifdef SD9177
1551 	if (IS_SD9177(handle->card_type)) {
1552 		switch (revision_id) {
1553 		case SD9177_A0:
1554 			if (magic == CHIP_MAGIC_VALUE) {
1555 				if (strap == CARD_TYPE_SD9177_UART)
1556 					strcpy(handle->card_info->fw_name,
1557 					       SDUART9177_DEFAULT_COMBO_FW_NAME);
1558 				else
1559 					strcpy(handle->card_info->fw_name,
1560 					       SDSD9177_DEFAULT_COMBO_FW_NAME);
1561 			}
1562 			strcpy(handle->card_info->fw_name_wlan,
1563 			       SD9177_DEFAULT_WLAN_FW_NAME);
1564 			break;
1565 		case SD9177_A1:
1566 			if (magic == CHIP_MAGIC_VALUE) {
1567 				if (strap == CARD_TYPE_SD9177_UART)
1568 					strcpy(handle->card_info->fw_name,
1569 					       SDUART9177_DEFAULT_COMBO_V1_FW_NAME);
1570 				else
1571 					strcpy(handle->card_info->fw_name,
1572 					       SDSD9177_DEFAULT_COMBO_V1_FW_NAME);
1573 			}
1574 			strcpy(handle->card_info->fw_name_wlan,
1575 			       SD9177_DEFAULT_WLAN_V1_FW_NAME);
1576 			break;
1577 		default:
1578 			break;
1579 		}
1580 	}
1581 #endif
1582 done:
1583 	PRINTM(MCMND, "combo fw:%s wlan fw:%s \n", handle->card_info->fw_name,
1584 	       handle->card_info->fw_name_wlan);
1585 	LEAVE();
1586 	return ret;
1587 }
1588 
1589 #define DEBUG_FW_DONE 0xFF
1590 #define DEBUG_MEMDUMP_FINISH 0xFE
1591 #define MAX_POLL_TRIES 100
1592 
1593 typedef enum {
1594 	DUMP_TYPE_ITCM = 0,
1595 	DUMP_TYPE_DTCM = 1,
1596 	DUMP_TYPE_SQRAM = 2,
1597 	DUMP_TYPE_APU_REGS = 3,
1598 	DUMP_TYPE_CIU_REGS = 4,
1599 	DUMP_TYPE_ICU_REGS = 5,
1600 	DUMP_TYPE_MAC_REGS = 6,
1601 	DUMP_TYPE_EXTEND_7 = 7,
1602 	DUMP_TYPE_EXTEND_8 = 8,
1603 	DUMP_TYPE_EXTEND_9 = 9,
1604 	DUMP_TYPE_EXTEND_10 = 10,
1605 	DUMP_TYPE_EXTEND_11 = 11,
1606 	DUMP_TYPE_EXTEND_12 = 12,
1607 	DUMP_TYPE_EXTEND_13 = 13,
1608 	DUMP_TYPE_EXTEND_LAST = 14
1609 } dumped_mem_type;
1610 
1611 #define MAX_NAME_LEN 8
1612 
1613 typedef struct {
1614 	t_u8 mem_name[MAX_NAME_LEN];
1615 	t_u8 *mem_Ptr;
1616 	struct file *pfile_mem;
1617 	t_u8 done_flag;
1618 	t_u8 type;
1619 } memory_type_mapping;
1620 
1621 static memory_type_mapping mem_type_mapping_tbl[] = {
1622 	{"ITCM", NULL, NULL, 0xF0, FW_DUMP_TYPE_MEM_ITCM},
1623 	{"DTCM", NULL, NULL, 0xF1, FW_DUMP_TYPE_MEM_DTCM},
1624 	{"SQRAM", NULL, NULL, 0xF2, FW_DUMP_TYPE_MEM_SQRAM},
1625 	{"APU", NULL, NULL, 0xF3, FW_DUMP_TYPE_REG_APU},
1626 	{"CIU", NULL, NULL, 0xF4, FW_DUMP_TYPE_REG_CIU},
1627 	{"ICU", NULL, NULL, 0xF5, FW_DUMP_TYPE_REG_ICU},
1628 	{"MAC", NULL, NULL, 0xF6, FW_DUMP_TYPE_REG_MAC},
1629 	{"EXT7", NULL, NULL, 0xF7, 0},
1630 	{"EXT8", NULL, NULL, 0xF8, 0},
1631 	{"EXT9", NULL, NULL, 0xF9, 0},
1632 	{"EXT10", NULL, NULL, 0xFA, 0},
1633 	{"EXT11", NULL, NULL, 0xFB, 0},
1634 	{"EXT12", NULL, NULL, 0xFC, 0},
1635 	{"EXT13", NULL, NULL, 0xFD, 0},
1636 	{"EXTLAST", NULL, NULL, 0xFE, 0},
1637 };
1638 static memory_type_mapping mem_type_mapping_tbl_8977_8997 = {"DUMP", NULL, NULL,
1639 							     0xDD, 0};
1640 /**
1641  *  @brief This function read/write firmware via cmd52
1642  *
1643  *  @param phandle   A pointer to moal_handle
1644  *  @param doneflag  A flag
1645  *
1646  *  @return         MLAN_STATUS_SUCCESS
1647  */
woal_cmd52_rdwr_firmware(moal_handle * phandle,t_u8 doneflag)1648 static rdwr_status woal_cmd52_rdwr_firmware(moal_handle *phandle, t_u8 doneflag)
1649 {
1650 	int ret = 0;
1651 	int tries = 0;
1652 	t_u8 ctrl_data = 0;
1653 	t_u8 dbg_dump_ctrl_reg = phandle->card_info->dump_fw_ctrl_reg;
1654 	t_u8 debug_host_ready = phandle->card_info->dump_fw_host_ready;
1655 
1656 #ifdef SD9177
1657 	if (IS_SD9177(phandle->card_type)) {
1658 		if (phandle->event_fw_dump)
1659 			debug_host_ready = 0xAA;
1660 	}
1661 #endif
1662 	ret = woal_sdio_writeb(phandle, dbg_dump_ctrl_reg, debug_host_ready);
1663 	if (ret) {
1664 		PRINTM(MERROR, "SDIO Write ERR\n");
1665 		return RDWR_STATUS_FAILURE;
1666 	}
1667 #ifdef SD9177
1668 	if (IS_SD9177(phandle->card_type)) {
1669 		if (phandle->event_fw_dump)
1670 			return RDWR_STATUS_SUCCESS;
1671 	}
1672 #endif
1673 	for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
1674 		ret = woal_sdio_readb(phandle, dbg_dump_ctrl_reg, &ctrl_data);
1675 		if (ret) {
1676 			PRINTM(MERROR, "SDIO READ ERR\n");
1677 			return RDWR_STATUS_FAILURE;
1678 		}
1679 		if (ctrl_data == DEBUG_FW_DONE)
1680 			break;
1681 		if (doneflag && ctrl_data == doneflag)
1682 			return RDWR_STATUS_DONE;
1683 		if (ctrl_data != debug_host_ready) {
1684 			PRINTM(MMSG,
1685 			       "The ctrl reg was changed, re-try again!\n");
1686 			ret = woal_sdio_writeb(phandle, dbg_dump_ctrl_reg,
1687 					       debug_host_ready);
1688 			if (ret) {
1689 				PRINTM(MERROR, "SDIO Write ERR\n");
1690 				return RDWR_STATUS_FAILURE;
1691 			}
1692 		}
1693 		udelay(100);
1694 	}
1695 	if (ctrl_data == debug_host_ready || tries == MAX_POLL_TRIES) {
1696 		PRINTM(MERROR, "Fail to pull ctrl_data\n");
1697 		return RDWR_STATUS_FAILURE;
1698 	}
1699 	return RDWR_STATUS_SUCCESS;
1700 }
1701 
1702 #ifdef SD8801
1703 #define DEBUG_HOST_READY 0xEE
1704 #define DEBUG_FW_DONE 0xFF
1705 #define DEBUG_MEMDUMP_FINISH 0xFE
1706 #define MAX_POLL_TRIES 100
1707 #define DEBUG_ITCM_DONE 0xaa
1708 #define DEBUG_DTCM_DONE 0xbb
1709 #define DEBUG_SQRAM_DONE 0xcc
1710 
1711 #define DEBUG_DUMP_CTRL_REG 0x63
1712 #define DEBUG_DUMP_FIRST_REG 0x62
1713 #define DEBUG_DUMP_START_REG 0x64
1714 #define DEBUG_DUMP_END_REG 0x6a
1715 #define ITCM_SIZE 0x60000
1716 #define SQRAM_SIZE 0x33500
1717 #define DTCM_SIZE 0x14000
1718 
1719 /**
1720  *  @brief This function dump firmware memory to file
1721  *
1722  *  @param phandle   A pointer to moal_handle
1723  *
1724  *  @return         N/A
1725  */
woal_dump_firmware_info(moal_handle * phandle)1726 void woal_dump_firmware_info(moal_handle *phandle)
1727 {
1728 	int ret = 0;
1729 	unsigned int reg, reg_start, reg_end;
1730 	t_u8 *ITCM_Ptr = NULL;
1731 	t_u8 *DTCM_Ptr = NULL;
1732 	t_u8 *SQRAM_Ptr = NULL;
1733 	t_u8 *dbg_ptr = NULL;
1734 	t_u32 sec, usec;
1735 	t_u8 ctrl_data = 0;
1736 	t_u32 dtcm_size = DTCM_SIZE;
1737 	t_u32 sqram_size = SQRAM_SIZE;
1738 	t_u8 *end_ptr = NULL;
1739 	int tries;
1740 
1741 	if (!phandle) {
1742 		PRINTM(MERROR, "Could not dump firmwware info\n");
1743 		return;
1744 	}
1745 	if (!phandle->fw_dump_buf) {
1746 		ret = moal_vmalloc(phandle, FW_DUMP_INFO_LEN,
1747 				   &(phandle->fw_dump_buf));
1748 		if (ret != MLAN_STATUS_SUCCESS || !phandle->fw_dump_buf) {
1749 			PRINTM(MERROR, "Failed to vmalloc fw dump bufffer\n");
1750 			return;
1751 		}
1752 	} else {
1753 		memset(phandle->fw_dump_buf, 0x00, FW_DUMP_INFO_LEN);
1754 	}
1755 	phandle->fw_dump_len = 0;
1756 
1757 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
1758 	sdio_claim_host(((struct sdio_mmc_card *)phandle->card)->func);
1759 #endif
1760 	/* start dump fw memory	*/
1761 	moal_get_system_time(phandle, &sec, &usec);
1762 	PRINTM(MMSG, "==== DEBUG MODE OUTPUT START: %u.%06u ====\n", sec, usec);
1763 	ret = moal_vmalloc(phandle, ITCM_SIZE + 1, (t_u8 **)&ITCM_Ptr);
1764 	if ((ret != MLAN_STATUS_SUCCESS) || !ITCM_Ptr) {
1765 		PRINTM(MERROR, "Error: vmalloc ITCM buffer failed!!!\n");
1766 		goto done;
1767 	}
1768 
1769 	PRINTM(MMSG, "DTCM_SIZE=0x%x\n", dtcm_size);
1770 	ret = moal_vmalloc(phandle, dtcm_size + 1, (t_u8 **)&DTCM_Ptr);
1771 	if ((ret != MLAN_STATUS_SUCCESS) || !DTCM_Ptr) {
1772 		PRINTM(MERROR, "Error: vmalloc DTCM buffer failed!!!\n");
1773 		goto done;
1774 	}
1775 	ret = moal_vmalloc(phandle, sqram_size + 1, (t_u8 **)&SQRAM_Ptr);
1776 	if ((ret != MLAN_STATUS_SUCCESS) || !SQRAM_Ptr) {
1777 		PRINTM(MERROR, "Error: vmalloc SQRAM buffer failed!!!\n");
1778 		goto done;
1779 	}
1780 	dbg_ptr = ITCM_Ptr;
1781 	end_ptr = ITCM_Ptr + ITCM_SIZE;
1782 	moal_get_system_time(phandle, &sec, &usec);
1783 	PRINTM(MMSG, "Start ITCM output %u.%06u, please wait...\n", sec, usec);
1784 	reg_start = DEBUG_DUMP_START_REG;
1785 	reg_end = DEBUG_DUMP_END_REG;
1786 	do {
1787 		ret = woal_sdio_writeb(phandle, DEBUG_DUMP_CTRL_REG,
1788 				       DEBUG_HOST_READY);
1789 		if (ret) {
1790 			PRINTM(MERROR, "SDIO Write ERR\n");
1791 			goto done;
1792 		}
1793 		for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
1794 			ret = woal_sdio_readb(phandle, DEBUG_DUMP_CTRL_REG,
1795 					      &ctrl_data);
1796 			if (ret) {
1797 				PRINTM(MERROR, "SDIO READ ERR\n");
1798 				goto done;
1799 			}
1800 			if ((ctrl_data == DEBUG_FW_DONE) ||
1801 			    (ctrl_data == DEBUG_ITCM_DONE) ||
1802 			    (ctrl_data == DEBUG_DTCM_DONE) ||
1803 			    (ctrl_data == DEBUG_SQRAM_DONE))
1804 				break;
1805 			if (ctrl_data != DEBUG_HOST_READY) {
1806 				ret = woal_sdio_writeb(phandle,
1807 						       DEBUG_DUMP_CTRL_REG,
1808 						       DEBUG_HOST_READY);
1809 				if (ret) {
1810 					PRINTM(MERROR, "SDIO Write ERR\n");
1811 					goto done;
1812 				}
1813 			}
1814 			udelay(100);
1815 		}
1816 		if (ctrl_data == DEBUG_HOST_READY) {
1817 			PRINTM(MERROR, "Fail to pull ctrl_data\n");
1818 			goto done;
1819 		}
1820 		reg = DEBUG_DUMP_FIRST_REG;
1821 		ret = woal_sdio_readb(phandle, reg, dbg_ptr);
1822 		if (ret) {
1823 			PRINTM(MMSG, "SDIO READ ERR\n");
1824 			goto done;
1825 		}
1826 		if (dbg_ptr < end_ptr)
1827 			dbg_ptr++;
1828 		else {
1829 			PRINTM(MINFO, "pre-allocced buf is not enough\n");
1830 			goto done;
1831 		}
1832 		for (reg = reg_start; reg <= reg_end; reg++) {
1833 			ret = woal_sdio_readb(phandle, reg, dbg_ptr);
1834 			if (ret) {
1835 				PRINTM(MMSG, "SDIO READ ERR\n");
1836 				goto done;
1837 			}
1838 			if (dbg_ptr < end_ptr)
1839 				dbg_ptr++;
1840 			else
1841 				PRINTM(MINFO,
1842 				       "pre-allocced buf is not enough\n");
1843 		}
1844 		switch (ctrl_data) {
1845 		case DEBUG_ITCM_DONE:
1846 #ifdef MLAN_64BIT
1847 			PRINTM(MMSG, "ITCM done: size=0x%lx\n",
1848 			       dbg_ptr - ITCM_Ptr);
1849 #else
1850 			PRINTM(MMSG, "ITCM done: size=0x%x\n",
1851 			       dbg_ptr - ITCM_Ptr);
1852 #endif
1853 			woal_save_dump_info_to_buf(phandle, ITCM_Ptr, ITCM_SIZE,
1854 						   FW_DUMP_TYPE_MEM_ITCM);
1855 			dbg_ptr = DTCM_Ptr;
1856 			end_ptr = DTCM_Ptr + dtcm_size;
1857 			moal_get_system_time(phandle, &sec, &usec);
1858 			PRINTM(MMSG,
1859 			       "Start DTCM output %u.%06u, please wait...\n",
1860 			       sec, usec);
1861 			break;
1862 		case DEBUG_DTCM_DONE:
1863 #ifdef MLAN_64BIT
1864 			PRINTM(MMSG, "DTCM done: size=0x%lx\n",
1865 			       dbg_ptr - DTCM_Ptr);
1866 #else
1867 			PRINTM(MMSG, "DTCM done: size=0x%x\n",
1868 			       dbg_ptr - DTCM_Ptr);
1869 #endif
1870 			woal_save_dump_info_to_buf(phandle, ITCM_Ptr, dtcm_size,
1871 						   FW_DUMP_TYPE_MEM_DTCM);
1872 			dbg_ptr = SQRAM_Ptr;
1873 			end_ptr = SQRAM_Ptr + sqram_size;
1874 			moal_get_system_time(phandle, &sec, &usec);
1875 			PRINTM(MMSG,
1876 			       "Start SQRAM output %u.%06u, please wait...\n",
1877 			       sec, usec);
1878 			break;
1879 		case DEBUG_SQRAM_DONE:
1880 #ifdef MLAN_64BIT
1881 			PRINTM(MMSG, "SQRAM done: size=0x%lx\n",
1882 			       dbg_ptr - SQRAM_Ptr);
1883 #else
1884 			PRINTM(MMSG, "SQRAM done: size=0x%x\n",
1885 			       dbg_ptr - SQRAM_Ptr);
1886 #endif
1887 			woal_save_dump_info_to_buf(phandle, SQRAM_Ptr,
1888 						   sqram_size,
1889 						   FW_DUMP_TYPE_MEM_SQRAM);
1890 			PRINTM(MMSG, "End output!\n");
1891 			break;
1892 		default:
1893 			break;
1894 		}
1895 	} while (ctrl_data != DEBUG_SQRAM_DONE);
1896 
1897 	woal_append_end_block(phandle);
1898 	PRINTM(MMSG,
1899 	       "The output ITCM/DTCM/SQRAM have been saved to files successfully!\n");
1900 	moal_get_system_time(phandle, &sec, &usec);
1901 	PRINTM(MMSG, "==== DEBUG MODE OUTPUT END: %u.%06u ====\n", sec, usec);
1902 	/* end dump fw memory */
1903 done:
1904 #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 32)
1905 	sdio_release_host(((struct sdio_mmc_card *)phandle->card)->func);
1906 #endif
1907 	if (ITCM_Ptr)
1908 		moal_vfree(phandle, ITCM_Ptr);
1909 	if (DTCM_Ptr)
1910 		moal_vfree(phandle, DTCM_Ptr);
1911 	if (SQRAM_Ptr)
1912 		moal_vfree(phandle, SQRAM_Ptr);
1913 	PRINTM(MMSG, "==== DEBUG MODE END ====\n");
1914 	return;
1915 }
1916 #endif
1917 
1918 /**
1919  *  @brief This function dump firmware memory to file
1920  *
1921  *  @param phandle   A pointer to moal_handle
1922  *
1923  *  @return         N/A
1924  */
woal_dump_firmware_info_v2(moal_handle * phandle)1925 void woal_dump_firmware_info_v2(moal_handle *phandle)
1926 {
1927 	int ret = 0;
1928 	unsigned int reg, reg_start, reg_end;
1929 	t_u8 *dbg_ptr = NULL;
1930 	t_u32 sec, usec;
1931 	t_u8 dump_num = 0;
1932 	t_u8 idx = 0;
1933 	t_u8 doneflag = 0;
1934 	rdwr_status stat;
1935 	t_u8 i = 0;
1936 	t_u8 read_reg = 0;
1937 	t_u32 memory_size = 0;
1938 	t_u8 *end_ptr = NULL;
1939 	t_u8 dbg_dump_start_reg = 0;
1940 	t_u8 dbg_dump_end_reg = 0;
1941 	t_u8 dbg_dump_ctrl_reg = 0;
1942 
1943 	if (!phandle) {
1944 		PRINTM(MERROR, "Could not dump firmwware info\n");
1945 		return;
1946 	}
1947 
1948 	dbg_dump_start_reg = phandle->card_info->dump_fw_start_reg;
1949 	dbg_dump_end_reg = phandle->card_info->dump_fw_end_reg;
1950 	dbg_dump_ctrl_reg = phandle->card_info->dump_fw_ctrl_reg;
1951 
1952 	if (!phandle->fw_dump_buf) {
1953 		ret = moal_vmalloc(phandle, FW_DUMP_INFO_LEN,
1954 				   &(phandle->fw_dump_buf));
1955 		if (ret != MLAN_STATUS_SUCCESS || !phandle->fw_dump_buf) {
1956 			PRINTM(MERROR, "Failed to vmalloc fw dump bufffer\n");
1957 			return;
1958 		}
1959 	} else {
1960 		memset(phandle->fw_dump_buf, 0x00, FW_DUMP_INFO_LEN);
1961 	}
1962 	phandle->fw_dump_len = 0;
1963 
1964 	/* start dump fw memory */
1965 	moal_get_system_time(phandle, &sec, &usec);
1966 	PRINTM(MMSG, "==== DEBUG MODE OUTPUT START: %u.%06u ====\n", sec, usec);
1967 	/* read the number of the memories which will dump */
1968 	if (RDWR_STATUS_FAILURE == woal_cmd52_rdwr_firmware(phandle, doneflag))
1969 		goto done;
1970 	reg = dbg_dump_start_reg;
1971 	ret = woal_sdio_readb(phandle, reg, &dump_num);
1972 	if (ret) {
1973 		PRINTM(MMSG, "SDIO READ MEM NUM ERR\n");
1974 		goto done;
1975 	}
1976 
1977 	/* read the length of every memory which will dump */
1978 	for (idx = 0; idx < dump_num; idx++) {
1979 		if (RDWR_STATUS_FAILURE ==
1980 		    woal_cmd52_rdwr_firmware(phandle, doneflag))
1981 			goto done;
1982 		memory_size = 0;
1983 		reg = dbg_dump_start_reg;
1984 		for (i = 0; i < 4; i++) {
1985 			ret = woal_sdio_readb(phandle, reg, &read_reg);
1986 			if (ret) {
1987 				PRINTM(MMSG, "SDIO READ ERR\n");
1988 				goto done;
1989 			}
1990 			memory_size |= (read_reg << i * 8);
1991 			reg++;
1992 		}
1993 		if (memory_size == 0) {
1994 			PRINTM(MMSG, "Firmware Dump Finished!\n");
1995 			ret = woal_sdiommc_write_reg(phandle, dbg_dump_ctrl_reg,
1996 						     DEBUG_MEMDUMP_FINISH);
1997 			if (ret) {
1998 				PRINTM(MERROR,
1999 				       "SDIO Write MEMDUMP_FINISH ERR\n");
2000 				goto done;
2001 			}
2002 			break;
2003 		} else {
2004 			PRINTM(MMSG, "%s_SIZE=0x%x\n",
2005 			       mem_type_mapping_tbl[idx].mem_name, memory_size);
2006 			ret = moal_vmalloc(
2007 				phandle, memory_size + 1,
2008 				(t_u8 **)&mem_type_mapping_tbl[idx].mem_Ptr);
2009 			if ((ret != MLAN_STATUS_SUCCESS) ||
2010 			    !mem_type_mapping_tbl[idx].mem_Ptr) {
2011 				PRINTM(MERROR,
2012 				       "Error: vmalloc %s buffer failed!!!\n",
2013 				       mem_type_mapping_tbl[idx].mem_name);
2014 				goto done;
2015 			}
2016 			dbg_ptr = mem_type_mapping_tbl[idx].mem_Ptr;
2017 			end_ptr = dbg_ptr + memory_size;
2018 		}
2019 		doneflag = mem_type_mapping_tbl[idx].done_flag;
2020 		moal_get_system_time(phandle, &sec, &usec);
2021 		PRINTM(MMSG, "Start %s output %u.%06u, please wait...\n",
2022 		       mem_type_mapping_tbl[idx].mem_name, sec, usec);
2023 		do {
2024 			stat = woal_cmd52_rdwr_firmware(phandle, doneflag);
2025 			if (RDWR_STATUS_FAILURE == stat)
2026 				goto done;
2027 			reg_start = dbg_dump_start_reg;
2028 			reg_end = dbg_dump_end_reg;
2029 			for (reg = reg_start; reg <= reg_end; reg++) {
2030 				ret = woal_sdio_readb(phandle, reg, dbg_ptr);
2031 				if (ret) {
2032 					PRINTM(MMSG, "SDIO READ ERR\n");
2033 					goto done;
2034 				}
2035 				if (dbg_ptr < end_ptr)
2036 					dbg_ptr++;
2037 				else
2038 					PRINTM(MINFO,
2039 					       "pre-allocced buf is not enough\n");
2040 			}
2041 			if (RDWR_STATUS_DONE == stat) {
2042 #ifdef MLAN_64BIT
2043 				PRINTM(MMSG,
2044 				       "%s done:"
2045 				       "size = 0x%lx\n",
2046 				       mem_type_mapping_tbl[idx].mem_name,
2047 				       dbg_ptr - mem_type_mapping_tbl[idx]
2048 							 .mem_Ptr);
2049 #else
2050 				PRINTM(MMSG,
2051 				       "%s done:"
2052 				       "size = 0x%x\n",
2053 				       mem_type_mapping_tbl[idx].mem_name,
2054 				       dbg_ptr - mem_type_mapping_tbl[idx]
2055 							 .mem_Ptr);
2056 #endif
2057 				woal_save_dump_info_to_buf(
2058 					phandle,
2059 					mem_type_mapping_tbl[idx].mem_Ptr,
2060 					memory_size,
2061 					mem_type_mapping_tbl[idx].type);
2062 				moal_vfree(phandle,
2063 					   mem_type_mapping_tbl[idx].mem_Ptr);
2064 				mem_type_mapping_tbl[idx].mem_Ptr = NULL;
2065 				break;
2066 			}
2067 		} while (1);
2068 	}
2069 	woal_append_end_block(phandle);
2070 	moal_get_system_time(phandle, &sec, &usec);
2071 	PRINTM(MMSG, "==== DEBUG MODE OUTPUT END: %u.%06u ====\n", sec, usec);
2072 	/* end dump fw memory */
2073 done:
2074 	for (idx = 0; idx < dump_num; idx++) {
2075 		if (mem_type_mapping_tbl[idx].mem_Ptr) {
2076 			moal_vfree(phandle, mem_type_mapping_tbl[idx].mem_Ptr);
2077 			mem_type_mapping_tbl[idx].mem_Ptr = NULL;
2078 		}
2079 	}
2080 	PRINTM(MMSG, "==== DEBUG MODE END ====\n");
2081 	return;
2082 }
2083 
2084 /**
2085  *  @brief This function dump firmware memory to file
2086  *
2087  *  @param phandle   A pointer to moal_handle
2088  *
2089  *  @return         N/A
2090  */
woal_dump_firmware_info_v3(moal_handle * phandle)2091 void woal_dump_firmware_info_v3(moal_handle *phandle)
2092 {
2093 	int ret = 0;
2094 	int tries = 0;
2095 	unsigned int reg, reg_start, reg_end;
2096 	t_u8 *dbg_ptr = NULL;
2097 	t_u8 *temp_Ptr = NULL;
2098 	t_u32 sec, usec;
2099 	t_u8 start_flag = 0;
2100 	t_u8 doneflag = 0;
2101 	rdwr_status stat;
2102 	t_u32 memory_size = 0;
2103 	t_u8 *end_ptr = NULL;
2104 	t_u8 dbg_dump_start_reg = 0;
2105 	t_u8 dbg_dump_end_reg = 0;
2106 	memory_type_mapping *pmem_type_mapping_tbl =
2107 		&mem_type_mapping_tbl_8977_8997;
2108 
2109 	if (!phandle) {
2110 		PRINTM(MERROR, "Could not dump firmwware info\n");
2111 		return;
2112 	}
2113 #ifdef SD9177
2114 	if (IS_SD9177(phandle->card_type)) {
2115 		if (phandle->event_fw_dump) {
2116 			if (RDWR_STATUS_FAILURE !=
2117 			    woal_cmd52_rdwr_firmware(phandle, doneflag)) {
2118 				PRINTM(MMSG,
2119 				       "====SDIO FW DUMP EVENT MODE START ====\n");
2120 				return;
2121 			}
2122 		}
2123 	}
2124 #endif
2125 
2126 	dbg_dump_start_reg = phandle->card_info->dump_fw_start_reg;
2127 	dbg_dump_end_reg = phandle->card_info->dump_fw_end_reg;
2128 
2129 	/* start dump fw memory */
2130 	moal_get_system_time(phandle, &sec, &usec);
2131 	PRINTM(MMSG, "==== DEBUG MODE OUTPUT START: %u.%06u ====\n", sec, usec);
2132 	/* read the number of the memories which will dump */
2133 	if (RDWR_STATUS_FAILURE == woal_cmd52_rdwr_firmware(phandle, doneflag))
2134 		goto done;
2135 
2136 	/** check the reg which indicate dump starting */
2137 	for (reg = dbg_dump_start_reg; reg <= dbg_dump_end_reg; reg++) {
2138 		for (tries = 0; tries < MAX_POLL_TRIES; tries++) {
2139 			ret = woal_sdio_readb(phandle, reg, &start_flag);
2140 			if (ret) {
2141 				PRINTM(MMSG, "SDIO READ ERR\n");
2142 				goto done;
2143 			}
2144 			/** 0 means dump starting*/
2145 			if (start_flag == 0)
2146 				break;
2147 			udelay(100);
2148 		}
2149 		if (tries == MAX_POLL_TRIES) {
2150 			PRINTM(MMSG, "FW not ready to dump\n");
2151 			goto done;
2152 		}
2153 	}
2154 	memory_size = 0xF0000;
2155 	PRINTM(MMSG, "%s_SIZE=0x%x\n", pmem_type_mapping_tbl->mem_name,
2156 	       memory_size);
2157 	ret = moal_vmalloc(phandle, memory_size + 1,
2158 			   (t_u8 **)&pmem_type_mapping_tbl->mem_Ptr);
2159 	if ((ret != MLAN_STATUS_SUCCESS) || !pmem_type_mapping_tbl->mem_Ptr) {
2160 		PRINTM(MERROR, "Error: vmalloc %s buffer failed!!!\n",
2161 		       pmem_type_mapping_tbl->mem_name);
2162 		goto done;
2163 	}
2164 	dbg_ptr = pmem_type_mapping_tbl->mem_Ptr;
2165 	end_ptr = dbg_ptr + memory_size;
2166 	doneflag = pmem_type_mapping_tbl->done_flag;
2167 	moal_get_system_time(phandle, &sec, &usec);
2168 	PRINTM(MMSG, "Start %s output %u.%06u, please wait...\n",
2169 	       pmem_type_mapping_tbl->mem_name, sec, usec);
2170 	do {
2171 		stat = woal_cmd52_rdwr_firmware(phandle, doneflag);
2172 		if (RDWR_STATUS_FAILURE == stat)
2173 			goto done;
2174 		reg_start = dbg_dump_start_reg;
2175 		reg_end = dbg_dump_end_reg;
2176 		for (reg = reg_start; reg <= reg_end; reg++) {
2177 			ret = woal_sdio_readb(phandle, reg, dbg_ptr);
2178 			if (ret) {
2179 				PRINTM(MMSG, "SDIO READ ERR\n");
2180 				goto done;
2181 			}
2182 			dbg_ptr++;
2183 			if (dbg_ptr >= end_ptr) {
2184 				PRINTM(MINFO,
2185 				       "pre-allocced buf is not enough\n");
2186 
2187 				ret = moal_vmalloc(phandle,
2188 						   memory_size + 0x2000 + 1,
2189 						   (t_u8 **)&temp_Ptr);
2190 				if ((ret != MLAN_STATUS_SUCCESS) || !temp_Ptr) {
2191 					PRINTM(MERROR,
2192 					       "Error: vmalloc  buffer failed!!!\n");
2193 					goto done;
2194 				}
2195 
2196 				moal_memcpy_ext(phandle, temp_Ptr,
2197 						pmem_type_mapping_tbl->mem_Ptr,
2198 						memory_size,
2199 						memory_size + 0x2000);
2200 				moal_vfree(phandle,
2201 					   pmem_type_mapping_tbl->mem_Ptr);
2202 				pmem_type_mapping_tbl->mem_Ptr = temp_Ptr;
2203 				temp_Ptr = NULL;
2204 				dbg_ptr = pmem_type_mapping_tbl->mem_Ptr +
2205 					  memory_size;
2206 
2207 				memory_size += 0x2000;
2208 				end_ptr = pmem_type_mapping_tbl->mem_Ptr +
2209 					  memory_size;
2210 			}
2211 		}
2212 		if (RDWR_STATUS_DONE == stat) {
2213 #ifdef MLAN_64BIT
2214 			PRINTM(MMSG,
2215 			       "%s done:"
2216 			       "size = 0x%lx\n",
2217 			       pmem_type_mapping_tbl->mem_name,
2218 			       dbg_ptr - pmem_type_mapping_tbl->mem_Ptr);
2219 #else
2220 			PRINTM(MMSG,
2221 			       "%s done:"
2222 			       "size = 0x%x\n",
2223 			       pmem_type_mapping_tbl->mem_name,
2224 			       dbg_ptr - pmem_type_mapping_tbl->mem_Ptr);
2225 
2226 #endif
2227 			if (phandle->fw_dump_buf) {
2228 				moal_vfree(phandle, phandle->fw_dump_buf);
2229 				phandle->fw_dump_buf = NULL;
2230 				phandle->fw_dump_len = 0;
2231 			}
2232 			phandle->fw_dump_buf = pmem_type_mapping_tbl->mem_Ptr;
2233 			phandle->fw_dump_len =
2234 				dbg_ptr - pmem_type_mapping_tbl->mem_Ptr;
2235 			pmem_type_mapping_tbl->mem_Ptr = NULL;
2236 			break;
2237 		}
2238 	} while (1);
2239 	moal_get_system_time(phandle, &sec, &usec);
2240 	PRINTM(MMSG, "==== DEBUG MODE OUTPUT END: %u.%06u ====\n", sec, usec);
2241 	/* end dump fw memory */
2242 done:
2243 	if (pmem_type_mapping_tbl->mem_Ptr) {
2244 		moal_vfree(phandle, pmem_type_mapping_tbl->mem_Ptr);
2245 		pmem_type_mapping_tbl->mem_Ptr = NULL;
2246 	}
2247 	PRINTM(MMSG, "==== DEBUG MODE END ====\n");
2248 	return;
2249 }
2250 
2251 /**
2252  *  @brief This function reads and displays SDIO registers for debugging
2253  *
2254  *  @param phandle  A pointer to moal_handle
2255  *
2256  *  @return         N/A
2257  */
woal_sdiommc_reg_dbg(moal_handle * phandle)2258 static void woal_sdiommc_reg_dbg(moal_handle *phandle)
2259 {
2260 	int ret = 0;
2261 	t_u8 loop, index = 0, func, data;
2262 	unsigned int reg, reg_start, reg_end;
2263 	unsigned int scratch_reg = phandle->card_info->scratch_reg;
2264 	t_u8 *reg_table = phandle->card_info->dump_reg.reg_table;
2265 	t_u8 reg_table_size = phandle->card_info->dump_reg.reg_table_size;
2266 	char buf[256], *ptr;
2267 
2268 	mlan_pm_wakeup_card(phandle->pmlan_adapter, MTRUE);
2269 	for (loop = 0; loop < 5; loop++) {
2270 		memset(buf, 0, sizeof(buf));
2271 		ptr = buf;
2272 		if (loop == 0) {
2273 			/* Read the registers of SDIO function0 */
2274 			func = loop;
2275 			reg_start = 0;
2276 			reg_end = 9;
2277 		} else if (loop == 1) {
2278 			/* Read the registers of SDIO function1 */
2279 			func = loop;
2280 			reg_start = phandle->card_info->func1_reg_start;
2281 			reg_end = phandle->card_info->func1_reg_end;
2282 		} else if (loop == 2) {
2283 			/* Read specific registers of SDIO function1 */
2284 			index = 0;
2285 			func = 1;
2286 			reg_start = reg_table[index++];
2287 			reg_end = reg_table[reg_table_size - 1];
2288 		} else {
2289 			/* Read the scratch registers of SDIO function1 */
2290 			if (loop == 4)
2291 				mdelay(100);
2292 			func = 1;
2293 			reg_start = scratch_reg;
2294 			reg_end = scratch_reg + 10;
2295 		}
2296 		if (loop != 2)
2297 			ptr += sprintf(ptr, "SDIO Func%d (%#x-%#x): ", func,
2298 				       reg_start, reg_end);
2299 		else
2300 			ptr += sprintf(ptr, "SDIO Func%d: ", func);
2301 		for (reg = reg_start; reg <= reg_end;) {
2302 			if (func == 0)
2303 				ret = woal_sdio_f0_readb(phandle, reg, &data);
2304 			else
2305 				ret = woal_sdio_readb(phandle, reg, &data);
2306 			if (loop == 2)
2307 				ptr += sprintf(ptr, "(%#x) ", reg);
2308 			if (!ret)
2309 				ptr += sprintf(ptr, "%02x ", data);
2310 			else {
2311 				ptr += sprintf(ptr, "ERR");
2312 				break;
2313 			}
2314 			if (loop == 2 && reg < reg_end)
2315 				reg = reg_table[index++];
2316 			else
2317 				reg++;
2318 		}
2319 		PRINTM(MMSG, "%s\n", buf);
2320 	}
2321 	mlan_pm_wakeup_card(phandle->pmlan_adapter, MFALSE);
2322 }
2323 
2324 /**
2325  *  @brief This function dump firmware memory to file
2326  *
2327  *  @param phandle   A pointer to moal_handle
2328  *
2329  *  @return         N/A
2330  */
woal_sdiommc_dump_fw_info(moal_handle * phandle)2331 static void woal_sdiommc_dump_fw_info(moal_handle *phandle)
2332 {
2333 	if (!phandle) {
2334 		PRINTM(MERROR, "Could not dump firmwware info\n");
2335 		return;
2336 	}
2337 	/** cancel all pending commands */
2338 	mlan_ioctl(phandle->pmlan_adapter, NULL);
2339 
2340 	mlan_pm_wakeup_card(phandle->pmlan_adapter, MTRUE);
2341 	phandle->fw_dump = MTRUE;
2342 	if (phandle->card_info->dump_fw_info == DUMP_FW_SDIO_V2) {
2343 		woal_dump_firmware_info_v2(phandle);
2344 	} else if (phandle->card_info->dump_fw_info == DUMP_FW_SDIO_V3) {
2345 		woal_dump_firmware_info_v3(phandle);
2346 		if (phandle->event_fw_dump) {
2347 			phandle->event_fw_dump = MFALSE;
2348 			queue_work(phandle->workqueue, &phandle->main_work);
2349 			phandle->is_fw_dump_timer_set = MTRUE;
2350 			woal_mod_timer(&phandle->fw_dump_timer, MOAL_TIMER_5S);
2351 			return;
2352 		}
2353 	}
2354 #ifdef SD8801
2355 	else {
2356 		woal_dump_firmware_info(phandle);
2357 	}
2358 #endif
2359 	phandle->fw_dump = MFALSE;
2360 	if (!phandle->priv_num)
2361 		return;
2362 	woal_send_fw_dump_complete_event(
2363 		woal_get_priv(phandle, MLAN_BSS_ROLE_ANY));
2364 	mlan_pm_wakeup_card(phandle->pmlan_adapter, MFALSE);
2365 	queue_work(phandle->workqueue, &phandle->main_work);
2366 	woal_process_hang(phandle);
2367 	return;
2368 }
2369 
2370 /**
2371  *  @brief This function save sdio reg info
2372  *
2373  *  @param phandle   A pointer to moal_handle
2374  *  @param buf       A pointer buffer saving log
2375  *
2376  *  @return          The length of this log
2377  */
woal_sdiommc_dump_reg_info(moal_handle * phandle,t_u8 * drv_buf)2378 static int woal_sdiommc_dump_reg_info(moal_handle *phandle, t_u8 *drv_buf)
2379 {
2380 	char *drv_ptr = (char *)drv_buf;
2381 	int ret = 0;
2382 	t_u8 loop, index = 0, func, data;
2383 	unsigned int reg, reg_start, reg_end;
2384 	unsigned int scratch_reg = 0;
2385 	t_u8 *reg_table = NULL;
2386 	t_u8 reg_table_size = 0;
2387 	char buf[256], *ptr;
2388 
2389 	ENTER();
2390 
2391 	if (!phandle || !drv_buf) {
2392 		PRINTM(MMSG, "%s: can't retreive info\n", __func__);
2393 		LEAVE();
2394 		return 0;
2395 	}
2396 
2397 	scratch_reg = phandle->card_info->scratch_reg;
2398 	reg_table = phandle->card_info->dump_reg.reg_table;
2399 	reg_table_size = phandle->card_info->dump_reg.reg_table_size;
2400 
2401 	mlan_pm_wakeup_card(phandle->pmlan_adapter, MTRUE);
2402 
2403 	drv_ptr += sprintf(drv_ptr, "--------sdio_reg_debug_info---------\n");
2404 	for (loop = 0; loop < 5; loop++) {
2405 		memset(buf, 0, sizeof(buf));
2406 		ptr = buf;
2407 		if (loop == 0) {
2408 			/* Read the registers of SDIO function0 */
2409 			func = loop;
2410 			reg_start = 0;
2411 			reg_end = 9;
2412 
2413 		} else if (loop == 1) {
2414 			/* Read the registers of SDIO function1 */
2415 			func = loop;
2416 			reg_start = phandle->card_info->func1_reg_start;
2417 			reg_end = phandle->card_info->func1_reg_end;
2418 		} else if (loop == 2) {
2419 			/* Read specific registers of SDIO function1 */
2420 			index = 0;
2421 			func = 1;
2422 			reg_start = reg_table[index++];
2423 			reg_end = reg_table[reg_table_size - 1];
2424 		} else {
2425 			/* Read the scratch registers of SDIO function1 */
2426 			if (loop == 4)
2427 				mdelay(100);
2428 			func = 1;
2429 			reg_start = scratch_reg;
2430 			reg_end = scratch_reg + 10;
2431 		}
2432 		if (loop != 2)
2433 			ptr += sprintf(ptr, "SDIO Func%d (%#x-%#x): ", func,
2434 				       reg_start, reg_end);
2435 		else
2436 			ptr += sprintf(ptr, "SDIO Func%d: ", func);
2437 		for (reg = reg_start; reg <= reg_end;) {
2438 			if (func == 0)
2439 				ret = woal_sdio_f0_readb(phandle, reg, &data);
2440 			else
2441 				ret = woal_sdio_readb(phandle, reg, &data);
2442 
2443 			if (loop == 2)
2444 				ptr += sprintf(ptr, "(%#x) ", reg);
2445 			if (!ret)
2446 				ptr += sprintf(ptr, "%02x ", data);
2447 			else {
2448 				ptr += sprintf(ptr, "ERR");
2449 				break;
2450 			}
2451 			if (loop == 2 && reg < reg_end)
2452 				reg = reg_table[index++];
2453 			else
2454 				reg++;
2455 		}
2456 		drv_ptr += sprintf(drv_ptr, "%s\n", buf);
2457 	}
2458 
2459 	drv_ptr +=
2460 		sprintf(drv_ptr, "--------sdio_reg_debug_info End---------\n");
2461 	mlan_pm_wakeup_card(phandle->pmlan_adapter, MFALSE);
2462 
2463 	LEAVE();
2464 	return drv_ptr - (char *)drv_buf;
2465 }
2466 
2467 /**
2468  *  @brief This function reset sdio through sdio bus driver
2469  *
2470  *  @param phandle   A pointer to moal_handle
2471  *
2472  *  @return          N/A
2473  */
woal_sdio_reset_hw(moal_handle * handle)2474 void woal_sdio_reset_hw(moal_handle *handle)
2475 {
2476 	struct sdio_mmc_card *card = handle->card;
2477 	struct sdio_func *func = card->func;
2478 	ENTER();
2479 	sdio_claim_host(func);
2480 	sdio_release_irq(card->func);
2481 	sdio_disable_func(card->func);
2482 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)
2483 #if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 18, 0)
2484 	mmc_hw_reset(func->card);
2485 #else
2486 	mmc_hw_reset(func->card->host);
2487 #endif
2488 #endif
2489 
2490 #ifdef MMC_QUIRK_BLKSZ_FOR_BYTE_MODE
2491 	/* The byte mode patch is available in kernel MMC driver
2492 	 * which fixes one issue in MP-A transfer.
2493 	 * bit1: use func->cur_blksize for byte mode
2494 	 */
2495 	func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE;
2496 #endif
2497 #if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)
2498 	func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
2499 #endif
2500 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)
2501 	/* wait for chip fully wake up */
2502 	if (!func->enable_timeout)
2503 		func->enable_timeout = 200;
2504 #endif
2505 	sdio_enable_func(func);
2506 	sdio_claim_irq(func, woal_sdio_interrupt);
2507 	sdio_set_block_size(card->func, MLAN_SDIO_BLOCK_SIZE);
2508 	sdio_release_host(func);
2509 	LEAVE();
2510 	return;
2511 }
2512 
2513 static moal_if_ops sdiommc_ops = {
2514 	.register_dev = woal_sdiommc_register_dev,
2515 	.unregister_dev = woal_sdiommc_unregister_dev,
2516 	.read_reg = woal_sdiommc_read_reg,
2517 	.write_reg = woal_sdiommc_write_reg,
2518 	.read_data_sync = woal_sdiommc_read_data_sync,
2519 	.write_data_sync = woal_sdiommc_write_data_sync,
2520 	.get_fw_name = woal_sdiommc_get_fw_name,
2521 	.dump_fw_info = woal_sdiommc_dump_fw_info,
2522 	.dump_reg_info = woal_sdiommc_dump_reg_info,
2523 	.reg_dbg = woal_sdiommc_reg_dbg,
2524 	.is_second_mac = woal_sdiommc_is_second_mac,
2525 };
2526