1 /******************************************************************************
4 *[Revision Date] 2010-03-01
7 * The program provides SDIO HIF driver
9 * Copyright (C) 2010 MediaTek Incorporation. All Rights Reserved.
10 ******************************************************************************/
13 /*******************************************************************************
16 * BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND
17 * AGREES THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK
18 * SOFTWARE") RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE
19 * PROVIDED TO BUYER ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY
20 * DISCLAIMS ANY AND ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT
21 * LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
22 * PARTICULAR PURPOSE OR NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE
23 * ANY WARRANTY WHATSOEVER WITH RESPECT TO THE SOFTWARE OF ANY THIRD PARTY
24 * WHICH MAY BE USED BY, INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK
25 * SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY
26 * WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE
27 * FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S SPECIFICATION OR TO
28 * CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
30 * BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
31 * LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL
32 * BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT
33 * ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY
34 * BUYER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
36 * THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
37 * WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT
38 * OF LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING
39 * THEREOF AND RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN
40 * FRANCISCO, CA, UNDER THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE
42 ********************************************************************************
49 ** [WCXRP00001269] [MT6620 Wi-Fi][Driver] cfg80211 porting merge back to DaVinci
53 ** [WCXRP00001269] [MT6620 Wi-Fi][Driver] cfg80211 porting merge back to DaVinci
54 ** cfg80211 support merge back from ALPS.JB to DaVinci - MT6620 Driver v2.3 branch.
58 * Add AEE message support
59 * 1) Show AEE warning(red screen) if SDIO access error occurs
63 * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree
64 * include correct header file upon setting.
67 * [WCXRP00001098] [MT6620 Wi-Fi][Driver] Replace printk by DBG LOG macros in linux porting layer
68 * 1. eliminaite direct calls to printk in porting layer.
69 * 2. replaced by DBGLOG, which would be XLOG on ALPS platforms.
72 * [WCXRP00000994] [MT6620 Wi-Fi][Driver] dump message for bus error and reset bus error flag while re-initialized
73 * 1. always show error message for SDIO bus errors.
74 * 2. reset bus error flag when re-initialization
77 * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree
78 * add MT6628 related definitions for Linux/Android driver.
81 * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC
82 * add device ID for MT5931.
85 * [WCXRP00000623] [MT6620 Wi-Fi][Driver] use ARCH define to distinguish PC Linux driver
86 * Use CONFIG_X86 instead of PC_LINUX_DRIVER_USE option to have proper compile settting for PC Linux driver
89 * [WCXRP00000592] [MT6620 Wi-Fi][Driver] Support PC Linux Environment Driver Build
90 * Add a compiler option "PC_LINUX_DRIVER_USE" for building driver in PC Linux environment.
93 * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous memory consumption
94 * deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK.
97 * [WCXRP00000559] [MT6620 Wi-Fi][Driver] Combine TX/RX DMA buffers into a single one to reduce physically continuous memory consumption
98 * 1. deprecate CFG_HANDLE_IST_IN_SDIO_CALLBACK
99 * 2. Use common coalescing buffer for both TX/RX directions
102 * 03 07 2011 terry.wu
103 * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message
104 * Toggle non-standard debug messages to comments.
106 * 11 15 2010 jeffrey.chang
107 * [WCXRP00000181] [MT6620 Wi-Fi][Driver] fix the driver message "GLUE_FLAG_HALT skip INT" during unloading
108 * Fix GLUE_FALG_HALT message which cause driver to hang
111 * [WCXRP00000166] [MT6620 Wi-Fi][Driver] use SDIO CMD52 for enabling/disabling interrupt to reduce transaction period
115 * [WCXRP00000166] [MT6620 Wi-Fi][Driver] use SDIO CMD52 for enabling/disabling interrupt to reduce transaction period
116 * change to use CMD52 for enabling/disabling interrupt to reduce SDIO transaction time
118 * 11 01 2010 yarco.yang
119 * [WCXRP00000149] [MT6620 WI-Fi][Driver]Fine tune performance on MT6516 platform
120 * Add code to run WlanIST in SDIO callback.
123 * [WCXRP00000122] [MT6620 Wi-Fi][Driver] Preparation for YuSu source tree integration
124 * remove HIF_SDIO_ONE flags because the settings could be merged for runtime detection instead of compile-time.
126 * 10 19 2010 jeffrey.chang
127 * [WCXRP00000120] [MT6620 Wi-Fi][Driver] Refine linux kernel module to the license of MTK propietary and enable MTK HIF by default
128 * Refine linux kernel module to the license of MTK and enable MTK HIF
130 * 08 21 2010 jeffrey.chang
132 * 1) add sdio two setting
133 * 2) bug fix of sdio glue
135 * 08 18 2010 jeffrey.chang
137 * support multi-function sdio
141 * #if defined(__X86__) is not working, change to use #ifdef CONFIG_X86.
145 * add ENE SDIO host workaround for x86 linux platform.
149 * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository.
151 * 06 06 2010 kevin.huang
152 * [WPD00003832][MT6620 5931] Create driver base
153 * [MT6620 5931] Create driver base
155 * 05 07 2010 jeffrey.chang
156 * [WPD00003826]Initial import for Linux port
159 * 03 28 2010 jeffrey.chang
160 * [WPD00003826]Initial import for Linux port
161 * clear sdio interrupt
163 * 03 24 2010 jeffrey.chang
164 * [WPD00003826]Initial import for Linux port
165 * initial import for Linux port
169 /*******************************************************************************
170 * C O M P I L E R F L A G S
171 ********************************************************************************
174 /*******************************************************************************
175 * E X T E R N A L R E F E R E N C E S
176 ********************************************************************************
182 #include "hif_sdio.h"
184 #include <linux/mmc/card.h>
185 #include <linux/mmc/host.h>
186 #include <linux/mmc/sdio.h>
187 #include <linux/mmc/sdio_func.h> /* sdio_readl(), etc */
188 #include <linux/mmc/sdio_ids.h>
191 #include <linux/mm.h>
193 #include <asm/memory.h>
197 #include "mt6620_reg.h"
198 #elif defined(MT5931)
199 #include "mt5931_reg.h"
200 #elif defined(MT6628)
201 #include "mt6628_reg.h"
204 #if CFG_DBG_GPIO_PINS/* FIXME: move to platform or custom header */
205 #include <mach/mt6516_gpio.h>
208 /*******************************************************************************
210 ********************************************************************************
213 #define HIF_SDIO_ERR_TITLE_STR "["CHIP_NAME"] SDIO Access Error!"
214 #define HIF_SDIO_ERR_DESC_STR "**SDIO Access Error**\n"
220 * function prototypes
225 mtk_sdio_probe(MTK_WCN_HIF_SDIO_CLTCTX, const MTK_WCN_HIF_SDIO_FUNCINFO *);
228 mtk_sdio_remove(MTK_WCN_HIF_SDIO_CLTCTX);
229 static INT32 mtk_sdio_interrupt(MTK_WCN_HIF_SDIO_CLTCTX);
232 * sdio function info table
235 static MTK_WCN_HIF_SDIO_FUNCINFO funcInfo[] = {
237 { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x020a, 0x1, 512) },
238 { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x020c, 0x2, 512) },
239 { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x018a, 0x1, 512) },
240 { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x018c, 0x2, 512) },
241 #elif defined(MT5931)
242 { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x5931, 0x1, 512) },
243 #elif defined(MT6628)
244 { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x6628, 0x1, 512) },
249 static MTK_WCN_HIF_SDIO_CLTINFO cltInfo = {
250 .func_tbl = funcInfo,
251 .func_tbl_size = sizeof(funcInfo)/sizeof(MTK_WCN_HIF_SDIO_FUNCINFO),
252 .hif_clt_probe = mtk_sdio_probe,
253 .hif_clt_remove = mtk_sdio_remove,
254 .hif_clt_irq = mtk_sdio_interrupt,
259 static const struct sdio_device_id mtk_sdio_ids[] = {
261 { SDIO_DEVICE(0x037a, 0x020a) }, /* Not an SDIO standard class device */
262 { SDIO_DEVICE(0x037a, 0x020b) }, /* Not an SDIO standard class device */
263 { SDIO_DEVICE(0x037a, 0x020c) }, /* Not an SDIO standard class device */
264 #elif defined(MT5931)
265 { SDIO_DEVICE(0x037a, 0x5931) }, /* Not an SDIO standard class device */
266 #elif defined(MT6628)
267 { SDIO_DEVICE(0x037a, 0x6628) }, /* Not an SDIO standard class device */
269 { /* end: all zeroes */ },
272 MODULE_DEVICE_TABLE(sdio, mtk_sdio_ids);
276 /*******************************************************************************
278 ********************************************************************************
282 /*******************************************************************************
283 * P U B L I C D A T A
284 ********************************************************************************
287 /*******************************************************************************
288 * P R I V A T E D A T A
289 ********************************************************************************
291 static probe_card pfWlanProbe = NULL;
292 static remove_card pfWlanRemove = NULL;
295 #if (MTK_WCN_HIF_SDIO == 0)
296 static struct sdio_driver mtk_sdio_driver = {
297 .name = "wlan", /* "MTK SDIO WLAN Driver" */
298 .id_table = mtk_sdio_ids,
305 #if CFG_DBG_GPIO_PINS
308 UINT_32 dbgPinSTP[] = {
309 GPIO_PLATFORM(33)/* CMFLASH, IDX_ERR J613 */
310 , GPIO_PLATFORM(62)/* EINT3, IDX_TX_THREAD */
311 , GPIO_PLATFORM(80)/* SPI_CS_N, IDX_TX_REQ J613 */
312 , GPIO_PLATFORM(81)/* SPI_SCK, IDX_TX_PORT_WRITE J613 */
313 , GPIO_PLATFORM(17) /* CMRST, IDX_STP_MTX_BT J618 */
314 , GPIO_PLATFORM(18) /* CMPDN, IDX_STP_MTX_FM J613 */
315 , GPIO_PLATFORM(19) /* CMVREF,IDX_STP_MTX_GPS J613 */
316 , GPIO_INVALID /* REMOVED, IDX_STP_MTX_WIFI */
317 , GPIO_INVALID /* REMOVED, IDX_STP_MTX_WMT */
318 , GPIO_PLATFORM(135) /* SCL2, IDX_LOOP_CNT J616 */
319 , GPIO_PLATFORM(136) /* SDA2, IDX_NO_BUF J616 */
320 , GPIO_PLATFORM(30) /* CAM_MECHSH0, IDX_BT_TX, J613 low-active */
321 , GPIO_PLATFORM(31) /* CAM_MECHSH1, IDX_BT_RX, J613 low-active */
322 , GPIO_PLATFORM(124) /* GPS_PWR_EN, ThreadDSPIn [GPS] */
323 , GPIO_PLATFORM(125) /* GPS_SYNC, mtk_sys_msg_recv [GPS] */
324 , GPIO_PLATFORM(21) /* GPS_EINT8, dump_nmea_data [GPS] */
325 , GPIO_PLATFORM(29) /* CAM_STROBE, IDX_GPS_TX, J613 low-active */
326 , GPIO_PLATFORM(20) /*CMHREF, J613 UNUSED */
327 // , GPIO_6516(64) /* EINT5, REMOVED!!! for MT6620-Wi-Fi Int */
328 // , GPIO_6516(122) /* BT_PWR_EN, REMOVED!!! for MT6620-PMU_EN */
329 // , GPIO_6516(123) /* BT_RESET, REMOVED!!! for MT6620-RST */
332 /*******************************************************************************
334 ********************************************************************************
337 /*******************************************************************************
338 * F U N C T I O N D E C L A R A T I O N S
339 ********************************************************************************
342 /*******************************************************************************
344 ********************************************************************************
346 #if CFG_DBG_GPIO_PINS
347 void debug_gpio_init(void)
351 for (i = 0; i < sizeof(dbgPinSTP)/sizeof(dbgPinSTP[0]); ++i) {
352 if (GPIO_INVALID == dbgPinSTP[i]) {
355 //printk(KERN_INFO "[%s] %ld \n", __FUNCTION__, dbgPinSTP[i]);
356 mt_set_gpio_pull_enable(dbgPinSTP[i], 0); /* disable pull */
357 mt_set_gpio_dir(dbgPinSTP[i], GPIO_DIR_OUT); /* set output */
358 mt_set_gpio_mode(dbgPinSTP[i], GPIO_MODE_00); /* set gpio mode */
360 /* toggle twice to check if ok: */
361 mt_set_gpio_out(dbgPinSTP[i], GPIO_OUT_ZERO); /* tie low */
362 mt_set_gpio_out(dbgPinSTP[i], GPIO_OUT_ONE); /* tie high*/
363 mt_set_gpio_out(dbgPinSTP[i], GPIO_OUT_ZERO); /* tie low */
364 mt_set_gpio_out(dbgPinSTP[i], GPIO_OUT_ONE); /* tie high*/
366 //printk(KERN_INFO "[%s] initialization ok \n", __FUNCTION__);
369 void debug_gpio_deinit(void)
372 for (i = 0; i < sizeof(dbgPinSTP)/sizeof(dbgPinSTP[0]); ++i) {
373 if (GPIO_INVALID == dbgPinSTP[i]) {
376 //printk(KERN_INFO "[%s] %ld \n", __FUNCTION__, dbgPinSTP[i]);
377 mt_set_gpio_dir(dbgPinSTP[i], GPIO_DIR_IN);
380 //printk(KERN_INFO "[%s] k\n", __FUNCTION__);
383 void mtk_wcn_stp_debug_gpio_assert(UINT_32 dwIndex, UINT_32 dwMethod)
387 if (dwIndex >= (sizeof(dbgPinSTP)/sizeof(dbgPinSTP[0]))) {
388 //printk(KERN_INFO "[%s] invalid dwIndex(%ld) \n", __FUNCTION__, dwIndex);
392 if (dwIndex > IDX_STP_MAX) {
393 //printk(KERN_INFO "[%s] dwIndex(%ld) > IDX_STP_MAX(%d) \n", __FUNCTION__, dwIndex, IDX_STP_MAX);
396 if (GPIO_INVALID == dbgPinSTP[dwIndex]) {
400 if (dwMethod & DBG_TIE_DIR) {
401 if (dwMethod & DBG_HIGH) {
402 mt_set_gpio_out(dbgPinSTP[dwIndex], GPIO_OUT_ONE);
405 mt_set_gpio_out(dbgPinSTP[dwIndex], GPIO_OUT_ZERO);
410 if (dwMethod & DBG_TOGGLE(0)) {
411 for (i = 0; i < DBG_TOGGLE_NUM(dwMethod); ++i) {
412 mt_set_gpio_out(dbgPinSTP[dwIndex], GPIO_OUT_ZERO);
413 mt_set_gpio_out(dbgPinSTP[dwIndex], GPIO_OUT_ONE);
422 /*----------------------------------------------------------------------------*/
424 * \brief This function is a SDIO interrupt callback function
426 * \param[in] func pointer to SDIO handle
430 /*----------------------------------------------------------------------------*/
434 static INT32 mtk_sdio_interrupt(MTK_WCN_HIF_SDIO_CLTCTX cltCtx)
436 P_GLUE_INFO_T prGlueInfo = NULL;
439 prGlueInfo = mtk_wcn_hif_sdio_get_drvdata(cltCtx);
444 //printk(KERN_INFO DRV_NAME"No glue info in mtk_sdio_interrupt()\n");
445 return (-HIF_SDIO_ERR_FAIL);
448 if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) {
449 //printk(KERN_INFO DRV_NAME"GLUE_FLAG_HALT skip INT\n");
450 ret = mtk_wcn_hif_sdio_writel(cltCtx, MCR_WHLPCR, WHLPCR_INT_EN_CLR);
454 ret = mtk_wcn_hif_sdio_writel(cltCtx, MCR_WHLPCR, WHLPCR_INT_EN_CLR);
456 set_bit (GLUE_FLAG_INT_BIT, &prGlueInfo->u4Flag);
458 /* when we got sdio interrupt, we wake up the tx servie thread*/
459 wake_up_interruptible(&prGlueInfo->waitq);
466 static unsigned int in_interrupt = 0;
468 static void mtk_sdio_interrupt(struct sdio_func *func)
470 P_GLUE_INFO_T prGlueInfo = NULL;
474 prGlueInfo = sdio_get_drvdata(func);
478 //printk(KERN_INFO DRV_NAME"No glue info in mtk_sdio_interrupt()\n");
482 if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) {
483 sdio_writel(prGlueInfo->rHifInfo.func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, &ret);
484 //printk(KERN_INFO DRV_NAME"GLUE_FLAG_HALT skip INT\n");
488 sdio_writel(prGlueInfo->rHifInfo.func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, &ret);
491 wlanISR(prGlueInfo->prAdapter, TRUE);
493 if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) {
494 /* Should stop now... skip pending interrupt */
495 //printk(KERN_INFO DRV_NAME"ignore pending interrupt\n");
498 wlanIST(prGlueInfo->prAdapter);
502 set_bit (GLUE_FLAG_INT_BIT, &prGlueInfo->u4Flag);
504 /* when we got sdio interrupt, we wake up the tx servie thread*/
505 wake_up_interruptible(&prGlueInfo->waitq);
509 /*----------------------------------------------------------------------------*/
511 * \brief This function is a SDIO probe function
513 * \param[in] func pointer to SDIO handle
514 * \param[in] id pointer to SDIO device id table
518 /*----------------------------------------------------------------------------*/
522 // FIXME: global variable
523 static const MTK_WCN_HIF_SDIO_FUNCINFO *prFunc;
527 mtk_sdio_probe(MTK_WCN_HIF_SDIO_CLTCTX cltCtx, const MTK_WCN_HIF_SDIO_FUNCINFO *prFuncInfo)
529 INT32 ret = HIF_SDIO_ERR_SUCCESS;
533 if (pfWlanProbe((PVOID) &cltCtx) != WLAN_STATUS_SUCCESS) {
534 //printk(KERN_WARNING DRV_NAME"pfWlanProbe fail!call pfWlanRemove()\n");
536 ret = -(HIF_SDIO_ERR_FAIL);
538 //printk(KERN_INFO DRV_NAME"mtk_wifi_sdio_probe() done(%d)\n", ret);
543 static int mtk_sdio_probe (
544 struct sdio_func *func,
545 const struct sdio_device_id *id
551 //printk(KERN_INFO DRV_NAME "mtk_sdio_probe()\n");
556 //printk(KERN_INFO DRV_NAME "Basic struct size checking...\n");
557 //printk(KERN_INFO DRV_NAME "sizeof(struct device) = %d\n", sizeof(struct device));
558 //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_host) = %d\n", sizeof(struct mmc_host));
559 //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_card) = %d\n", sizeof(struct mmc_card));
560 //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_driver) = %d\n", sizeof(struct mmc_driver));
561 //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_data) = %d\n", sizeof(struct mmc_data));
562 //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_command) = %d\n", sizeof(struct mmc_command));
563 //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_request) = %d\n", sizeof(struct mmc_request));
564 //printk(KERN_INFO DRV_NAME "sizeof(struct sdio_func) = %d\n", sizeof(struct sdio_func));
566 //printk(KERN_INFO DRV_NAME "Card information checking...\n");
567 //printk(KERN_INFO DRV_NAME "func = 0x%p\n", func);
568 //printk(KERN_INFO DRV_NAME "Number of info = %d:\n", func->card->num_info);
570 for (i = 0; i < func->card->num_info; i++) {
571 //printk(KERN_INFO DRV_NAME "info[%d]: %s\n", i, func->card->info[i]);
574 sdio_claim_host(func);
575 ret = sdio_enable_func(func);
576 sdio_release_host(func);
579 //printk(KERN_INFO DRV_NAME"sdio_enable_func failed!\n");
582 //printk(KERN_INFO DRV_NAME"sdio_enable_func done!\n");
584 if (pfWlanProbe((PVOID)func) != WLAN_STATUS_SUCCESS) {
585 //printk(KERN_WARNING DRV_NAME"pfWlanProbe fail!call pfWlanRemove()\n");
590 #if CFG_DBG_GPIO_PINS
591 //printk(KERN_INFO "[%s] init debug gpio, 20100815 \n", __FUNCTION__);
592 /* Debug pins initialization */
598 //printk(KERN_INFO DRV_NAME"mtk_sdio_probe() done(%d)\n", ret);
606 mtk_sdio_remove(MTK_WCN_HIF_SDIO_CLTCTX cltCtx)
608 INT32 ret = HIF_SDIO_ERR_SUCCESS;
609 //printk(KERN_INFO DRV_NAME"pfWlanRemove done\n");
617 struct sdio_func *func
620 //printk(KERN_INFO DRV_NAME"mtk_sdio_remove()\n");
622 #if CFG_DBG_GPIO_PINS
623 //printk(KERN_INFO "[%s] deinit debug gpio \n", __FUNCTION__);
628 //printk(KERN_INFO DRV_NAME"pfWlanRemove done\n");
631 sdio_claim_host(func);
632 sdio_disable_func(func);
633 //printk(KERN_INFO DRV_NAME"sdio_disable_func() done\n");
634 sdio_release_host(func);
636 //printk(KERN_INFO DRV_NAME"mtk_sdio_remove() done\n");
640 #if (MTK_WCN_HIF_SDIO == 0)
643 struct device * pDev,
647 //printk(KERN_INFO "mtk_sdio: mtk_sdio_suspend dev(0x%p)\n", pDev);
648 //printk(KERN_INFO "mtk_sdio: MediaTek SDIO WLAN driver\n");
653 int mtk_sdio_resume (
657 //printk(KERN_INFO "mtk_sdio: mtk_sdio_resume dev(0x%p)\n", pDev);
663 static const struct dev_pm_ops mtk_sdio_pmops = {
664 .suspend = mtk_sdio_suspend,
665 .resume = mtk_sdio_resume,
667 /*----------------------------------------------------------------------------*/
669 * \brief This function will register sdio bus to the os
671 * \param[in] pfProbe Function pointer to detect card
672 * \param[in] pfRemove Function pointer to remove card
674 * \return The result of registering sdio bus
676 /*----------------------------------------------------------------------------*/
688 //printk(KERN_INFO "mtk_sdio: MediaTek SDIO WLAN driver\n");
689 //printk(KERN_INFO "mtk_sdio: Copyright MediaTek Inc.\n");
691 pfWlanProbe = pfProbe;
692 pfWlanRemove = pfRemove;
695 /* register MTK sdio client */
696 ret = ((mtk_wcn_hif_sdio_client_reg(&cltInfo) == HIF_SDIO_ERR_SUCCESS) ? WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE);
698 mtk_sdio_driver.probe = mtk_sdio_probe;
699 mtk_sdio_driver.remove = mtk_sdio_remove;
701 //mtk_sdio_driver.drv.suspend = mtk_sdio_suspend;
702 //mtk_sdio_driver.drv.resume = mtk_sdio_resume;
703 mtk_sdio_driver.drv.pm = &mtk_sdio_pmops;
704 ret = (sdio_register_driver(&mtk_sdio_driver) == 0) ? WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE;
709 } /* end of glRegisterBus() */
712 /*----------------------------------------------------------------------------*/
714 * \brief This function will unregister sdio bus to the os
716 * \param[in] pfRemove Function pointer to remove card
720 /*----------------------------------------------------------------------------*/
730 /* unregister MTK sdio client */
731 mtk_wcn_hif_sdio_client_unreg(&cltInfo);
733 sdio_unregister_driver(&mtk_sdio_driver);
737 } /* end of glUnregisterBus() */
740 /*----------------------------------------------------------------------------*/
742 * \brief This function stores hif related info, which is initialized before.
744 * \param[in] prGlueInfo Pointer to glue info structure
745 * \param[in] u4Cookie Pointer to UINT_32 memory base variable for _HIF_HPI
749 /*----------------------------------------------------------------------------*/
752 P_GLUE_INFO_T prGlueInfo,
756 P_GL_HIF_INFO_T prHif = NULL;
758 prHif = &prGlueInfo->rHifInfo;
761 //prHif->prFuncInfo = ((MTK_WCN_HIF_SDIO_FUNCINFO *) u4Cookie);
762 prHif->prFuncInfo = prFunc;
763 prHif->cltCtx = *((MTK_WCN_HIF_SDIO_CLTCTX *) u4Cookie);
764 mtk_wcn_hif_sdio_set_drvdata(prHif->cltCtx, prGlueInfo);
767 prHif->func = (struct sdio_func *) u4Cookie;
769 //printk(KERN_INFO DRV_NAME"prHif->func->dev = 0x%p\n", &prHif->func->dev);
770 //printk(KERN_INFO DRV_NAME"prHif->func->vendor = 0x%04X\n", prHif->func->vendor);
771 //printk(KERN_INFO DRV_NAME"prHif->func->device = 0x%04X\n", prHif->func->device);
772 //printk(KERN_INFO DRV_NAME"prHif->func->func = 0x%04X\n", prHif->func->num);
774 sdio_set_drvdata(prHif->func, prGlueInfo);
776 SET_NETDEV_DEV(prGlueInfo->prDevHandler, &prHif->func->dev);
780 } /* end of glSetHifInfo() */
782 /*----------------------------------------------------------------------------*/
784 * \brief This function clears hif related info.
786 * \param[in] prGlueInfo Pointer to glue info structure
790 /*----------------------------------------------------------------------------*/
793 P_GLUE_INFO_T prGlueInfo
796 //P_GL_HIF_INFO_T prHif = NULL;
797 //ASSERT(prGlueInfo);
798 //prHif = &prGlueInfo->rHifInfo;
801 } /* end of glClearHifInfo() */
804 /*----------------------------------------------------------------------------*/
806 * \brief Initialize bus operation and hif related information, request resources.
808 * \param[out] pvData A pointer to HIF-specific data type buffer.
809 * For eHPI, pvData is a pointer to UINT_32 type and stores a
810 * mapped base address.
814 /*----------------------------------------------------------------------------*/
820 #if (MTK_WCN_HIF_SDIO == 0)
822 struct sdio_func *func = NULL;
826 func = (struct sdio_func *) pvData;
828 sdio_claim_host(func);
829 ret = sdio_set_block_size(func, 512);
830 sdio_release_host(func);
833 //printk(KERN_INFO DRV_NAME"sdio_set_block_size 512 failed!\n");
836 //printk(KERN_INFO DRV_NAME"sdio_set_block_size 512 done!\n");
839 //printk(KERN_INFO DRV_NAME"param: func->cur_blksize(%d)\n", func->cur_blksize);
840 //printk(KERN_INFO DRV_NAME"param: func->max_blksize(%d)\n", func->max_blksize);
841 //printk(KERN_INFO DRV_NAME"param: func->card->host->max_blk_size(%d)\n", func->card->host->max_blk_size);
842 //printk(KERN_INFO DRV_NAME"param: func->card->host->max_blk_count(%d)\n", func->card->host->max_blk_count);
845 } /* end of glBusInit() */
848 /*----------------------------------------------------------------------------*/
850 * \brief Stop bus operation and release resources.
852 * \param[in] pvData A pointer to struct net_device.
856 /*----------------------------------------------------------------------------*/
864 } /* end of glBusRelease() */
867 /*----------------------------------------------------------------------------*/
869 * \brief Setup bus interrupt operation and interrupt handler for os.
871 * \param[in] pvData A pointer to struct net_device.
872 * \param[in] pfnIsr A pointer to interrupt handler function.
873 * \param[in] pvCookie Private data for pfnIsr function.
875 * \retval WLAN_STATUS_SUCCESS if success
876 * NEGATIVE_VALUE if fail
878 /*----------------------------------------------------------------------------*/
888 #if (MTK_WCN_HIF_SDIO == 0)
889 struct net_device *prNetDevice = NULL;
890 P_GLUE_INFO_T prGlueInfo = NULL;
891 P_GL_HIF_INFO_T prHifInfo = NULL;
897 prNetDevice = (struct net_device *) pvData;
898 prGlueInfo = (P_GLUE_INFO_T) pvCookie;
904 prHifInfo = &prGlueInfo->rHifInfo;
906 sdio_claim_host(prHifInfo->func);
907 ret = sdio_claim_irq(prHifInfo->func, mtk_sdio_interrupt);
908 sdio_release_host(prHifInfo->func);
911 } /* end of glBusSetIrq() */
914 /*----------------------------------------------------------------------------*/
916 * \brief Stop bus interrupt operation and disable interrupt handling for os.
918 * \param[in] pvData A pointer to struct net_device.
919 * \param[in] pvCookie Private data for pfnIsr function.
923 /*----------------------------------------------------------------------------*/
930 #if (MTK_WCN_HIF_SDIO == 0)
931 struct net_device *prNetDevice = NULL;
932 P_GLUE_INFO_T prGlueInfo = NULL;
933 P_GL_HIF_INFO_T prHifInfo = NULL;
938 //printk(KERN_INFO DRV_NAME"%s null pvData\n", __FUNCTION__);
941 prNetDevice = (struct net_device *) pvData;
942 prGlueInfo = (P_GLUE_INFO_T) pvCookie;
945 //printk(KERN_INFO DRV_NAME"%s no glue info\n", __FUNCTION__);
949 prHifInfo = &prGlueInfo->rHifInfo;
951 sdio_claim_host(prHifInfo->func);
952 ret = sdio_release_irq(prHifInfo->func);
953 sdio_release_host(prHifInfo->func);
957 } /* end of glBusreeIrq() */
960 /*----------------------------------------------------------------------------*/
962 * \brief Read a 32-bit device register
964 * \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure.
965 * \param[in] u4Register Register offset
966 * \param[in] pu4Value Pointer to variable used to store read value
968 * \retval TRUE operation success
969 * \retval FALSE operation fail
971 /*----------------------------------------------------------------------------*/
974 IN P_GLUE_INFO_T prGlueInfo,
975 IN UINT_32 u4Register,
976 OUT PUINT_32 pu4Value
985 ret = mtk_wcn_hif_sdio_readl(prGlueInfo->rHifInfo.cltCtx, u4Register, (PUINT32) pu4Value);
988 sdio_claim_host(prGlueInfo->rHifInfo.func);
991 *pu4Value = sdio_readl(prGlueInfo->rHifInfo.func, u4Register, &ret);
994 sdio_release_host(prGlueInfo->rHifInfo.func);
999 kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_readl() reports error: %x", ret);
1000 DBGLOG(HAL, ERROR, ("sdio_readl() reports error: %x", ret));
1003 return (ret) ? FALSE : TRUE;
1004 } /* end of kalDevRegRead() */
1007 /*----------------------------------------------------------------------------*/
1009 * \brief Write a 32-bit device register
1011 * \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure.
1012 * \param[in] u4Register Register offset
1013 * \param[in] u4Value Value to be written
1015 * \retval TRUE operation success
1016 * \retval FALSE operation fail
1018 /*----------------------------------------------------------------------------*/
1021 IN P_GLUE_INFO_T prGlueInfo,
1022 IN UINT_32 u4Register,
1030 #if MTK_WCN_HIF_SDIO
1031 ret = mtk_wcn_hif_sdio_writel(prGlueInfo->rHifInfo.cltCtx, u4Register, u4Value);
1033 if (!in_interrupt) {
1034 sdio_claim_host(prGlueInfo->rHifInfo.func);
1037 sdio_writel(prGlueInfo->rHifInfo.func, u4Value, u4Register, &ret);
1039 if (!in_interrupt) {
1040 sdio_release_host(prGlueInfo->rHifInfo.func);
1045 kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_writel() reports error: %x", ret);
1046 DBGLOG(HAL, ERROR, ("sdio_writel() reports error: %x", ret));
1049 return (ret) ? FALSE : TRUE;
1050 } /* end of kalDevRegWrite() */
1053 /*----------------------------------------------------------------------------*/
1055 * \brief Read device I/O port
1057 * \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure.
1058 * \param[in] u2Port I/O port offset
1059 * \param[in] u2Len Length to be read
1060 * \param[out] pucBuf Pointer to read buffer
1061 * \param[in] u2ValidOutBufSize Length of the buffer valid to be accessed
1063 * \retval TRUE operation success
1064 * \retval FALSE operation fail
1066 /*----------------------------------------------------------------------------*/
1069 IN P_GLUE_INFO_T prGlueInfo,
1073 IN UINT_16 u2ValidOutBufSize
1076 P_GL_HIF_INFO_T prHifInfo = NULL;
1077 PUINT_8 pucDst = NULL;
1082 #if (MTK_WCN_HIF_SDIO == 0)
1083 struct sdio_func *prSdioFunc = NULL;
1087 //printk(KERN_INFO DRV_NAME"++kalDevPortRead++ buf:0x%p, port:0x%x, length:%d\n", pucBuf, u2Port, u2Len);
1091 prHifInfo = &prGlueInfo->rHifInfo;
1096 ASSERT(u2Len <= u2ValidOutBufSize);
1098 #if (MTK_WCN_HIF_SDIO == 0)
1099 prSdioFunc = prHifInfo->func;
1101 ASSERT(prSdioFunc->cur_blksize > 0);
1103 if (!in_interrupt) {
1104 sdio_claim_host(prSdioFunc);
1107 /* Split buffer into multiple single block to workaround hifsys */
1108 while (count >= prSdioFunc->cur_blksize) {
1109 count -= prSdioFunc->cur_blksize;
1112 if (count > 0 && bNum > 0) {
1117 ret = sdio_readsb(prSdioFunc, pucDst, u2Port, prSdioFunc->cur_blksize * bNum);
1120 /* ENE workaround */
1123 sdio_writel(prSdioFunc, 0x0, SDIO_X86_WORKAROUND_WRITE_MCR, &tmp);
1129 ret = sdio_readsb(prSdioFunc, pucDst, u2Port, count);
1132 if (!in_interrupt) {
1133 sdio_release_host(prSdioFunc);
1137 /* Split buffer into multiple single block to workaround hifsys */
1138 while (count >= (prGlueInfo->rHifInfo).prFuncInfo->blk_sz) {
1139 count -= ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz);
1142 if (count > 0 && bNum > 0) {
1147 ret = mtk_wcn_hif_sdio_read_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucDst,
1148 ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz) * bNum);
1151 ret = mtk_wcn_hif_sdio_read_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucDst, count);
1156 kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_readsb() reports error: %x", ret);
1157 DBGLOG(HAL, ERROR, ("sdio_readsb() reports error: %x", ret));
1160 return (ret) ? FALSE : TRUE;
1161 } /* end of kalDevPortRead() */
1164 /*----------------------------------------------------------------------------*/
1166 * \brief Write device I/O port
1168 * \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure.
1169 * \param[in] u2Port I/O port offset
1170 * \param[in] u2Len Length to be write
1171 * \param[in] pucBuf Pointer to write buffer
1172 * \param[in] u2ValidInBufSize Length of the buffer valid to be accessed
1174 * \retval TRUE operation success
1175 * \retval FALSE operation fail
1177 /*----------------------------------------------------------------------------*/
1180 IN P_GLUE_INFO_T prGlueInfo,
1184 IN UINT_16 u2ValidInBufSize
1187 P_GL_HIF_INFO_T prHifInfo = NULL;
1188 PUINT_8 pucSrc = NULL;
1193 #if (MTK_WCN_HIF_SDIO == 0)
1194 struct sdio_func *prSdioFunc = NULL;
1198 //printk(KERN_INFO DRV_NAME"++kalDevPortWrite++ buf:0x%p, port:0x%x, length:%d\n", pucBuf, u2Port, u2Len);
1202 prHifInfo = &prGlueInfo->rHifInfo;
1207 ASSERT(u2Len <= u2ValidInBufSize);
1209 #if (MTK_WCN_HIF_SDIO == 0)
1210 prSdioFunc = prHifInfo->func;
1211 ASSERT(prSdioFunc->cur_blksize > 0);
1213 if (!in_interrupt) {
1214 sdio_claim_host(prSdioFunc);
1217 /* Split buffer into multiple single block to workaround hifsys */
1218 while (count >= prSdioFunc->cur_blksize) {
1219 count -= prSdioFunc->cur_blksize;
1222 if (count > 0 && bNum > 0) {
1226 count = (count+3)/4*4;
1227 if (bNum > 0) { // block mode
1228 ret = sdio_writesb(prSdioFunc, u2Port, pucSrc, prSdioFunc->cur_blksize * bNum);
1231 /* ENE workaround */
1234 sdio_writel(prSdioFunc, 0x0, SDIO_X86_WORKAROUND_WRITE_MCR, &tmp);
1241 ret = sdio_writesb(prSdioFunc, u2Port, pucSrc, count);
1244 if (!in_interrupt) {
1245 sdio_release_host(prSdioFunc);
1248 /* Split buffer into multiple single block to workaround hifsys */
1249 while (count >= ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz)) {
1250 count -= ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz);
1253 if (count > 0 && bNum > 0) {
1257 if (bNum > 0) { // block mode
1258 ret = mtk_wcn_hif_sdio_write_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucSrc,
1259 ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz) * bNum);
1262 ret = mtk_wcn_hif_sdio_write_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucSrc, count);
1267 kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_writesb() reports error: %x", ret);
1268 DBGLOG(HAL, ERROR, ("sdio_writesb() reports error: %x", ret));
1271 return (ret) ? FALSE : TRUE;
1272 } /* end of kalDevPortWrite() */
1275 /*----------------------------------------------------------------------------*/
1277 * \brief Write device I/O port in byte with CMD52
1279 * \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure.
1280 * \param[in] u4Addr I/O port offset
1281 * \param[in] ucData Single byte of data to be written
1283 * \retval TRUE operation success
1284 * \retval FALSE operation fail
1286 /*----------------------------------------------------------------------------*/
1288 kalDevWriteWithSdioCmd52 (
1289 IN P_GLUE_INFO_T prGlueInfo,
1296 #if (MTK_WCN_HIF_SDIO == 0)
1297 if (!in_interrupt) {
1298 sdio_claim_host(prGlueInfo->rHifInfo.func);
1301 sdio_writeb(prGlueInfo->rHifInfo.func, ucData, u4Addr, &ret);
1303 if (!in_interrupt) {
1304 sdio_release_host(prGlueInfo->rHifInfo.func);
1307 ret = mtk_wcn_hif_sdio_writeb(prGlueInfo->rHifInfo.cltCtx, u4Addr, ucData);
1311 kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_writeb() reports error: %x", ret);
1312 DBGLOG(HAL, ERROR, ("sdio_writeb() reports error: %x", ret));
1315 return (ret) ? FALSE : TRUE;
1317 } /* end of kalDevWriteWithSdioCmd52() */
1322 IN P_GLUE_INFO_T prGlueInfo,
1323 IN UINT_32 ePowerMode