support different wifi bt chip auto compatible
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / combo_mt66xx / mt6620 / wlan / os / linux / hif / sdio / sdio.c
1 /******************************************************************************
2 *[File]             sdio.c
3 *[Version]          v1.0
4 *[Revision Date]    2010-03-01
5 *[Author]
6 *[Description]
7 *    The program provides SDIO HIF driver
8 *[Copyright]
9 *    Copyright (C) 2010 MediaTek Incorporation. All Rights Reserved.
10 ******************************************************************************/
11
12
13
14 /*
15 ** $Log: sdio.c $
16  *
17  * 04 12 2012 terry.wu
18  * NULL
19  * Add AEE message support
20  * 1) Show AEE warning(red screen) if SDIO access error occurs
21
22  *
23  * 02 14 2012 cp.wu
24  * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree
25  * include correct header file upon setting.
26  *
27  * 11 10 2011 cp.wu
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.
31  *
32  * 09 20 2011 cp.wu
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
36  *
37  * 08 17 2011 cp.wu
38  * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree
39  * add MT6628 related definitions for Linux/Android driver.
40  *
41  * 05 18 2011 cp.wu
42  * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC
43  * add device ID for MT5931.
44  *
45  * 04 08 2011 pat.lu
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
48  *
49  * 03 22 2011 pat.lu
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.
52  *
53  * 03 18 2011 cp.wu
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.
56  *
57  * 03 15 2011 cp.wu
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
61  *
62  *
63  * 03 07 2011 terry.wu
64  * [WCXRP00000521] [MT6620 Wi-Fi][Driver] Remove non-standard debug message
65  * Toggle non-standard debug messages to comments.
66  *
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
70  *
71  * 11 08 2010 cp.wu
72  * [WCXRP00000166] [MT6620 Wi-Fi][Driver] use SDIO CMD52 for enabling/disabling interrupt to reduce transaction period
73  * correct typo
74  *
75  * 11 08 2010 cp.wu
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
78  *
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.
82  *
83  * 10 19 2010 cp.wu
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.
86  *
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
90  *
91  * 08 21 2010 jeffrey.chang
92  * NULL
93  * 1) add sdio two setting
94  * 2) bug fix of sdio glue
95  *
96  * 08 18 2010 jeffrey.chang
97  * NULL
98  * support multi-function sdio
99  *
100  * 08 18 2010 cp.wu
101  * NULL
102  * #if defined(__X86__) is not working, change to use #ifdef CONFIG_X86.
103  *
104  * 08 17 2010 cp.wu
105  * NULL
106  * add ENE SDIO host workaround for x86 linux platform.
107  *
108  * 07 08 2010 cp.wu
109  *
110  * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository.
111  *
112  * 06 06 2010 kevin.huang
113  * [WPD00003832][MT6620 5931] Create driver base
114  * [MT6620 5931] Create driver base
115  *
116  * 05 07 2010 jeffrey.chang
117  * [WPD00003826]Initial import for Linux port
118  * Fix hotplug bug
119  *
120  * 03 28 2010 jeffrey.chang
121  * [WPD00003826]Initial import for Linux port
122  * clear sdio interrupt
123  *
124  * 03 24 2010 jeffrey.chang
125  * [WPD00003826]Initial import for Linux port
126  * initial import for Linux port
127 **
128 */
129
130 /*******************************************************************************
131 *                         C O M P I L E R   F L A G S
132 ********************************************************************************
133 */
134
135 /*******************************************************************************
136 *                    E X T E R N A L   R E F E R E N C E S
137 ********************************************************************************
138 */
139
140 #include "gl_os.h"
141
142 #if MTK_WCN_HIF_SDIO
143 #include "hif_sdio.h"
144 #else
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>
150 #endif
151
152 #include <linux/mm.h>
153 #ifdef CONFIG_ARM
154 #include <asm/memory.h>
155 #endif
156
157 #if defined(MT6620)
158     #include "mt6620_reg.h"
159 #elif defined(MT5931)
160     #include "mt5931_reg.h"
161 #elif defined(MT6628)
162     #include "mt6628_reg.h"
163 #endif
164
165 #if CFG_DBG_GPIO_PINS/* FIXME: move to platform or custom header */
166 #include <mach/mt6516_gpio.h>
167 #endif
168
169 /*******************************************************************************
170 *                              C O N S T A N T S
171 ********************************************************************************
172 */
173
174 #define HIF_SDIO_ERR_TITLE_STR              "["CHIP_NAME"] SDIO Access Error!"
175 #define HIF_SDIO_ERR_DESC_STR               "**SDIO Access Error**\n"
176
177 #if MTK_WCN_HIF_SDIO
178
179
180 /*
181  * function prototypes
182  *
183  */
184
185 static INT32
186 mtk_sdio_probe(MTK_WCN_HIF_SDIO_CLTCTX, const MTK_WCN_HIF_SDIO_FUNCINFO *);
187
188 static INT32
189 mtk_sdio_remove(MTK_WCN_HIF_SDIO_CLTCTX);
190 static INT32 mtk_sdio_interrupt(MTK_WCN_HIF_SDIO_CLTCTX);
191
192 /*
193  * sdio function info table
194  */
195
196 static MTK_WCN_HIF_SDIO_FUNCINFO funcInfo[] = {
197 #if defined(MT6620)
198     { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x020a, 0x1, 512) },
199     { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x020c, 0x2, 512) },
200     { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x018a, 0x1, 512) },
201     { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x018c, 0x2, 512) },
202 #elif defined(MT5931)
203     { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x5931, 0x1, 512) },
204 #elif defined(MT6628)
205     { MTK_WCN_HIF_SDIO_FUNC(0x037a, 0x6628, 0x1, 512) },
206 #endif
207 };
208
209
210 static MTK_WCN_HIF_SDIO_CLTINFO cltInfo = {
211     .func_tbl = funcInfo,
212     .func_tbl_size = sizeof(funcInfo)/sizeof(MTK_WCN_HIF_SDIO_FUNCINFO),
213     .hif_clt_probe = mtk_sdio_probe,
214     .hif_clt_remove = mtk_sdio_remove,
215     .hif_clt_irq = mtk_sdio_interrupt,
216 };
217
218 #else
219
220 static const struct sdio_device_id mtk_sdio_ids[] = {
221 #if defined(MT6620)
222         { SDIO_DEVICE(0x037a, 0x020a) }, /* Not an SDIO standard class device */
223         { SDIO_DEVICE(0x037a, 0x020b) }, /* Not an SDIO standard class device */
224         { SDIO_DEVICE(0x037a, 0x020c) }, /* Not an SDIO standard class device */
225 #elif defined(MT5931)
226         { SDIO_DEVICE(0x037a, 0x5931) }, /* Not an SDIO standard class device */
227 #elif defined(MT6628)
228         { SDIO_DEVICE(0x037a, 0x6628) }, /* Not an SDIO standard class device */
229 #endif
230         { /* end: all zeroes */ },
231 };
232
233 MODULE_DEVICE_TABLE(sdio, mtk_sdio_ids);
234
235 #endif
236
237 /*******************************************************************************
238 *                             D A T A   T Y P E S
239 ********************************************************************************
240 */
241
242
243 /*******************************************************************************
244 *                            P U B L I C   D A T A
245 ********************************************************************************
246 */
247
248 /*******************************************************************************
249 *                           P R I V A T E   D A T A
250 ********************************************************************************
251 */
252 static probe_card pfWlanProbe = NULL;
253 static remove_card pfWlanRemove = NULL;
254
255
256 #if (MTK_WCN_HIF_SDIO == 0)
257 static struct sdio_driver mtk_sdio_driver = {
258         .name           = "wlan", /* "MTK SDIO WLAN Driver" */
259         .id_table       = mtk_sdio_ids,
260         .probe          = NULL,
261         .remove         = NULL,
262 };
263 #endif
264
265
266 #if CFG_DBG_GPIO_PINS
267
268 /* debug pins */
269 UINT_32 dbgPinSTP[] = {
270     GPIO_PLATFORM(33)/* CMFLASH, IDX_ERR J613 */
271     , GPIO_PLATFORM(62)/* EINT3, IDX_TX_THREAD */
272     , GPIO_PLATFORM(80)/* SPI_CS_N, IDX_TX_REQ J613 */
273     , GPIO_PLATFORM(81)/* SPI_SCK, IDX_TX_PORT_WRITE J613 */
274     , GPIO_PLATFORM(17) /* CMRST, IDX_STP_MTX_BT J618 */
275     , GPIO_PLATFORM(18) /* CMPDN, IDX_STP_MTX_FM J613 */
276     , GPIO_PLATFORM(19) /* CMVREF,IDX_STP_MTX_GPS J613 */
277     , GPIO_INVALID /* REMOVED, IDX_STP_MTX_WIFI */
278     , GPIO_INVALID /* REMOVED, IDX_STP_MTX_WMT */
279     , GPIO_PLATFORM(135) /* SCL2, IDX_LOOP_CNT  J616 */
280     , GPIO_PLATFORM(136) /* SDA2, IDX_NO_BUF J616 */
281     , GPIO_PLATFORM(30) /* CAM_MECHSH0, IDX_BT_TX, J613 low-active */
282     , GPIO_PLATFORM(31) /* CAM_MECHSH1, IDX_BT_RX, J613 low-active */
283     , GPIO_PLATFORM(124) /* GPS_PWR_EN, ThreadDSPIn [GPS] */
284     , GPIO_PLATFORM(125) /* GPS_SYNC, mtk_sys_msg_recv [GPS] */
285     , GPIO_PLATFORM(21) /* GPS_EINT8, dump_nmea_data [GPS] */
286     , GPIO_PLATFORM(29) /* CAM_STROBE, IDX_GPS_TX, J613 low-active */
287     , GPIO_PLATFORM(20) /*CMHREF, J613 UNUSED */
288 //    , GPIO_6516(64) /* EINT5, REMOVED!!! for MT6620-Wi-Fi Int */
289 //    , GPIO_6516(122) /* BT_PWR_EN, REMOVED!!! for MT6620-PMU_EN */
290 //    , GPIO_6516(123) /* BT_RESET, REMOVED!!! for MT6620-RST */
291 };
292 #endif
293 /*******************************************************************************
294 *                                 M A C R O S
295 ********************************************************************************
296 */
297
298 /*******************************************************************************
299 *                   F U N C T I O N   D E C L A R A T I O N S
300 ********************************************************************************
301 */
302
303 /*******************************************************************************
304 *                              F U N C T I O N S
305 ********************************************************************************
306 */
307 #if CFG_DBG_GPIO_PINS
308 void debug_gpio_init(void)
309 {
310     int i;
311
312     for (i = 0; i < sizeof(dbgPinSTP)/sizeof(dbgPinSTP[0]); ++i) {
313         if (GPIO_INVALID == dbgPinSTP[i]) {
314             continue;
315         }
316         //printk(KERN_INFO "[%s] %ld \n", __FUNCTION__, dbgPinSTP[i]);
317         mt_set_gpio_pull_enable(dbgPinSTP[i], 0); /* disable pull */
318         mt_set_gpio_dir(dbgPinSTP[i], GPIO_DIR_OUT); /* set output */
319         mt_set_gpio_mode(dbgPinSTP[i], GPIO_MODE_00); /* set gpio mode */
320
321         /* toggle twice to check if ok: */
322         mt_set_gpio_out(dbgPinSTP[i], GPIO_OUT_ZERO); /* tie low */
323         mt_set_gpio_out(dbgPinSTP[i], GPIO_OUT_ONE); /* tie high*/
324         mt_set_gpio_out(dbgPinSTP[i], GPIO_OUT_ZERO); /* tie low */
325         mt_set_gpio_out(dbgPinSTP[i], GPIO_OUT_ONE); /* tie high*/
326     }
327     //printk(KERN_INFO "[%s] initialization ok \n", __FUNCTION__);
328 }
329
330 void debug_gpio_deinit(void)
331 {
332     int i;
333     for (i = 0; i < sizeof(dbgPinSTP)/sizeof(dbgPinSTP[0]); ++i) {
334         if (GPIO_INVALID == dbgPinSTP[i]) {
335             continue;
336         }
337         //printk(KERN_INFO "[%s] %ld \n", __FUNCTION__, dbgPinSTP[i]);
338         mt_set_gpio_dir(dbgPinSTP[i], GPIO_DIR_IN);
339     }
340
341     //printk(KERN_INFO "[%s] k\n", __FUNCTION__);
342 }
343
344 void mtk_wcn_stp_debug_gpio_assert(UINT_32 dwIndex, UINT_32 dwMethod)
345 {
346     unsigned int i;
347
348     if (dwIndex >= (sizeof(dbgPinSTP)/sizeof(dbgPinSTP[0]))) {
349         //printk(KERN_INFO "[%s] invalid dwIndex(%ld) \n", __FUNCTION__, dwIndex);
350         return;
351     }
352
353     if (dwIndex > IDX_STP_MAX) {
354         //printk(KERN_INFO "[%s] dwIndex(%ld) > IDX_STP_MAX(%d) \n", __FUNCTION__, dwIndex, IDX_STP_MAX);
355     }
356
357     if (GPIO_INVALID == dbgPinSTP[dwIndex]) {
358         return;
359     }
360
361     if (dwMethod & DBG_TIE_DIR) {
362         if (dwMethod & DBG_HIGH) {
363             mt_set_gpio_out(dbgPinSTP[dwIndex], GPIO_OUT_ONE);
364         }
365         else {
366             mt_set_gpio_out(dbgPinSTP[dwIndex], GPIO_OUT_ZERO);
367         }
368         return;
369     }
370
371     if (dwMethod & DBG_TOGGLE(0)) {
372         for (i = 0; i < DBG_TOGGLE_NUM(dwMethod); ++i) {
373             mt_set_gpio_out(dbgPinSTP[dwIndex], GPIO_OUT_ZERO);
374             mt_set_gpio_out(dbgPinSTP[dwIndex], GPIO_OUT_ONE);
375         }
376         return;
377     }
378
379     return;
380 }
381 #endif
382
383 /*----------------------------------------------------------------------------*/
384 /*!
385 * \brief This function is a SDIO interrupt callback function
386 *
387 * \param[in] func  pointer to SDIO handle
388 *
389 * \return void
390 */
391 /*----------------------------------------------------------------------------*/
392
393 #if MTK_WCN_HIF_SDIO
394
395 static INT32 mtk_sdio_interrupt(MTK_WCN_HIF_SDIO_CLTCTX cltCtx)
396 {
397     P_GLUE_INFO_T prGlueInfo = NULL;
398     INT32 ret = 0;
399
400     prGlueInfo = mtk_wcn_hif_sdio_get_drvdata(cltCtx);
401
402     ASSERT(prGlueInfo);
403
404     if (!prGlueInfo) {
405         //printk(KERN_INFO DRV_NAME"No glue info in mtk_sdio_interrupt()\n");
406         return (-HIF_SDIO_ERR_FAIL);
407     }
408
409     if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) {
410         //printk(KERN_INFO DRV_NAME"GLUE_FLAG_HALT skip INT\n");
411         ret = mtk_wcn_hif_sdio_writel(cltCtx, MCR_WHLPCR, WHLPCR_INT_EN_CLR);
412         return ret;
413     }
414
415     ret = mtk_wcn_hif_sdio_writel(cltCtx, MCR_WHLPCR, WHLPCR_INT_EN_CLR);
416
417     set_bit (GLUE_FLAG_INT_BIT, &prGlueInfo->u4Flag);
418
419     /* when we got sdio interrupt, we wake up the tx servie thread*/
420     wake_up_interruptible(&prGlueInfo->waitq);
421
422     return ret;
423 }
424
425 #else
426
427 static unsigned int in_interrupt = 0;
428
429 static void mtk_sdio_interrupt(struct sdio_func *func)
430 {
431     P_GLUE_INFO_T prGlueInfo = NULL;
432
433     int ret = 0;
434
435     prGlueInfo = sdio_get_drvdata(func);
436     ASSERT(prGlueInfo);
437
438     if (!prGlueInfo) {
439         //printk(KERN_INFO DRV_NAME"No glue info in mtk_sdio_interrupt()\n");
440         return;
441     }
442
443     if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) {
444         sdio_writel(prGlueInfo->rHifInfo.func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, &ret);
445         //printk(KERN_INFO DRV_NAME"GLUE_FLAG_HALT skip INT\n");
446         return;
447     }
448
449     sdio_writel(prGlueInfo->rHifInfo.func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, &ret);
450
451     #if 0
452     wlanISR(prGlueInfo->prAdapter, TRUE);
453
454     if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) {
455         /* Should stop now... skip pending interrupt */
456         //printk(KERN_INFO DRV_NAME"ignore pending interrupt\n");
457     }
458     else {
459         wlanIST(prGlueInfo->prAdapter);
460     }
461     #endif
462
463     set_bit (GLUE_FLAG_INT_BIT, &prGlueInfo->u4Flag);
464
465     /* when we got sdio interrupt, we wake up the tx servie thread*/
466     wake_up_interruptible(&prGlueInfo->waitq);
467 }
468 #endif
469
470 /*----------------------------------------------------------------------------*/
471 /*!
472 * \brief This function is a SDIO probe function
473 *
474 * \param[in] func   pointer to SDIO handle
475 * \param[in] id     pointer to SDIO device id table
476 *
477 * \return void
478 */
479 /*----------------------------------------------------------------------------*/
480
481 #if MTK_WCN_HIF_SDIO
482
483 // FIXME: global variable
484 static const MTK_WCN_HIF_SDIO_FUNCINFO *prFunc;
485
486
487 static INT32
488 mtk_sdio_probe(MTK_WCN_HIF_SDIO_CLTCTX cltCtx, const MTK_WCN_HIF_SDIO_FUNCINFO *prFuncInfo)
489 {
490     INT32 ret = HIF_SDIO_ERR_SUCCESS;
491
492     prFunc = prFuncInfo;
493
494     if (pfWlanProbe((PVOID) &cltCtx) != WLAN_STATUS_SUCCESS) {
495         //printk(KERN_WARNING DRV_NAME"pfWlanProbe fail!call pfWlanRemove()\n");
496         pfWlanRemove();
497         ret = -(HIF_SDIO_ERR_FAIL);
498     } else {
499         //printk(KERN_INFO DRV_NAME"mtk_wifi_sdio_probe() done(%d)\n", ret);
500     }
501     return ret;
502 }
503 #else
504 static int mtk_sdio_probe (
505     struct sdio_func *func,
506     const struct sdio_device_id *id
507     )
508 {
509     int ret = 0;
510     int i = 0;
511
512     //printk(KERN_INFO DRV_NAME "mtk_sdio_probe()\n");
513
514     ASSERT(func);
515     ASSERT(id);
516
517     //printk(KERN_INFO DRV_NAME "Basic struct size checking...\n");
518     //printk(KERN_INFO DRV_NAME "sizeof(struct device) = %d\n", sizeof(struct device));
519     //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_host) = %d\n", sizeof(struct mmc_host));
520     //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_card) = %d\n", sizeof(struct mmc_card));
521     //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_driver) = %d\n", sizeof(struct mmc_driver));
522     //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_data) = %d\n", sizeof(struct mmc_data));
523     //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_command) = %d\n", sizeof(struct mmc_command));
524     //printk(KERN_INFO DRV_NAME "sizeof(struct mmc_request) = %d\n", sizeof(struct mmc_request));
525     //printk(KERN_INFO DRV_NAME "sizeof(struct sdio_func) = %d\n", sizeof(struct sdio_func));
526
527     //printk(KERN_INFO DRV_NAME "Card information checking...\n");
528     //printk(KERN_INFO DRV_NAME "func = 0x%p\n", func);
529     //printk(KERN_INFO DRV_NAME "Number of info = %d:\n", func->card->num_info);
530
531     for (i = 0; i < func->card->num_info; i++) {
532         //printk(KERN_INFO DRV_NAME "info[%d]: %s\n", i, func->card->info[i]);
533     }
534
535     sdio_claim_host(func);
536     ret = sdio_enable_func(func);
537     sdio_release_host(func);
538
539     if (ret) {
540         //printk(KERN_INFO DRV_NAME"sdio_enable_func failed!\n");
541         goto out;
542     }
543     //printk(KERN_INFO DRV_NAME"sdio_enable_func done!\n");
544
545     if (pfWlanProbe((PVOID)func) != WLAN_STATUS_SUCCESS) {
546         //printk(KERN_WARNING DRV_NAME"pfWlanProbe fail!call pfWlanRemove()\n");
547         pfWlanRemove();
548         ret = -1;
549     }
550     else {
551 #if CFG_DBG_GPIO_PINS
552     //printk(KERN_INFO "[%s] init debug gpio, 20100815 \n", __FUNCTION__);
553     /* Debug pins initialization */
554     debug_gpio_init();
555 #endif
556     }
557
558 out:
559     //printk(KERN_INFO DRV_NAME"mtk_sdio_probe() done(%d)\n", ret);
560     return ret;
561 }
562 #endif
563
564
565 #if MTK_WCN_HIF_SDIO
566 static INT32
567 mtk_sdio_remove(MTK_WCN_HIF_SDIO_CLTCTX cltCtx)
568 {
569     INT32 ret = HIF_SDIO_ERR_SUCCESS;
570     //printk(KERN_INFO DRV_NAME"pfWlanRemove done\n");
571     pfWlanRemove();
572
573     return ret;
574 }
575 #else
576 static void
577 mtk_sdio_remove (
578     struct sdio_func *func
579     )
580 {
581     //printk(KERN_INFO DRV_NAME"mtk_sdio_remove()\n");
582
583 #if CFG_DBG_GPIO_PINS
584     //printk(KERN_INFO "[%s] deinit debug gpio \n", __FUNCTION__);
585     debug_gpio_deinit();
586 #endif
587
588     ASSERT(func);
589     //printk(KERN_INFO DRV_NAME"pfWlanRemove done\n");
590     pfWlanRemove();
591
592     sdio_claim_host(func);
593     sdio_disable_func(func);
594     //printk(KERN_INFO DRV_NAME"sdio_disable_func() done\n");
595     sdio_release_host(func);
596
597     //printk(KERN_INFO DRV_NAME"mtk_sdio_remove() done\n");
598 }
599 #endif
600
601 #if (MTK_WCN_HIF_SDIO == 0)
602 static int
603 mtk_sdio_suspend (
604     struct device * pDev,
605     pm_message_t state
606     )
607 {
608     //printk(KERN_INFO "mtk_sdio: mtk_sdio_suspend dev(0x%p)\n", pDev);
609     //printk(KERN_INFO "mtk_sdio: MediaTek SDIO WLAN driver\n");
610
611     return 0;
612 }
613
614 int mtk_sdio_resume (
615     struct device * pDev
616     )
617 {
618     //printk(KERN_INFO "mtk_sdio: mtk_sdio_resume dev(0x%p)\n", pDev);
619
620     return 0;
621 }
622 #endif
623
624
625 /*----------------------------------------------------------------------------*/
626 /*!
627 * \brief This function will register sdio bus to the os
628 *
629 * \param[in] pfProbe    Function pointer to detect card
630 * \param[in] pfRemove   Function pointer to remove card
631 *
632 * \return The result of registering sdio bus
633 */
634 /*----------------------------------------------------------------------------*/
635 WLAN_STATUS
636 glRegisterBus (
637     probe_card pfProbe,
638     remove_card pfRemove
639     )
640 {
641     int ret = 0;
642
643     ASSERT(pfProbe);
644     ASSERT(pfRemove);
645
646     //printk(KERN_INFO "mtk_sdio: MediaTek SDIO WLAN driver\n");
647     //printk(KERN_INFO "mtk_sdio: Copyright MediaTek Inc.\n");
648
649     pfWlanProbe = pfProbe;
650     pfWlanRemove = pfRemove;
651
652 #if MTK_WCN_HIF_SDIO
653     /* register MTK sdio client */
654     ret = ((mtk_wcn_hif_sdio_client_reg(&cltInfo) == HIF_SDIO_ERR_SUCCESS) ? WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE);
655 #else
656     mtk_sdio_driver.probe = mtk_sdio_probe;
657     mtk_sdio_driver.remove = mtk_sdio_remove;
658
659     mtk_sdio_driver.drv.suspend = mtk_sdio_suspend;
660     mtk_sdio_driver.drv.resume = mtk_sdio_resume;
661
662     ret = (sdio_register_driver(&mtk_sdio_driver) == 0) ? WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE;
663 #endif
664
665     return ret;
666 } /* end of glRegisterBus() */
667
668
669 /*----------------------------------------------------------------------------*/
670 /*!
671 * \brief This function will unregister sdio bus to the os
672 *
673 * \param[in] pfRemove   Function pointer to remove card
674 *
675 * \return (none)
676 */
677 /*----------------------------------------------------------------------------*/
678 VOID
679 glUnregisterBus(
680     remove_card pfRemove
681     )
682 {
683     ASSERT(pfRemove);
684     pfRemove();
685
686 #if MTK_WCN_HIF_SDIO
687     /* unregister MTK sdio client */
688     mtk_wcn_hif_sdio_client_unreg(&cltInfo);
689 #else
690     sdio_unregister_driver(&mtk_sdio_driver);
691 #endif
692
693     return;
694 } /* end of glUnregisterBus() */
695
696
697 /*----------------------------------------------------------------------------*/
698 /*!
699 * \brief This function stores hif related info, which is initialized before.
700 *
701 * \param[in] prGlueInfo Pointer to glue info structure
702 * \param[in] u4Cookie   Pointer to UINT_32 memory base variable for _HIF_HPI
703 *
704 * \return (none)
705 */
706 /*----------------------------------------------------------------------------*/
707 VOID
708 glSetHifInfo (
709     P_GLUE_INFO_T prGlueInfo,
710     UINT_32 u4Cookie
711     )
712 {
713     P_GL_HIF_INFO_T prHif = NULL;
714
715     prHif = &prGlueInfo->rHifInfo;
716
717 #if MTK_WCN_HIF_SDIO
718     //prHif->prFuncInfo = ((MTK_WCN_HIF_SDIO_FUNCINFO *) u4Cookie);
719     prHif->prFuncInfo = prFunc;
720     prHif->cltCtx = *((MTK_WCN_HIF_SDIO_CLTCTX *) u4Cookie);
721     mtk_wcn_hif_sdio_set_drvdata(prHif->cltCtx, prGlueInfo);
722
723 #else
724     prHif->func = (struct sdio_func *) u4Cookie;
725
726     //printk(KERN_INFO DRV_NAME"prHif->func->dev = 0x%p\n", &prHif->func->dev);
727     //printk(KERN_INFO DRV_NAME"prHif->func->vendor = 0x%04X\n", prHif->func->vendor);
728     //printk(KERN_INFO DRV_NAME"prHif->func->device = 0x%04X\n", prHif->func->device);
729     //printk(KERN_INFO DRV_NAME"prHif->func->func = 0x%04X\n", prHif->func->num);
730
731     sdio_set_drvdata(prHif->func, prGlueInfo);
732
733     SET_NETDEV_DEV(prGlueInfo->prDevHandler, &prHif->func->dev);
734 #endif
735
736     return;
737 } /* end of glSetHifInfo() */
738
739 /*----------------------------------------------------------------------------*/
740 /*!
741 * \brief This function clears hif related info.
742 *
743 * \param[in] prGlueInfo Pointer to glue info structure
744 *
745 * \return (none)
746 */
747 /*----------------------------------------------------------------------------*/
748 VOID
749 glClearHifInfo (
750     P_GLUE_INFO_T prGlueInfo
751     )
752 {
753     //P_GL_HIF_INFO_T prHif = NULL;
754     //ASSERT(prGlueInfo);
755     //prHif = &prGlueInfo->rHifInfo;
756
757     return;
758 } /* end of glClearHifInfo() */
759
760
761 /*----------------------------------------------------------------------------*/
762 /*!
763 * \brief Initialize bus operation and hif related information, request resources.
764 *
765 * \param[out] pvData    A pointer to HIF-specific data type buffer.
766 *                       For eHPI, pvData is a pointer to UINT_32 type and stores a
767 *                       mapped base address.
768 *
769 * \return (none)
770 */
771 /*----------------------------------------------------------------------------*/
772 BOOL
773 glBusInit (
774     PVOID pvData
775     )
776 {
777 #if (MTK_WCN_HIF_SDIO == 0)
778     int ret = 0;
779     struct sdio_func *func = NULL;
780
781     ASSERT(pvData);
782
783     func = (struct sdio_func *) pvData;
784
785     sdio_claim_host(func);
786     ret = sdio_set_block_size(func, 512);
787     sdio_release_host(func);
788
789     if (ret) {
790         //printk(KERN_INFO DRV_NAME"sdio_set_block_size 512 failed!\n");
791     }
792     else {
793         //printk(KERN_INFO DRV_NAME"sdio_set_block_size 512 done!\n");
794     }
795
796     //printk(KERN_INFO DRV_NAME"param: func->cur_blksize(%d)\n", func->cur_blksize);
797     //printk(KERN_INFO DRV_NAME"param: func->max_blksize(%d)\n", func->max_blksize);
798     //printk(KERN_INFO DRV_NAME"param: func->card->host->max_blk_size(%d)\n", func->card->host->max_blk_size);
799     //printk(KERN_INFO DRV_NAME"param: func->card->host->max_blk_count(%d)\n", func->card->host->max_blk_count);
800 #endif
801     return TRUE;
802 } /* end of glBusInit() */
803
804
805 /*----------------------------------------------------------------------------*/
806 /*!
807 * \brief Stop bus operation and release resources.
808 *
809 * \param[in] pvData A pointer to struct net_device.
810 *
811 * \return (none)
812 */
813 /*----------------------------------------------------------------------------*/
814 VOID
815 glBusRelease (
816     PVOID pvData
817     )
818 {
819
820     return;
821 } /* end of glBusRelease() */
822
823
824 /*----------------------------------------------------------------------------*/
825 /*!
826 * \brief Setup bus interrupt operation and interrupt handler for os.
827 *
828 * \param[in] pvData     A pointer to struct net_device.
829 * \param[in] pfnIsr     A pointer to interrupt handler function.
830 * \param[in] pvCookie   Private data for pfnIsr function.
831 *
832 * \retval WLAN_STATUS_SUCCESS   if success
833 *         NEGATIVE_VALUE   if fail
834 */
835 /*----------------------------------------------------------------------------*/
836 INT_32
837 glBusSetIrq (
838     PVOID pvData,
839     PVOID pfnIsr,
840     PVOID pvCookie
841     )
842 {
843     int ret = 0;
844
845 #if (MTK_WCN_HIF_SDIO == 0)
846     struct net_device *prNetDevice = NULL;
847     P_GLUE_INFO_T prGlueInfo = NULL;
848     P_GL_HIF_INFO_T prHifInfo = NULL;
849
850     ASSERT(pvData);
851     if (!pvData) {
852         return -1;
853     }
854     prNetDevice = (struct net_device *) pvData;
855     prGlueInfo = (P_GLUE_INFO_T) pvCookie;
856     ASSERT(prGlueInfo);
857     if (!prGlueInfo) {
858         return -1;
859     }
860
861     prHifInfo = &prGlueInfo->rHifInfo;
862
863     sdio_claim_host(prHifInfo->func);
864     ret = sdio_claim_irq(prHifInfo->func, mtk_sdio_interrupt);
865     sdio_release_host(prHifInfo->func);
866 #else
867                 /* hif_sdio case */
868                 struct net_device *prNetDevice = NULL;
869                 P_GLUE_INFO_T prGlueInfo = NULL;
870         
871                 ASSERT(pvData);
872                 if (!pvData) {
873                         return -1;
874                 }
875                 prNetDevice = (struct net_device *) pvData;
876         
877                 prGlueInfo = (P_GLUE_INFO_T) pvCookie;
878                 ASSERT(prGlueInfo);
879                 if (!prGlueInfo) {
880                         return -1;
881                 }
882         
883                 mtk_wcn_hif_sdio_enable_irq(prGlueInfo->rHifInfo.cltCtx, MTK_WCN_BOOL_TRUE);
884
885 #endif
886     return ret;
887 } /* end of glBusSetIrq() */
888
889
890 /*----------------------------------------------------------------------------*/
891 /*!
892 * \brief Stop bus interrupt operation and disable interrupt handling for os.
893 *
894 * \param[in] pvData     A pointer to struct net_device.
895 * \param[in] pvCookie   Private data for pfnIsr function.
896 *
897 * \return (none)
898 */
899 /*----------------------------------------------------------------------------*/
900 VOID
901 glBusFreeIrq (
902     PVOID pvData,
903     PVOID pvCookie
904     )
905 {
906 #if (MTK_WCN_HIF_SDIO == 0)
907     struct net_device *prNetDevice = NULL;
908     P_GLUE_INFO_T prGlueInfo = NULL;
909     P_GL_HIF_INFO_T prHifInfo = NULL;
910     int ret = 0;
911
912     ASSERT(pvData);
913     if (!pvData) {
914         //printk(KERN_INFO DRV_NAME"%s null pvData\n", __FUNCTION__);
915         return;
916     }
917     prNetDevice = (struct net_device *) pvData;
918     prGlueInfo = (P_GLUE_INFO_T) pvCookie;
919     ASSERT(prGlueInfo);
920     if (!prGlueInfo) {
921         //printk(KERN_INFO DRV_NAME"%s no glue info\n", __FUNCTION__);
922         return;
923     }
924
925     prHifInfo = &prGlueInfo->rHifInfo;
926
927     sdio_claim_host(prHifInfo->func);
928     ret = sdio_release_irq(prHifInfo->func);
929     sdio_release_host(prHifInfo->func);
930 #else
931                 /* hif_sdio case */
932                 struct net_device *prNetDevice = NULL;
933                 P_GLUE_INFO_T prGlueInfo = NULL;
934         
935                 ASSERT(pvData);
936                 if (!pvData) {
937                         //printk(KERN_INFO DRV_NAME"%s null pvData\n", __FUNCTION__);
938                         return;
939                 }
940                 prNetDevice = (struct net_device *) pvData;
941         
942                 prGlueInfo = (P_GLUE_INFO_T) pvCookie;
943                 ASSERT(prGlueInfo);
944                 if (!prGlueInfo) {
945                         //printk(KERN_INFO DRV_NAME"%s no glue info\n", __FUNCTION__);
946                         return;
947                 }
948         
949                 mtk_wcn_hif_sdio_enable_irq(prGlueInfo->rHifInfo.cltCtx, MTK_WCN_BOOL_FALSE);
950
951 #endif
952
953     return;
954 } /* end of glBusreeIrq() */
955
956
957 /*----------------------------------------------------------------------------*/
958 /*!
959 * \brief Read a 32-bit device register
960 *
961 * \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure.
962 * \param[in] u4Register Register offset
963 * \param[in] pu4Value   Pointer to variable used to store read value
964 *
965 * \retval TRUE          operation success
966 * \retval FALSE         operation fail
967 */
968 /*----------------------------------------------------------------------------*/
969 BOOL
970 kalDevRegRead (
971     IN  P_GLUE_INFO_T   prGlueInfo,
972     IN  UINT_32         u4Register,
973     OUT PUINT_32        pu4Value
974     )
975 {
976     int ret = 0;
977
978     ASSERT(prGlueInfo);
979     ASSERT(pu4Value);
980
981 #if MTK_WCN_HIF_SDIO
982     ret = mtk_wcn_hif_sdio_readl(prGlueInfo->rHifInfo.cltCtx, u4Register, (PUINT32) pu4Value);
983 #else
984     if (!in_interrupt) {
985         sdio_claim_host(prGlueInfo->rHifInfo.func);
986     }
987
988     *pu4Value = sdio_readl(prGlueInfo->rHifInfo.func, u4Register, &ret);
989
990     if (!in_interrupt) {
991         sdio_release_host(prGlueInfo->rHifInfo.func);
992     }
993 #endif
994
995     if (ret) {
996         kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_readl() reports error: %x", ret);
997         DBGLOG(HAL, ERROR, ("sdio_readl() reports error: %x", ret));
998     }
999
1000     return (ret) ? FALSE : TRUE;
1001 } /* end of kalDevRegRead() */
1002
1003
1004 /*----------------------------------------------------------------------------*/
1005 /*!
1006 * \brief Write a 32-bit device register
1007 *
1008 * \param[in] prGlueInfo Pointer to the GLUE_INFO_T structure.
1009 * \param[in] u4Register Register offset
1010 * \param[in] u4Value    Value to be written
1011 *
1012 * \retval TRUE          operation success
1013 * \retval FALSE         operation fail
1014 */
1015 /*----------------------------------------------------------------------------*/
1016 BOOL
1017 kalDevRegWrite (
1018     IN P_GLUE_INFO_T  prGlueInfo,
1019     IN UINT_32        u4Register,
1020     IN UINT_32        u4Value
1021     )
1022 {
1023     int ret = 0;
1024
1025     ASSERT(prGlueInfo);
1026
1027 #if MTK_WCN_HIF_SDIO
1028     ret = mtk_wcn_hif_sdio_writel(prGlueInfo->rHifInfo.cltCtx, u4Register, u4Value);
1029 #else
1030     if (!in_interrupt) {
1031         sdio_claim_host(prGlueInfo->rHifInfo.func);
1032     }
1033
1034     sdio_writel(prGlueInfo->rHifInfo.func, u4Value, u4Register, &ret);
1035
1036     if (!in_interrupt) {
1037         sdio_release_host(prGlueInfo->rHifInfo.func);
1038     }
1039 #endif
1040
1041     if (ret) {
1042         kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_writel() reports error: %x", ret);
1043         DBGLOG(HAL, ERROR, ("sdio_writel() reports error: %x", ret));
1044     }
1045
1046     return (ret) ? FALSE : TRUE;
1047 } /* end of kalDevRegWrite() */
1048
1049
1050 /*----------------------------------------------------------------------------*/
1051 /*!
1052 * \brief Read device I/O port
1053 *
1054 * \param[in] prGlueInfo         Pointer to the GLUE_INFO_T structure.
1055 * \param[in] u2Port             I/O port offset
1056 * \param[in] u2Len              Length to be read
1057 * \param[out] pucBuf            Pointer to read buffer
1058 * \param[in] u2ValidOutBufSize  Length of the buffer valid to be accessed
1059 *
1060 * \retval TRUE          operation success
1061 * \retval FALSE         operation fail
1062 */
1063 /*----------------------------------------------------------------------------*/
1064 BOOL
1065 kalDevPortRead (
1066     IN  P_GLUE_INFO_T   prGlueInfo,
1067     IN  UINT_16         u2Port,
1068     IN  UINT_16         u2Len,
1069     OUT PUINT_8         pucBuf,
1070     IN  UINT_16         u2ValidOutBufSize
1071     )
1072 {
1073     P_GL_HIF_INFO_T prHifInfo = NULL;
1074     PUINT_8 pucDst = NULL;
1075     int count = u2Len;
1076     int ret = 0;
1077     int bNum = 0;
1078
1079 #if (MTK_WCN_HIF_SDIO == 0)
1080     struct sdio_func *prSdioFunc = NULL;
1081 #endif
1082
1083     #if DBG
1084     //printk(KERN_INFO DRV_NAME"++kalDevPortRead++ buf:0x%p, port:0x%x, length:%d\n", pucBuf, u2Port, u2Len);
1085     #endif
1086
1087     ASSERT(prGlueInfo);
1088     prHifInfo = &prGlueInfo->rHifInfo;
1089
1090     ASSERT(pucBuf);
1091     pucDst = pucBuf;
1092
1093     ASSERT(u2Len <= u2ValidOutBufSize);
1094
1095 #if (MTK_WCN_HIF_SDIO == 0)
1096     prSdioFunc = prHifInfo->func;
1097
1098     ASSERT(prSdioFunc->cur_blksize > 0);
1099
1100     if (!in_interrupt) {
1101         sdio_claim_host(prSdioFunc);
1102     }
1103
1104     /* Split buffer into multiple single block to workaround hifsys */
1105     while (count >= prSdioFunc->cur_blksize) {
1106         count -= prSdioFunc->cur_blksize;
1107         bNum++;
1108     }
1109     if (count > 0 && bNum > 0) {
1110         bNum++;
1111     }
1112
1113     if (bNum > 0) {
1114         ret = sdio_readsb(prSdioFunc, pucDst, u2Port, prSdioFunc->cur_blksize * bNum);
1115
1116 #ifdef CONFIG_X86
1117         /* ENE workaround */
1118         {
1119             int tmp;
1120             sdio_writel(prSdioFunc, 0x0, SDIO_X86_WORKAROUND_WRITE_MCR, &tmp);
1121         }
1122 #endif
1123
1124     }
1125     else {
1126         ret = sdio_readsb(prSdioFunc, pucDst, u2Port, count);
1127     }
1128
1129     if (!in_interrupt) {
1130         sdio_release_host(prSdioFunc);
1131     }
1132 #else
1133
1134     /* Split buffer into multiple single block to workaround hifsys */
1135     while (count >= (prGlueInfo->rHifInfo).prFuncInfo->blk_sz) {
1136         count -= ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz);
1137         bNum++;
1138     }
1139     if (count > 0 && bNum > 0) {
1140         bNum++;
1141     }
1142
1143     if (bNum > 0) {
1144         ret = mtk_wcn_hif_sdio_read_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucDst,
1145                  ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz) * bNum);
1146     }
1147     else {
1148         ret = mtk_wcn_hif_sdio_read_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucDst, (count+3)&~0x3U);
1149     }
1150 #endif
1151
1152     if (ret) {
1153         kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_readsb() reports error: %x", ret);
1154         DBGLOG(HAL, ERROR, ("sdio_readsb() reports error: %x", ret));
1155     }
1156
1157     return (ret) ? FALSE : TRUE;
1158 } /* end of kalDevPortRead() */
1159
1160
1161 /*----------------------------------------------------------------------------*/
1162 /*!
1163 * \brief Write device I/O port
1164 *
1165 * \param[in] prGlueInfo         Pointer to the GLUE_INFO_T structure.
1166 * \param[in] u2Port             I/O port offset
1167 * \param[in] u2Len              Length to be write
1168 * \param[in] pucBuf             Pointer to write buffer
1169 * \param[in] u2ValidInBufSize   Length of the buffer valid to be accessed
1170 *
1171 * \retval TRUE          operation success
1172 * \retval FALSE         operation fail
1173 */
1174 /*----------------------------------------------------------------------------*/
1175 BOOL
1176 kalDevPortWrite (
1177     IN P_GLUE_INFO_T  prGlueInfo,
1178     IN UINT_16        u2Port,
1179     IN UINT_16        u2Len,
1180     IN PUINT_8        pucBuf,
1181     IN UINT_16        u2ValidInBufSize
1182     )
1183 {
1184     P_GL_HIF_INFO_T prHifInfo = NULL;
1185     PUINT_8 pucSrc = NULL;
1186     int count = u2Len;
1187     int ret = 0;
1188     int bNum = 0;
1189
1190 #if (MTK_WCN_HIF_SDIO == 0)
1191     struct sdio_func *prSdioFunc = NULL;
1192 #endif
1193
1194     #if DBG
1195     //printk(KERN_INFO DRV_NAME"++kalDevPortWrite++ buf:0x%p, port:0x%x, length:%d\n", pucBuf, u2Port, u2Len);
1196     #endif
1197
1198     ASSERT(prGlueInfo);
1199     prHifInfo = &prGlueInfo->rHifInfo;
1200
1201     ASSERT(pucBuf);
1202     pucSrc = pucBuf;
1203
1204     ASSERT(u2Len <= u2ValidInBufSize);
1205
1206 #if (MTK_WCN_HIF_SDIO == 0)
1207     prSdioFunc = prHifInfo->func;
1208     ASSERT(prSdioFunc->cur_blksize > 0);
1209
1210     if (!in_interrupt) {
1211         sdio_claim_host(prSdioFunc);
1212     }
1213
1214     /* Split buffer into multiple single block to workaround hifsys */
1215     while (count >= prSdioFunc->cur_blksize) {
1216         count -= prSdioFunc->cur_blksize;
1217         bNum++;
1218     }
1219     if (count > 0 && bNum > 0) {
1220         bNum++;
1221     }
1222
1223     if (bNum > 0) { // block mode
1224         ret = sdio_writesb(prSdioFunc, u2Port, pucSrc, prSdioFunc->cur_blksize * bNum);
1225
1226 #ifdef CONFIG_X86
1227         /* ENE workaround */
1228         {
1229             int tmp;
1230             sdio_writel(prSdioFunc, 0x0, SDIO_X86_WORKAROUND_WRITE_MCR, &tmp);
1231         }
1232 #endif
1233
1234     }
1235     else {  // byte mode
1236
1237         ret = sdio_writesb(prSdioFunc, u2Port, pucSrc, count);
1238     }
1239
1240     if (!in_interrupt) {
1241         sdio_release_host(prSdioFunc);
1242     }
1243 #else
1244     /* Split buffer into multiple single block to workaround hifsys */
1245     while (count >= ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz)) {
1246         count -= ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz);
1247         bNum++;
1248     }
1249     if (count > 0 && bNum > 0) {
1250         bNum++;
1251     }
1252
1253     if (bNum > 0) { // block mode
1254         ret = mtk_wcn_hif_sdio_write_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucSrc,
1255                              ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz) * bNum);
1256     }
1257     else {  // byte mode
1258         ret = mtk_wcn_hif_sdio_write_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucSrc, (count+3)&~0x3U);
1259     }
1260 #endif
1261
1262     if (ret) {
1263         kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_writesb() reports error: %x", ret);
1264         DBGLOG(HAL, ERROR, ("sdio_writesb() reports error: %x", ret));
1265     }
1266
1267     return (ret) ? FALSE : TRUE;
1268 } /* end of kalDevPortWrite() */
1269
1270
1271 /*----------------------------------------------------------------------------*/
1272 /*!
1273 * \brief Write device I/O port in byte with CMD52
1274 *
1275 * \param[in] prGlueInfo         Pointer to the GLUE_INFO_T structure.
1276 * \param[in] u4Addr             I/O port offset
1277 * \param[in] ucData             Single byte of data to be written
1278 *
1279 * \retval TRUE          operation success
1280 * \retval FALSE         operation fail
1281 */
1282 /*----------------------------------------------------------------------------*/
1283 BOOL
1284 kalDevWriteWithSdioCmd52 (
1285     IN P_GLUE_INFO_T    prGlueInfo,
1286     IN UINT_32          u4Addr,
1287     IN UINT_8           ucData
1288     )
1289 {
1290     int ret = 0;
1291
1292 #if (MTK_WCN_HIF_SDIO == 0)
1293     if (!in_interrupt) {
1294         sdio_claim_host(prGlueInfo->rHifInfo.func);
1295     }
1296
1297     sdio_writeb(prGlueInfo->rHifInfo.func, ucData, u4Addr, &ret);
1298
1299     if (!in_interrupt) {
1300         sdio_release_host(prGlueInfo->rHifInfo.func);
1301     }
1302 #else
1303     ret = mtk_wcn_hif_sdio_writeb(prGlueInfo->rHifInfo.cltCtx, u4Addr, ucData);
1304 #endif
1305
1306     if (ret) {
1307         kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR, HIF_SDIO_ERR_DESC_STR "sdio_writeb() reports error: %x", ret);
1308         DBGLOG(HAL, ERROR, ("sdio_writeb() reports error: %x", ret));
1309     }
1310
1311     return (ret) ? FALSE : TRUE;
1312
1313 } /* end of kalDevWriteWithSdioCmd52() */
1314
1315
1316 VOID
1317 glSetPowerState (
1318     IN P_GLUE_INFO_T  prGlueInfo,
1319     IN UINT_32 ePowerMode
1320     )
1321 {
1322     return;
1323 }
1324