1 /******************************************************************************
4 *[Revision Date] 2010-03-01
7 * The program provides SDIO HIF driver
9 * Copyright (C) 2010 MediaTek Incorporation. All Rights Reserved.
10 ******************************************************************************/
19 * Add AEE message support
20 * 1) Show AEE warning(red screen) if SDIO access error occurs
24 * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree
25 * include correct header file upon setting.
28 * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer
29 * 1. eliminaite direct calls to printk in porting layer.
30 * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms.
33 * [WCXRP00000994] [MT6620 Wi-Fi][Driver] dump message for bus error and reset bus error flag while re-initialized
34 * 1. always show error message for SDIO bus errors.
35 * 2. reset bus error flag when re-initialization
38 * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree
39 * add MT6628 related definitions for Linux/Android driver.
42 * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC
43 * add device ID for MT5931.
46 * [WCXRP00000623] [MT6620 Wi-Fi][Driver] use ARCH define to distinguish PC Linux driver
47 * Use CONFIG_X86 instead of PC_LINUX_DRIVER_USE option to have proper compile settting for PC Linux driver
50 * [WCXRP00000592] [MT6620 Wi-Fi][Driver] Support PC Linux Environment Driver Build
51 * Add a compiler option "PC_LINUX_DRIVER_USE" for building driver in PC Linux environment.
54 * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous memory consumption
55 * deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK.
58 * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous memory consumption
59 * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK
60 * 2. Use common coalescing buffer for both TX/RX directions
64 * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message
65 * Toggle non-standard debug messages to comments.
67 * 11 15 2010 jeffrey.chang
68 * [WCXRP00000181] [MT6620 Wi-Fi][Driver] fix the driver message "GLUE_FLAG_HALT skip INT" during unloading
69 * Fix GLUE_FALG_HALT message which cause driver to hang
72 * [WCXRP00000166] [MT6620 Wi-Fi][Driver] use SDIO CMD52 for enabling/disabling interrupt to reduce transaction period
76 * [WCXRP00000166] [MT6620 Wi-Fi][Driver] use SDIO CMD52 for enabling/disabling interrupt to reduce transaction period
77 * change to use CMD52 for enabling/disabling interrupt to reduce SDIO transaction time
79 * 11 01 2010 yarco.yang
80 * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform
81 * Add code to run WlanIST in SDIO callback.
84 * [WCXRP00000122] [MT6620 Wi-Fi][Driver] Preparation for YuSu source tree integration
85 * remove HIF_SDIO_ONE flags because the settings could be merged for runtime detection instead of compile-time.
87 * 10 19 2010 jeffrey.chang
88 * [WCXRP00000120] [MT6620 Wi-Fi][Driver] Refine linux kernel module to the license of MTK propietary and enable MTK HIF by default
89 * Refine linux kernel module to the license of MTK and enable MTK HIF
91 * 08 21 2010 jeffrey.chang
93 * 1) add sdio two setting
94 * 2) bug fix of sdio glue
96 * 08 18 2010 jeffrey.chang
98 * support multi-function sdio
102 * #if defined(__X86__) is not working, change to use #ifdef CONFIG_X86.
106 * add ENE SDIO host workaround for x86 linux platform.
110 * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository.
112 * 06 06 2010 kevin.huang
113 * [WPD00003832][MT6620 5931] Create driver base
114 * [MT6620 5931] Create driver base
116 * 05 07 2010 jeffrey.chang
117 * [WPD00003826]Initial import for Linux port
120 * 03 28 2010 jeffrey.chang
121 * [WPD00003826]Initial import for Linux port
122 * clear sdio interrupt
124 * 03 24 2010 jeffrey.chang
125 * [WPD00003826]Initial import for Linux port
126 * initial import for Linux port
130 /*******************************************************************************
131 * C O M P I L E R F L A G S
132 ********************************************************************************
135 /*******************************************************************************
136 * E X T E R N A L R E F E R E N C E S
137 ********************************************************************************
143 #include "hif_sdio.h"
145 #include <linux/mmc/card.h>
146 #include <linux/mmc/host.h>
147 #include <linux/mmc/sdio.h>
148 #include <linux/mmc/sdio_func.h> /* sdio_readl(), etc */
149 #include <linux/mmc/sdio_ids.h>
152 #include <linux/mm.h>
153 //#ifndef CONFIG_X86 modify by Nicolas Luo
155 #include <asm/memory.h>
159 #include "mt6620_reg.h"
160 #elif defined(MT5931)
161 #include "mt5931_reg.h"
162 #elif defined(MT6628)
163 #include "mt6628_reg.h"
166 #if CFG_DBG_GPIO_PINS/* FIXME: move to platform or custom header */
167 #include <mach/mt6516_gpio.h>
170 /*******************************************************************************
172 ********************************************************************************
175 #define HIF_SDIO_ERR_TITLE_STR "["CHIP_NAME"] SDIO Access Error!"
176 #define HIF_SDIO_ERR_DESC_STR "**SDIO Access Error**\n"
182 * function prototypes
187 mtk_sdio_probe(MTK_WCN_HIF_SDIO_CLTCTX, const MTK_WCN_HIF_SDIO_FUNCINFO *);
190 mtk_sdio_remove(MTK_WCN_HIF_SDIO_CLTCTX);
191 static INT32 mtk_sdio_interrupt(MTK_WCN_HIF_SDIO_CLTCTX);
194 * sdio function info table
197 static MTK_WCN_HIF_SDIO_FUNCINFO funcInfo[] = {
199 { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x020a, 0x1, 512) },
200 { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x020c, 0x2, 512) },
201 { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x018a, 0x1, 512) },
202 { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x018c, 0x2, 512) },
203 #elif defined(MT5931)
204 { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x5931, 0x1, 512) },
205 #elif defined(MT6628)
206 { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x6628, 0x1, 512) },
211 static MTK_WCN_HIF_SDIO_CLTINFO cltInfo = {
212 .func_tbl = funcInfo,
213 .func_tbl_size = sizeof(funcInfo)/sizeof(MTK_WCN_HIF_SDIO_FUNCINFO),
214 .hif_clt_probe = mtk_sdio_probe,
215 .hif_clt_remove = mtk_sdio_remove,
216 .hif_clt_irq = mtk_sdio_interrupt,
221 static const struct sdio_device_id mtk_sdio_ids[] = {
223 { SDIO_DEVICE(0x037a, 0x020a) }, /* Not an SDIO standard class device */
224 { SDIO_DEVICE(0x037a, 0x020b) }, /* Not an SDIO standard class device */
225 { SDIO_DEVICE(0x037a, 0x020c) }, /* Not an SDIO standard class device */
226 #elif defined(MT5931)
227 { SDIO_DEVICE(0x037a, 0x5931) }, /* Not an SDIO standard class device */
228 #elif defined(MT6628)
229 { SDIO_DEVICE(0x037a, 0x6628) }, /* Not an SDIO standard class device */
231 { /* end: all zeroes */ },
234 MODULE_DEVICE_TABLE(sdio, mtk_sdio_ids);
238 /*******************************************************************************
240 ********************************************************************************
244 /*******************************************************************************
245 * P U B L I C D A T A
246 ********************************************************************************
248 extern KAL_WAKE_LOCK_T isr_wakelock;
249 /*******************************************************************************
250 * P R I V A T E D A T A
251 ********************************************************************************
253 static probe_card pfWlanProbe = NULL;
254 static remove_card pfWlanRemove = NULL;
257 #if (MTK_WCN_HIF_SDIO == 0)
258 static struct sdio_driver mtk_sdio_driver = {
259 .name = "wlan", /* "MTK SDIO WLAN Driver" */
260 .id_table = mtk_sdio_ids,
267 #if CFG_DBG_GPIO_PINS
270 UINT_32 dbgPinSTP[] = {
271 GPIO_PLATFORM(33)/* CMFLASH, IDX_ERR J613 */
272 , GPIO_PLATFORM(62)/* EINT3, IDX_TX_THREAD */
273 , GPIO_PLATFORM(80)/* SPI_CS_N, IDX_TX_REQ J613 */
274 , GPIO_PLATFORM(81)/* SPI_SCK, IDX_TX_PORT_WRITE J613 */
275 , GPIO_PLATFORM(17) /* CMRST, IDX_STP_MTX_BT J618 */
276 , GPIO_PLATFORM(18) /* CMPDN, IDX_STP_MTX_FM J613 */
277 , GPIO_PLATFORM(19) /* CMVREF,IDX_STP_MTX_GPS J613 */
278 , GPIO_INVALID /* REMOVED, IDX_STP_MTX_WIFI */
279 , GPIO_INVALID /* REMOVED, IDX_STP_MTX_WMT */
280 , GPIO_PLATFORM(135) /* SCL2, IDX_LOOP_CNT J616 */
281 , GPIO_PLATFORM(136) /* SDA2, IDX_NO_BUF J616 */
282 , GPIO_PLATFORM(30) /* CAM_MECHSH0, IDX_BT_TX, J613 low-active */
283 , GPIO_PLATFORM(31) /* CAM_MECHSH1, IDX_BT_RX, J613 low-active */
284 , GPIO_PLATFORM(124) /* GPS_PWR_EN, ThreadDSPIn [GPS] */
285 , GPIO_PLATFORM(125) /* GPS_SYNC, mtk_sys_msg_recv [GPS] */
286 , GPIO_PLATFORM(21) /* GPS_EINT8, dump_nmea_data [GPS] */
287 , GPIO_PLATFORM(29) /* CAM_STROBE, IDX_GPS_TX, J613 low-active */
288 , GPIO_PLATFORM(20) /*CMHREF, J613 UNUSED */
289 // , GPIO_6516(64) /* EINT5, REMOVED!!! for MT6620-Wi-Fi Int */
290 // , GPIO_6516(122) /* BT_PWR_EN, REMOVED!!! for MT6620-PMU_EN */
291 // , GPIO_6516(123) /* BT_RESET, REMOVED!!! for MT6620-RST */
294 /*******************************************************************************
296 ********************************************************************************
299 /*******************************************************************************
300 * F U N C T I O N D E C L A R A T I O N S
301 ********************************************************************************
304 /*******************************************************************************
306 ********************************************************************************
308 #if CFG_DBG_GPIO_PINS
309 void debug_gpio_init(void)
313 for (i = 0; i < sizeof(dbgPinSTP)/sizeof(dbgPinSTP[0]); ++i) {
314 if (GPIO_INVALID == dbgPinSTP[i]) {
317 //printk(KERN_INFO "[%s] %ld \n", __FUNCTION__, dbgPinSTP[i]);
318 mt_set_gpio_pull_enable(dbgPinSTP[i], 0); /* disable pull */
319 mt_set_gpio_dir(dbgPinSTP[i], GPIO_DIR_OUT); /* set output */
320 mt_set_gpio_mode(dbgPinSTP[i], GPIO_MODE_00); /* set gpio mode */
322 /* toggle twice to check if ok: */
323 mt_set_gpio_out(dbgPinSTP[i], GPIO_OUT_ZERO); /* tie low */
324 mt_set_gpio_out(dbgPinSTP[i], GPIO_OUT_ONE); /* tie high*/
325 mt_set_gpio_out(dbgPinSTP[i], GPIO_OUT_ZERO); /* tie low */
326 mt_set_gpio_out(dbgPinSTP[i], GPIO_OUT_ONE); /* tie high*/
328 //printk(KERN_INFO "[%s] initialization ok \n", __FUNCTION__);
331 void debug_gpio_deinit(void)
334 for (i = 0; i < sizeof(dbgPinSTP)/sizeof(dbgPinSTP[0]); ++i) {
335 if (GPIO_INVALID == dbgPinSTP[i]) {
338 //printk(KERN_INFO "[%s] %ld \n", __FUNCTION__, dbgPinSTP[i]);
339 mt_set_gpio_dir(dbgPinSTP[i], GPIO_DIR_IN);
342 //printk(KERN_INFO "[%s] k\n", __FUNCTION__);
345 void mtk_wcn_stp_debug_gpio_assert(UINT_32 dwIndex, UINT_32 dwMethod)
349 if (dwIndex >= (sizeof(dbgPinSTP)/sizeof(dbgPinSTP[0]))) {
350 //printk(KERN_INFO "[%s] invalid dwIndex(%ld) \n", __FUNCTION__, dwIndex);
354 if (dwIndex > IDX_STP_MAX) {
355 //printk(KERN_INFO "[%s] dwIndex(%ld) > IDX_STP_MAX(%d) \n", __FUNCTION__, dwIndex, IDX_STP_MAX);
358 if (GPIO_INVALID == dbgPinSTP[dwIndex]) {
362 if (dwMethod & DBG_TIE_DIR) {
363 if (dwMethod & DBG_HIGH) {
364 mt_set_gpio_out(dbgPinSTP[dwIndex], GPIO_OUT_ONE);
367 mt_set_gpio_out(dbgPinSTP[dwIndex], GPIO_OUT_ZERO);
372 if (dwMethod & DBG_TOGGLE(0)) {
373 for (i = 0; i < DBG_TOGGLE_NUM(dwMethod); ++i) {
374 mt_set_gpio_out(dbgPinSTP[dwIndex], GPIO_OUT_ZERO);
375 mt_set_gpio_out(dbgPinSTP[dwIndex], GPIO_OUT_ONE);
384 /*----------------------------------------------------------------------------*/
386 * \brief This function is a SDIO interrupt callback function
388 * \param[in] func pointer to SDIO handle
392 /*----------------------------------------------------------------------------*/
396 static INT32 mtk_sdio_interrupt(MTK_WCN_HIF_SDIO_CLTCTX cltCtx)
398 P_GLUE_INFO_T prGlueInfo = NULL;
401 prGlueInfo = mtk_wcn_hif_sdio_get_drvdata(cltCtx);
406 //printk(KERN_INFO DRV_NAME"No glue info in mtk_sdio_interrupt()\n");
407 return (-HIF_SDIO_ERR_FAIL);
410 if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) {
411 //printk(KERN_INFO DRV_NAME"GLUE_FLAG_HALT skip INT\n");
412 ret = mtk_wcn_hif_sdio_writel(cltCtx, MCR_WHLPCR, WHLPCR_INT_EN_CLR);
417 KAL_WAKE_UNLOCK(NULL, &isr_wakelock);
418 KAL_WAKE_LOCK_TIMEOUT(NULL, &isr_wakelock, KAL_HZ/10);
420 ret = mtk_wcn_hif_sdio_writel(cltCtx, MCR_WHLPCR, WHLPCR_INT_EN_CLR);
422 set_bit (GLUE_FLAG_INT_BIT, &prGlueInfo->u4Flag);
424 /* when we got sdio interrupt, we wake up the tx servie thread*/
425 wake_up_interruptible(&prGlueInfo->waitq);
432 static unsigned int in_interrupt = 0;
434 static void mtk_sdio_interrupt(struct sdio_func *func)
436 P_GLUE_INFO_T prGlueInfo = NULL;
440 prGlueInfo = sdio_get_drvdata(func);
444 //printk(KERN_INFO DRV_NAME"No glue info in mtk_sdio_interrupt()\n");
448 if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) {
449 sdio_writel(prGlueInfo->rHifInfo.func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, &ret);
450 //printk(KERN_INFO DRV_NAME"GLUE_FLAG_HALT skip INT\n");
454 sdio_writel(prGlueInfo->rHifInfo.func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, &ret);
457 wlanISR(prGlueInfo->prAdapter, TRUE);
459 if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) {
460 /* Should stop now... skip pending interrupt */
461 //printk(KERN_INFO DRV_NAME"ignore pending interrupt\n");
464 wlanIST(prGlueInfo->prAdapter);
468 set_bit (GLUE_FLAG_INT_BIT, &prGlueInfo->u4Flag);
470 /* when we got sdio interrupt, we wake up the tx servie thread*/
471 wake_up_interruptible(&prGlueInfo->waitq);
475 /*----------------------------------------------------------------------------*/
477 * \brief This function is a SDIO probe function
479 * \param[in] func pointer to SDIO handle
480 * \param[in] id pointer to SDIO device id table
484 /*----------------------------------------------------------------------------*/
488 // FIXME: global variable
489 static const MTK_WCN_HIF_SDIO_FUNCINFO *prFunc;
493 mtk_sdio_probe(MTK_WCN_HIF_SDIO_CLTCTX cltCtx, const MTK_WCN_HIF_SDIO_FUNCINFO *prFuncInfo)
495 INT32 ret = HIF_SDIO_ERR_SUCCESS;
499 if (pfWlanProbe((PVOID) &cltCtx) != WLAN_STATUS_SUCCESS) {
500 //printk(KERN_WARNING DRV_NAME"pfWlanProbe fail!call pfWlanRemove()\n");
502 ret = -(HIF_SDIO_ERR_FAIL);
504 //printk(KERN_INFO DRV_NAME"mtk_wifi_sdio_probe() done(%d)\n", ret);
509 static int mtk_sdio_probe (
510 struct sdio_func *func,
511 const struct sdio_device_id *id
517 //printk(KERN_INFO DRV_NAME "mtk_sdio_probe()\n");
522 //printk(KERN_INFO DRV_NAME "Basic struct size checking...\n");
523 //printk(KERN_INFO DRV_NAME "sizeof(struct device) = %d\n", sizeof(struct device));
524 //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_host) = %d\n", sizeof(struct mmc_host));
525 //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_card) = %d\n", sizeof(struct mmc_card));
526 //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_driver) = %d\n", sizeof(struct mmc_driver));
527 //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_data) = %d\n", sizeof(struct mmc_data));
528 //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_command) = %d\n", sizeof(struct mmc_command));
529 //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_request) = %d\n", sizeof(struct mmc_request));
530 //printk(KERN_INFO DRV_NAME "sizeof(struct sdio_func) = %d\n", sizeof(struct sdio_func));
532 //printk(KERN_INFO DRV_NAME "Card information checking...\n");
533 //printk(KERN_INFO DRV_NAME "func = 0x%p\n", func);
534 //printk(KERN_INFO DRV_NAME "Number of info = %d:\n", func->card->num_info);
536 for (i = 0; i < func->card->num_info; i++) {
537 //printk(KERN_INFO DRV_NAME "info[%d]: %s\n", i, func->card->info[i]);
540 sdio_claim_host(func);
541 ret = sdio_enable_func(func);
542 sdio_release_host(func);
545 //printk(KERN_INFO DRV_NAME"sdio_enable_func failed!\n");
548 //printk(KERN_INFO DRV_NAME"sdio_enable_func done!\n");
550 if (pfWlanProbe((PVOID)func) != WLAN_STATUS_SUCCESS) {
551 //printk(KERN_WARNING DRV_NAME"pfWlanProbe fail!call pfWlanRemove()\n");
556 #if CFG_DBG_GPIO_PINS
557 //printk(KERN_INFO "[%s] init debug gpio, 20100815 \n", __FUNCTION__);
558 /* Debug pins initialization */
564 //printk(KERN_INFO DRV_NAME"mtk_sdio_probe() done(%d)\n", ret);
572 mtk_sdio_remove(MTK_WCN_HIF_SDIO_CLTCTX cltCtx)
574 INT32 ret = HIF_SDIO_ERR_SUCCESS;
575 //printk(KERN_INFO DRV_NAME"pfWlanRemove done\n");
583 struct sdio_func *func
586 //printk(KERN_INFO DRV_NAME"mtk_sdio_remove()\n");
588 #if CFG_DBG_GPIO_PINS
589 //printk(KERN_INFO "[%s] deinit debug gpio \n", __FUNCTION__);
594 //printk(KERN_INFO DRV_NAME"pfWlanRemove done\n");
597 sdio_claim_host(func);
598 sdio_disable_func(func);
599 //printk(KERN_INFO DRV_NAME"sdio_disable_func() done\n");
600 sdio_release_host(func);
602 //printk(KERN_INFO DRV_NAME"mtk_sdio_remove() done\n");
606 #if (MTK_WCN_HIF_SDIO == 0)
609 struct device * pDev,
613 //printk(KERN_INFO "mtk_sdio: mtk_sdio_suspend dev(0x%p)\n", pDev);
614 //printk(KERN_INFO "mtk_sdio: MediaTek SDIO WLAN driver\n");
619 int mtk_sdio_resume (
623 //printk(KERN_INFO "mtk_sdio: mtk_sdio_resume dev(0x%p)\n", pDev);
630 /*----------------------------------------------------------------------------*/
632 * \brief This function will register sdio bus to the os
634 * \param[in] pfProbe Function pointer to detect card
635 * \param[in] pfRemove Function pointer to remove card
637 * \return The result of registering sdio bus
639 /*----------------------------------------------------------------------------*/
651 //printk(KERN_INFO "mtk_sdio: MediaTek SDIO WLAN driver\n");
652 //printk(KERN_INFO "mtk_sdio: Copyright MediaTek Inc.\n");
654 pfWlanProbe = pfProbe;
655 pfWlanRemove = pfRemove;
658 /* register MTK sdio client */
659 ret = ((mtk_wcn_hif_sdio_client_reg(&cltInfo) == HIF_SDIO_ERR_SUCCESS) ? WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE);
661 mtk_sdio_driver.probe = mtk_sdio_probe;
662 mtk_sdio_driver.remove = mtk_sdio_remove;
664 mtk_sdio_driver.drv.suspend = mtk_sdio_suspend;
665 mtk_sdio_driver.drv.resume = mtk_sdio_resume;
667 ret = (sdio_register_driver(&mtk_sdio_driver) == 0) ? WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE;
671 } /* end of glRegisterBus() */
674 /*----------------------------------------------------------------------------*/
676 * \brief This function will unregister sdio bus to the os
678 * \param[in] pfRemove Function pointer to remove card
682 /*----------------------------------------------------------------------------*/
692 /* unregister MTK sdio client */
693 mtk_wcn_hif_sdio_client_unreg(&cltInfo);
695 sdio_unregister_driver(&mtk_sdio_driver);
699 } /* end of glUnregisterBus() */
702 /*----------------------------------------------------------------------------*/
704 * \brief This function stores hif related info, which is initialized before.
706 * \param[in] prGlueInfo Pointer to glue info structure
707 * \param[in] u4Cookie Pointer to UINT_32 memory base variable for _HIF_HPI
711 /*----------------------------------------------------------------------------*/
714 P_GLUE_INFO_T prGlueInfo,
718 P_GL_HIF_INFO_T prHif = NULL;
720 prHif = &prGlueInfo->rHifInfo;
723 //prHif->prFuncInfo = ((MTK_WCN_HIF_SDIO_FUNCINFO *) u4Cookie);
724 prHif->prFuncInfo = prFunc;
725 prHif->cltCtx = *((MTK_WCN_HIF_SDIO_CLTCTX *) u4Cookie);
726 mtk_wcn_hif_sdio_set_drvdata(prHif->cltCtx, prGlueInfo);
729 prHif->func = (struct sdio_func *) u4Cookie;
731 //printk(KERN_INFO DRV_NAME"prHif->func->dev = 0x%p\n", &prHif->func->dev);
732 //printk(KERN_INFO DRV_NAME"prHif->func->vendor = 0x%04X\n", prHif->func->vendor);
733 //printk(KERN_INFO DRV_NAME"prHif->func->device = 0x%04X\n", prHif->func->device);
734 //printk(KERN_INFO DRV_NAME"prHif->func->func = 0x%04X\n", prHif->func->num);
736 sdio_set_drvdata(prHif->func, prGlueInfo);
738 SET_NETDEV_DEV(prGlueInfo->prDevHandler, &prHif->func->dev);
742 } /* end of glSetHifInfo() */
744 /*----------------------------------------------------------------------------*/
746 * \brief This function clears hif related info.
748 * \param[in] prGlueInfo Pointer to glue info structure
752 /*----------------------------------------------------------------------------*/
755 P_GLUE_INFO_T prGlueInfo
758 //P_GL_HIF_INFO_T prHif = NULL;
759 //ASSERT(prGlueInfo);
760 //prHif = &prGlueInfo->rHifInfo;
763 } /* end of glClearHifInfo() */
766 /*----------------------------------------------------------------------------*/
768 * \brief Initialize bus operation and hif related information, request resources.
770 * \param[out] pvData A pointer to HIF-specific data type buffer.
771 * For eHPI, pvData is a pointer to UINT_32 type and stores a
772 * mapped base address.
776 /*----------------------------------------------------------------------------*/
782 #if (MTK_WCN_HIF_SDIO == 0)
784 struct sdio_func *func = NULL;
788 func = (struct sdio_func *) pvData;
790 sdio_claim_host(func);
791 ret = sdio_set_block_size(func, 512);
792 sdio_release_host(func);
795 //printk(KERN_INFO DRV_NAME"sdio_set_block_size 512 failed!\n");
798 //printk(KERN_INFO DRV_NAME"sdio_set_block_size 512 done!\n");
801 //printk(KERN_INFO DRV_NAME"param: func->cur_blksize(%d)\n", func->cur_blksize);
802 //printk(KERN_INFO DRV_NAME"param: func->max_blksize(%d)\n", func->max_blksize);
803 //printk(KERN_INFO DRV_NAME"param: func->card->host->max_blk_size(%d)\n", func->card->host->max_blk_size);
804 //printk(KERN_INFO DRV_NAME"param: func->card->host->max_blk_count(%d)\n", func->card->host->max_blk_count);
807 } /* end of glBusInit() */
810 /*----------------------------------------------------------------------------*/
812 * \brief Stop bus operation and release resources.
814 * \param[in] pvData A pointer to struct net_device.
818 /*----------------------------------------------------------------------------*/
826 } /* end of glBusRelease() */
829 /*----------------------------------------------------------------------------*/
831 * \brief Setup bus interrupt operation and interrupt handler for os.
833 * \param[in] pvData A pointer to struct net_device.
834 * \param[in] pfnIsr A pointer to interrupt handler function.
835 * \param[in] pvCookie Private data for pfnIsr function.
837 * \retval WLAN_STATUS_SUCCESS if success
838 * NEGATIVE_VALUE if fail
840 /*----------------------------------------------------------------------------*/
850 #if (MTK_WCN_HIF_SDIO == 0)
851 struct net_device *prNetDevice = NULL;
852 P_GLUE_INFO_T prGlueInfo = NULL;
853 P_GL_HIF_INFO_T prHifInfo = NULL;
859 prNetDevice = (struct net_device *) pvData;
860 prGlueInfo = (P_GLUE_INFO_T) pvCookie;
866 prHifInfo = &prGlueInfo->rHifInfo;
868 sdio_claim_host(prHifInfo->func);
869 ret = sdio_claim_irq(prHifInfo->func, mtk_sdio_interrupt);
870 sdio_release_host(prHifInfo->func);
873 struct net_device *prNetDevice = NULL;
874 P_GLUE_INFO_T prGlueInfo = NULL;
880 prNetDevice = (struct net_device *) pvData;
882 prGlueInfo = (P_GLUE_INFO_T) pvCookie;
888 mtk_wcn_hif_sdio_enable_irq(prGlueInfo->rHifInfo.cltCtx, MTK_WCN_BOOL_TRUE);
892 } /* end of glBusSetIrq() */
895 /*----------------------------------------------------------------------------*/
897 * \brief Stop bus interrupt operation and disable interrupt handling for os.
899 * \param[in] pvData A pointer to struct net_device.
900 * \param[in] pvCookie Private data for pfnIsr function.
904 /*----------------------------------------------------------------------------*/
911 #if (MTK_WCN_HIF_SDIO == 0)
912 struct net_device *prNetDevice = NULL;
913 P_GLUE_INFO_T prGlueInfo = NULL;
914 P_GL_HIF_INFO_T prHifInfo = NULL;
919 //printk(KERN_INFO DRV_NAME"%s null pvData\n", __FUNCTION__);
922 prNetDevice = (struct net_device *) pvData;
923 prGlueInfo = (P_GLUE_INFO_T) pvCookie;
926 //printk(KERN_INFO DRV_NAME"%s no glue info\n", __FUNCTION__);
930 prHifInfo = &prGlueInfo->rHifInfo;
932 sdio_claim_host(prHifInfo->func);
933 ret = sdio_release_irq(prHifInfo->func);
934 sdio_release_host(prHifInfo->func);
937 struct net_device *prNetDevice = NULL;
938 P_GLUE_INFO_T prGlueInfo = NULL;
942 //printk(KERN_INFO DRV_NAME"%s null pvData\n", __FUNCTION__);
945 prNetDevice = (struct net_device *) pvData;
947 prGlueInfo = (P_GLUE_INFO_T) pvCookie;
950 //printk(KERN_INFO DRV_NAME"%s no glue info\n", __FUNCTION__);
954 mtk_wcn_hif_sdio_enable_irq(prGlueInfo->rHifInfo.cltCtx, MTK_WCN_BOOL_FALSE);
958 } /* end of glBusreeIrq() */
961 /*----------------------------------------------------------------------------*/
963 * \brief Read a 32-bit device register
965 * \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure.
966 * \param[in] u4Register Register offset
967 * \param[in] pu4Value Pointer to variable used to store read value
969 * \retval TRUE operation success
970 * \retval FALSE operation fail
972 /*----------------------------------------------------------------------------*/
975 IN P_GLUE_INFO_T prGlueInfo,
976 IN UINT_32 u4Register,
977 OUT PUINT_32 pu4Value
987 ret = mtk_wcn_hif_sdio_readl(prGlueInfo->rHifInfo.cltCtx, u4Register, (PUINT32) pu4Value);
990 sdio_claim_host(prGlueInfo->rHifInfo.func);
994 *pu4Value = sdio_readl(prGlueInfo->rHifInfo.func, u4Register, &ret);
997 printk("gwl =-==============> sdio_readl retry %d!\n", a);
1002 if (!in_interrupt) {
1003 sdio_release_host(prGlueInfo->rHifInfo.func);
1008 kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_readl() reports error: %x", ret);
1009 DBGLOG(HAL, ERROR, ("sdio_readl() reports error: %x", ret));
1012 return (ret) ? FALSE : TRUE;
1013 } /* end of kalDevRegRead() */
1016 /*----------------------------------------------------------------------------*/
1018 * \brief Write a 32-bit device register
1020 * \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure.
1021 * \param[in] u4Register Register offset
1022 * \param[in] u4Value Value to be written
1024 * \retval TRUE operation success
1025 * \retval FALSE operation fail
1027 /*----------------------------------------------------------------------------*/
1030 IN P_GLUE_INFO_T prGlueInfo,
1031 IN UINT_32 u4Register,
1040 #if MTK_WCN_HIF_SDIO
1041 ret = mtk_wcn_hif_sdio_writel(prGlueInfo->rHifInfo.cltCtx, u4Register, u4Value);
1043 if (!in_interrupt) {
1044 sdio_claim_host(prGlueInfo->rHifInfo.func);
1048 sdio_writel(prGlueInfo->rHifInfo.func, u4Value, u4Register, &ret);
1049 if (ret && a < 10) {
1051 printk("gwl =-==============> sdio_writel retry %d!\n", a);
1056 if (!in_interrupt) {
1057 sdio_release_host(prGlueInfo->rHifInfo.func);
1062 kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_writel() reports error: %x", ret);
1063 DBGLOG(HAL, ERROR, ("sdio_writel() reports error: %x", ret));
1066 return (ret) ? FALSE : TRUE;
1067 } /* end of kalDevRegWrite() */
1070 /*----------------------------------------------------------------------------*/
1072 * \brief Read device I/O port
1074 * \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure.
1075 * \param[in] u2Port I/O port offset
1076 * \param[in] u2Len Length to be read
1077 * \param[out] pucBuf Pointer to read buffer
1078 * \param[in] u2ValidOutBufSize Length of the buffer valid to be accessed
1080 * \retval TRUE operation success
1081 * \retval FALSE operation fail
1083 /*----------------------------------------------------------------------------*/
1086 IN P_GLUE_INFO_T prGlueInfo,
1090 IN UINT_16 u2ValidOutBufSize
1093 P_GL_HIF_INFO_T prHifInfo = NULL;
1094 PUINT_8 pucDst = NULL;
1099 #if (MTK_WCN_HIF_SDIO == 0)
1100 struct sdio_func *prSdioFunc = NULL;
1104 //printk(KERN_INFO DRV_NAME"++kalDevPortRead++ buf:0x%p, port:0x%x, length:%d\n", pucBuf, u2Port, u2Len);
1108 prHifInfo = &prGlueInfo->rHifInfo;
1113 ASSERT(u2Len <= u2ValidOutBufSize);
1115 #if (MTK_WCN_HIF_SDIO == 0)
1116 prSdioFunc = prHifInfo->func;
1118 ASSERT(prSdioFunc->cur_blksize > 0);
1120 if (!in_interrupt) {
1121 sdio_claim_host(prSdioFunc);
1124 /* Split buffer into multiple single block to workaround hifsys */
1125 while (count >= prSdioFunc->cur_blksize) {
1126 count -= prSdioFunc->cur_blksize;
1129 if (count > 0 && bNum > 0) {
1134 ret = sdio_readsb(prSdioFunc, pucDst, u2Port, prSdioFunc->cur_blksize * bNum);
1137 /* ENE workaround */
1140 sdio_writel(prSdioFunc, 0x0, SDIO_X86_WORKAROUND_WRITE_MCR, &tmp);
1147 int aligned_count = (count+3) & (~0x3L);
1148 ret = sdio_readsb(prSdioFunc, pucDst, u2Port, aligned_count);
1150 ret = sdio_readsb(prSdioFunc, pucDst, u2Port, count);
1154 if (!in_interrupt) {
1155 sdio_release_host(prSdioFunc);
1159 /* Split buffer into multiple single block to workaround hifsys */
1160 while (count >= (prGlueInfo->rHifInfo).prFuncInfo->blk_sz) {
1161 count -= ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz);
1164 if (count > 0 && bNum > 0) {
1169 ret = mtk_wcn_hif_sdio_read_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucDst,
1170 ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz) * bNum);
1173 ret = mtk_wcn_hif_sdio_read_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucDst, count);
1178 kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_readsb() reports error: %x", ret);
1179 DBGLOG(HAL, ERROR, ("sdio_readsb() reports error: %x", ret));
1182 return (ret) ? FALSE : TRUE;
1183 } /* end of kalDevPortRead() */
1186 /*----------------------------------------------------------------------------*/
1188 * \brief Write device I/O port
1190 * \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure.
1191 * \param[in] u2Port I/O port offset
1192 * \param[in] u2Len Length to be write
1193 * \param[in] pucBuf Pointer to write buffer
1194 * \param[in] u2ValidInBufSize Length of the buffer valid to be accessed
1196 * \retval TRUE operation success
1197 * \retval FALSE operation fail
1199 /*----------------------------------------------------------------------------*/
1202 IN P_GLUE_INFO_T prGlueInfo,
1206 IN UINT_16 u2ValidInBufSize
1209 P_GL_HIF_INFO_T prHifInfo = NULL;
1210 PUINT_8 pucSrc = NULL;
1215 #if (MTK_WCN_HIF_SDIO == 0)
1216 struct sdio_func *prSdioFunc = NULL;
1220 //printk(KERN_INFO DRV_NAME"++kalDevPortWrite++ buf:0x%p, port:0x%x, length:%d\n", pucBuf, u2Port, u2Len);
1224 prHifInfo = &prGlueInfo->rHifInfo;
1229 ASSERT(u2Len <= u2ValidInBufSize);
1231 #if (MTK_WCN_HIF_SDIO == 0)
1232 prSdioFunc = prHifInfo->func;
1233 ASSERT(prSdioFunc->cur_blksize > 0);
1235 if (!in_interrupt) {
1236 sdio_claim_host(prSdioFunc);
1239 /* Split buffer into multiple single block to workaround hifsys */
1240 while (count >= prSdioFunc->cur_blksize) {
1241 count -= prSdioFunc->cur_blksize;
1244 if (count > 0 && bNum > 0) {
1248 if (bNum > 0) { // block mode
1249 ret = sdio_writesb(prSdioFunc, u2Port, pucSrc, prSdioFunc->cur_blksize * bNum);
1252 /* ENE workaround */
1255 sdio_writel(prSdioFunc, 0x0, SDIO_X86_WORKAROUND_WRITE_MCR, &tmp);
1262 int aligned_count = (count+3) & (~0x3L);
1263 ret = sdio_writesb(prSdioFunc, u2Port, pucSrc, aligned_count);
1265 ret = sdio_writesb(prSdioFunc, u2Port, pucSrc, count);
1269 if (!in_interrupt) {
1270 sdio_release_host(prSdioFunc);
1273 /* Split buffer into multiple single block to workaround hifsys */
1274 while (count >= ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz)) {
1275 count -= ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz);
1278 if (count > 0 && bNum > 0) {
1282 if (bNum > 0) { // block mode
1283 ret = mtk_wcn_hif_sdio_write_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucSrc,
1284 ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz) * bNum);
1287 ret = mtk_wcn_hif_sdio_write_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucSrc, count);
1292 kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_writesb() reports error: %x", ret);
1293 DBGLOG(HAL, ERROR, ("sdio_writesb() reports error: %x", ret));
1296 return (ret) ? FALSE : TRUE;
1297 } /* end of kalDevPortWrite() */
1300 /*----------------------------------------------------------------------------*/
1302 * \brief Write device I/O port in byte with CMD52
1304 * \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure.
1305 * \param[in] u4Addr I/O port offset
1306 * \param[in] ucData Single byte of data to be written
1308 * \retval TRUE operation success
1309 * \retval FALSE operation fail
1311 /*----------------------------------------------------------------------------*/
1313 kalDevWriteWithSdioCmd52 (
1314 IN P_GLUE_INFO_T prGlueInfo,
1321 #if (MTK_WCN_HIF_SDIO == 0)
1322 if (!in_interrupt) {
1323 sdio_claim_host(prGlueInfo->rHifInfo.func);
1326 sdio_writeb(prGlueInfo->rHifInfo.func, ucData, u4Addr, &ret);
1328 if (!in_interrupt) {
1329 sdio_release_host(prGlueInfo->rHifInfo.func);
1332 ret = mtk_wcn_hif_sdio_writeb(prGlueInfo->rHifInfo.cltCtx, u4Addr, ucData);
1336 kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_writeb() reports error: %x", ret);
1337 DBGLOG(HAL, ERROR, ("sdio_writeb() reports error: %x", ret));
1340 return (ret) ? FALSE : TRUE;
1342 } /* end of kalDevWriteWithSdioCmd52() */
1347 IN P_GLUE_INFO_T prGlueInfo,
1348 IN UINT_32 ePowerMode