support different wifi bt chip auto compatible
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / mt5931 / 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 //#ifndef CONFIG_X86  modify by Nicolas Luo
154 #ifdef CONFIG_ARM
155 #include <asm/memory.h>
156 #endif
157
158 #if defined(MT6620)
159     #include "mt6620_reg.h"
160 #elif defined(MT5931)
161     #include "mt5931_reg.h"
162 #elif defined(MT6628)
163     #include "mt6628_reg.h"
164 #endif
165
166 #if CFG_DBG_GPIO_PINS/* FIXME: move to platform or custom header */
167 #include <mach/mt6516_gpio.h>
168 #endif
169
170 /*******************************************************************************
171 *                              C O N S T A N T S
172 ********************************************************************************
173 */
174
175 #define HIF_SDIO_ERR_TITLE_STR              "["CHIP_NAME"] SDIO Access Error!"
176 #define HIF_SDIO_ERR_DESC_STR               "**SDIO Access Error**\n"
177
178 #if MTK_WCN_HIF_SDIO
179
180
181 /*
182  * function prototypes
183  *
184  */
185
186 static INT32
187 mtk_sdio_probe(MTK_WCN_HIF_SDIO_CLTCTX, const MTK_WCN_HIF_SDIO_FUNCINFO *);
188
189 static INT32
190 mtk_sdio_remove(MTK_WCN_HIF_SDIO_CLTCTX);
191 static INT32 mtk_sdio_interrupt(MTK_WCN_HIF_SDIO_CLTCTX);
192
193 /*
194  * sdio function info table
195  */
196
197 static MTK_WCN_HIF_SDIO_FUNCINFO funcInfo[] = {
198 #if defined(MT6620)
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) },
207 #endif
208 };
209
210
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,
217 };
218
219 #else
220
221 static const struct sdio_device_id mtk_sdio_ids[] = {
222 #if defined(MT6620)
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 */
230 #endif
231         { /* end: all zeroes */ },
232 };
233
234 MODULE_DEVICE_TABLE(sdio, mtk_sdio_ids);
235
236 #endif
237
238 /*******************************************************************************
239 *                             D A T A   T Y P E S
240 ********************************************************************************
241 */
242
243
244 /*******************************************************************************
245 *                            P U B L I C   D A T A
246 ********************************************************************************
247 */
248 extern KAL_WAKE_LOCK_T isr_wakelock;
249 /*******************************************************************************
250 *                           P R I V A T E   D A T A
251 ********************************************************************************
252 */
253 static probe_card pfWlanProbe = NULL;
254 static remove_card pfWlanRemove = NULL;
255
256
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,
261         .probe          = NULL,
262         .remove         = NULL,
263 };
264 #endif
265
266
267 #if CFG_DBG_GPIO_PINS
268
269 /* debug 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 */
292 };
293 #endif
294 /*******************************************************************************
295 *                                 M A C R O S
296 ********************************************************************************
297 */
298
299 /*******************************************************************************
300 *                   F U N C T I O N   D E C L A R A T I O N S
301 ********************************************************************************
302 */
303
304 /*******************************************************************************
305 *                              F U N C T I O N S
306 ********************************************************************************
307 */
308 #if CFG_DBG_GPIO_PINS
309 void debug_gpio_init(void)
310 {
311     int i;
312
313     for (i = 0; i < sizeof(dbgPinSTP)/sizeof(dbgPinSTP[0]); ++i) {
314         if (GPIO_INVALID == dbgPinSTP[i]) {
315             continue;
316         }
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 */
321
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*/
327     }
328     //printk(KERN_INFO "[%s] initialization ok \n", __FUNCTION__);
329 }
330
331 void debug_gpio_deinit(void)
332 {
333     int i;
334     for (i = 0; i < sizeof(dbgPinSTP)/sizeof(dbgPinSTP[0]); ++i) {
335         if (GPIO_INVALID == dbgPinSTP[i]) {
336             continue;
337         }
338         //printk(KERN_INFO "[%s] %ld \n", __FUNCTION__, dbgPinSTP[i]);
339         mt_set_gpio_dir(dbgPinSTP[i], GPIO_DIR_IN);
340     }
341
342     //printk(KERN_INFO "[%s] k\n", __FUNCTION__);
343 }
344
345 void mtk_wcn_stp_debug_gpio_assert(UINT_32 dwIndex, UINT_32 dwMethod)
346 {
347     unsigned int i;
348
349     if (dwIndex >= (sizeof(dbgPinSTP)/sizeof(dbgPinSTP[0]))) {
350         //printk(KERN_INFO "[%s] invalid dwIndex(%ld) \n", __FUNCTION__, dwIndex);
351         return;
352     }
353
354     if (dwIndex > IDX_STP_MAX) {
355         //printk(KERN_INFO "[%s] dwIndex(%ld) > IDX_STP_MAX(%d) \n", __FUNCTION__, dwIndex, IDX_STP_MAX);
356     }
357
358     if (GPIO_INVALID == dbgPinSTP[dwIndex]) {
359         return;
360     }
361
362     if (dwMethod & DBG_TIE_DIR) {
363         if (dwMethod & DBG_HIGH) {
364             mt_set_gpio_out(dbgPinSTP[dwIndex], GPIO_OUT_ONE);
365         }
366         else {
367             mt_set_gpio_out(dbgPinSTP[dwIndex], GPIO_OUT_ZERO);
368         }
369         return;
370     }
371
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);
376         }
377         return;
378     }
379
380     return;
381 }
382 #endif
383
384 /*----------------------------------------------------------------------------*/
385 /*!
386 * \brief This function is a SDIO interrupt callback function
387 *
388 * \param[in] func  pointer to SDIO handle
389 *
390 * \return void
391 */
392 /*----------------------------------------------------------------------------*/
393
394 #if MTK_WCN_HIF_SDIO
395
396 static INT32 mtk_sdio_interrupt(MTK_WCN_HIF_SDIO_CLTCTX cltCtx)
397 {
398     P_GLUE_INFO_T prGlueInfo = NULL;
399     INT32 ret = 0;
400
401     prGlueInfo = mtk_wcn_hif_sdio_get_drvdata(cltCtx);
402
403     ASSERT(prGlueInfo);
404
405     if (!prGlueInfo) {
406         //printk(KERN_INFO DRV_NAME"No glue info in mtk_sdio_interrupt()\n");
407         return (-HIF_SDIO_ERR_FAIL);
408     }
409
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);
413         return ret;
414     }
415
416     /*WCNCR 00002676*/
417     KAL_WAKE_UNLOCK(NULL, &isr_wakelock);
418     KAL_WAKE_LOCK_TIMEOUT(NULL, &isr_wakelock, KAL_HZ/10);
419
420     ret = mtk_wcn_hif_sdio_writel(cltCtx, MCR_WHLPCR, WHLPCR_INT_EN_CLR);
421
422     set_bit (GLUE_FLAG_INT_BIT, &prGlueInfo->u4Flag);
423
424     /* when we got sdio interrupt, we wake up the tx servie thread*/
425     wake_up_interruptible(&prGlueInfo->waitq);
426
427     return ret;
428 }
429
430 #else
431
432 static unsigned int in_interrupt = 0;
433
434 static void mtk_sdio_interrupt(struct sdio_func *func)
435 {
436     P_GLUE_INFO_T prGlueInfo = NULL;
437
438     int ret = 0;
439
440     prGlueInfo = sdio_get_drvdata(func);
441     ASSERT(prGlueInfo);
442
443     if (!prGlueInfo) {
444         //printk(KERN_INFO DRV_NAME"No glue info in mtk_sdio_interrupt()\n");
445         return;
446     }
447
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");
451         return;
452     }
453
454     sdio_writel(prGlueInfo->rHifInfo.func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, &ret);
455
456     #if 0
457     wlanISR(prGlueInfo->prAdapter, TRUE);
458
459     if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) {
460         /* Should stop now... skip pending interrupt */
461         //printk(KERN_INFO DRV_NAME"ignore pending interrupt\n");
462     }
463     else {
464         wlanIST(prGlueInfo->prAdapter);
465     }
466     #endif
467
468     set_bit (GLUE_FLAG_INT_BIT, &prGlueInfo->u4Flag);
469
470     /* when we got sdio interrupt, we wake up the tx servie thread*/
471     wake_up_interruptible(&prGlueInfo->waitq);
472 }
473 #endif
474
475 /*----------------------------------------------------------------------------*/
476 /*!
477 * \brief This function is a SDIO probe function
478 *
479 * \param[in] func   pointer to SDIO handle
480 * \param[in] id     pointer to SDIO device id table
481 *
482 * \return void
483 */
484 /*----------------------------------------------------------------------------*/
485
486 #if MTK_WCN_HIF_SDIO
487
488 // FIXME: global variable
489 static const MTK_WCN_HIF_SDIO_FUNCINFO *prFunc;
490
491
492 static INT32
493 mtk_sdio_probe(MTK_WCN_HIF_SDIO_CLTCTX cltCtx, const MTK_WCN_HIF_SDIO_FUNCINFO *prFuncInfo)
494 {
495     INT32 ret = HIF_SDIO_ERR_SUCCESS;
496
497     prFunc = prFuncInfo;
498
499     if (pfWlanProbe((PVOID) &cltCtx) != WLAN_STATUS_SUCCESS) {
500         //printk(KERN_WARNING DRV_NAME"pfWlanProbe fail!call pfWlanRemove()\n");
501         pfWlanRemove();
502         ret = -(HIF_SDIO_ERR_FAIL);
503     } else {
504         //printk(KERN_INFO DRV_NAME"mtk_wifi_sdio_probe() done(%d)\n", ret);
505     }
506     return ret;
507 }
508 #else
509 static int mtk_sdio_probe (
510     struct sdio_func *func,
511     const struct sdio_device_id *id
512     )
513 {
514     int ret = 0;
515     int i = 0;
516
517     //printk(KERN_INFO DRV_NAME "mtk_sdio_probe()\n");
518
519     ASSERT(func);
520     ASSERT(id);
521
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));
531
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);
535
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]);
538     }
539
540     sdio_claim_host(func);
541     ret = sdio_enable_func(func);
542     sdio_release_host(func);
543
544     if (ret) {
545         //printk(KERN_INFO DRV_NAME"sdio_enable_func failed!\n");
546         goto out;
547     }
548     //printk(KERN_INFO DRV_NAME"sdio_enable_func done!\n");
549
550     if (pfWlanProbe((PVOID)func) != WLAN_STATUS_SUCCESS) {
551         //printk(KERN_WARNING DRV_NAME"pfWlanProbe fail!call pfWlanRemove()\n");
552         pfWlanRemove();
553         ret = -1;
554     }
555     else {
556 #if CFG_DBG_GPIO_PINS
557     //printk(KERN_INFO "[%s] init debug gpio, 20100815 \n", __FUNCTION__);
558     /* Debug pins initialization */
559     debug_gpio_init();
560 #endif
561     }
562
563 out:
564     //printk(KERN_INFO DRV_NAME"mtk_sdio_probe() done(%d)\n", ret);
565     return ret;
566 }
567 #endif
568
569
570 #if MTK_WCN_HIF_SDIO
571 static INT32
572 mtk_sdio_remove(MTK_WCN_HIF_SDIO_CLTCTX cltCtx)
573 {
574     INT32 ret = HIF_SDIO_ERR_SUCCESS;
575     //printk(KERN_INFO DRV_NAME"pfWlanRemove done\n");
576     pfWlanRemove();
577
578     return ret;
579 }
580 #else
581 static void
582 mtk_sdio_remove (
583     struct sdio_func *func
584     )
585 {
586     //printk(KERN_INFO DRV_NAME"mtk_sdio_remove()\n");
587
588 #if CFG_DBG_GPIO_PINS
589     //printk(KERN_INFO "[%s] deinit debug gpio \n", __FUNCTION__);
590     debug_gpio_deinit();
591 #endif
592
593     ASSERT(func);
594     //printk(KERN_INFO DRV_NAME"pfWlanRemove done\n");
595     pfWlanRemove();
596
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);
601
602     //printk(KERN_INFO DRV_NAME"mtk_sdio_remove() done\n");
603 }
604 #endif
605
606 #if (MTK_WCN_HIF_SDIO == 0)
607 static int
608 mtk_sdio_suspend (
609     struct device * pDev,
610     pm_message_t state
611     )
612 {
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");
615
616     return 0;
617 }
618
619 int mtk_sdio_resume (
620     struct device * pDev
621     )
622 {
623     //printk(KERN_INFO "mtk_sdio: mtk_sdio_resume dev(0x%p)\n", pDev);
624
625     return 0;
626 }
627 #endif
628
629
630 /*----------------------------------------------------------------------------*/
631 /*!
632 * \brief This function will register sdio bus to the os
633 *
634 * \param[in] pfProbe    Function pointer to detect card
635 * \param[in] pfRemove   Function pointer to remove card
636 *
637 * \return The result of registering sdio bus
638 */
639 /*----------------------------------------------------------------------------*/
640 WLAN_STATUS
641 glRegisterBus (
642     probe_card pfProbe,
643     remove_card pfRemove
644     )
645 {
646     int ret = 0;
647
648     ASSERT(pfProbe);
649     ASSERT(pfRemove);
650
651     //printk(KERN_INFO "mtk_sdio: MediaTek SDIO WLAN driver\n");
652     //printk(KERN_INFO "mtk_sdio: Copyright MediaTek Inc.\n");
653
654     pfWlanProbe = pfProbe;
655     pfWlanRemove = pfRemove;
656
657 #if MTK_WCN_HIF_SDIO
658     /* register MTK sdio client */
659     ret = ((mtk_wcn_hif_sdio_client_reg(&cltInfo) == HIF_SDIO_ERR_SUCCESS) ? WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE);
660 #else
661     mtk_sdio_driver.probe = mtk_sdio_probe;
662     mtk_sdio_driver.remove = mtk_sdio_remove;
663
664     mtk_sdio_driver.drv.suspend = mtk_sdio_suspend;
665     mtk_sdio_driver.drv.resume = mtk_sdio_resume;
666
667     ret = (sdio_register_driver(&mtk_sdio_driver) == 0) ? WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE;
668 #endif
669
670     return ret;
671 } /* end of glRegisterBus() */
672
673
674 /*----------------------------------------------------------------------------*/
675 /*!
676 * \brief This function will unregister sdio bus to the os
677 *
678 * \param[in] pfRemove   Function pointer to remove card
679 *
680 * \return (none)
681 */
682 /*----------------------------------------------------------------------------*/
683 VOID
684 glUnregisterBus(
685     remove_card pfRemove
686     )
687 {
688     ASSERT(pfRemove);
689     pfRemove();
690
691 #if MTK_WCN_HIF_SDIO
692     /* unregister MTK sdio client */
693     mtk_wcn_hif_sdio_client_unreg(&cltInfo);
694 #else
695     sdio_unregister_driver(&mtk_sdio_driver);
696 #endif
697
698     return;
699 } /* end of glUnregisterBus() */
700
701
702 /*----------------------------------------------------------------------------*/
703 /*!
704 * \brief This function stores hif related info, which is initialized before.
705 *
706 * \param[in] prGlueInfo Pointer to glue info structure
707 * \param[in] u4Cookie   Pointer to UINT_32 memory base variable for _HIF_HPI
708 *
709 * \return (none)
710 */
711 /*----------------------------------------------------------------------------*/
712 VOID
713 glSetHifInfo (
714     P_GLUE_INFO_T prGlueInfo,
715     UINT_32 u4Cookie
716     )
717 {
718     P_GL_HIF_INFO_T prHif = NULL;
719
720     prHif = &prGlueInfo->rHifInfo;
721
722 #if MTK_WCN_HIF_SDIO
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);
727
728 #else
729     prHif->func = (struct sdio_func *) u4Cookie;
730
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);
735
736     sdio_set_drvdata(prHif->func, prGlueInfo);
737
738     SET_NETDEV_DEV(prGlueInfo->prDevHandler, &prHif->func->dev);
739 #endif
740
741     return;
742 } /* end of glSetHifInfo() */
743
744 /*----------------------------------------------------------------------------*/
745 /*!
746 * \brief This function clears hif related info.
747 *
748 * \param[in] prGlueInfo Pointer to glue info structure
749 *
750 * \return (none)
751 */
752 /*----------------------------------------------------------------------------*/
753 VOID
754 glClearHifInfo (
755     P_GLUE_INFO_T prGlueInfo
756     )
757 {
758     //P_GL_HIF_INFO_T prHif = NULL;
759     //ASSERT(prGlueInfo);
760     //prHif = &prGlueInfo->rHifInfo;
761
762     return;
763 } /* end of glClearHifInfo() */
764
765
766 /*----------------------------------------------------------------------------*/
767 /*!
768 * \brief Initialize bus operation and hif related information, request resources.
769 *
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.
773 *
774 * \return (none)
775 */
776 /*----------------------------------------------------------------------------*/
777 BOOL
778 glBusInit (
779     PVOID pvData
780     )
781 {
782 #if (MTK_WCN_HIF_SDIO == 0)
783     int ret = 0;
784     struct sdio_func *func = NULL;
785
786     ASSERT(pvData);
787
788     func = (struct sdio_func *) pvData;
789
790     sdio_claim_host(func);
791     ret = sdio_set_block_size(func, 512);
792     sdio_release_host(func);
793
794     if (ret) {
795         //printk(KERN_INFO DRV_NAME"sdio_set_block_size 512 failed!\n");
796     }
797     else {
798         //printk(KERN_INFO DRV_NAME"sdio_set_block_size 512 done!\n");
799     }
800
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);
805 #endif
806     return TRUE;
807 } /* end of glBusInit() */
808
809
810 /*----------------------------------------------------------------------------*/
811 /*!
812 * \brief Stop bus operation and release resources.
813 *
814 * \param[in] pvData A pointer to struct net_device.
815 *
816 * \return (none)
817 */
818 /*----------------------------------------------------------------------------*/
819 VOID
820 glBusRelease (
821     PVOID pvData
822     )
823 {
824
825     return;
826 } /* end of glBusRelease() */
827
828
829 /*----------------------------------------------------------------------------*/
830 /*!
831 * \brief Setup bus interrupt operation and interrupt handler for os.
832 *
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.
836 *
837 * \retval WLAN_STATUS_SUCCESS   if success
838 *         NEGATIVE_VALUE   if fail
839 */
840 /*----------------------------------------------------------------------------*/
841 INT_32
842 glBusSetIrq (
843     PVOID pvData,
844     PVOID pfnIsr,
845     PVOID pvCookie
846     )
847 {
848     int ret = 0;
849
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;
854
855     ASSERT(pvData);
856     if (!pvData) {
857         return -1;
858     }
859     prNetDevice = (struct net_device *) pvData;
860     prGlueInfo = (P_GLUE_INFO_T) pvCookie;
861     ASSERT(prGlueInfo);
862     if (!prGlueInfo) {
863         return -1;
864     }
865
866     prHifInfo = &prGlueInfo->rHifInfo;
867
868     sdio_claim_host(prHifInfo->func);
869     ret = sdio_claim_irq(prHifInfo->func, mtk_sdio_interrupt);
870     sdio_release_host(prHifInfo->func);
871 #else
872     /* hif_sdio case */
873     struct net_device *prNetDevice = NULL;
874     P_GLUE_INFO_T prGlueInfo = NULL;
875
876     ASSERT(pvData);
877     if (!pvData) {
878         return -1;
879     }
880     prNetDevice = (struct net_device *) pvData;
881
882     prGlueInfo = (P_GLUE_INFO_T) pvCookie;
883     ASSERT(prGlueInfo);
884     if (!prGlueInfo) {
885         return -1;
886     }
887
888     mtk_wcn_hif_sdio_enable_irq(prGlueInfo->rHifInfo.cltCtx, MTK_WCN_BOOL_TRUE);
889
890 #endif
891     return ret;
892 } /* end of glBusSetIrq() */
893
894
895 /*----------------------------------------------------------------------------*/
896 /*!
897 * \brief Stop bus interrupt operation and disable interrupt handling for os.
898 *
899 * \param[in] pvData     A pointer to struct net_device.
900 * \param[in] pvCookie   Private data for pfnIsr function.
901 *
902 * \return (none)
903 */
904 /*----------------------------------------------------------------------------*/
905 VOID
906 glBusFreeIrq (
907     PVOID pvData,
908     PVOID pvCookie
909     )
910 {
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;
915     int ret = 0;
916
917     ASSERT(pvData);
918     if (!pvData) {
919         //printk(KERN_INFO DRV_NAME"%s null pvData\n", __FUNCTION__);
920         return;
921     }
922     prNetDevice = (struct net_device *) pvData;
923     prGlueInfo = (P_GLUE_INFO_T) pvCookie;
924     ASSERT(prGlueInfo);
925     if (!prGlueInfo) {
926         //printk(KERN_INFO DRV_NAME"%s no glue info\n", __FUNCTION__);
927         return;
928     }
929
930     prHifInfo = &prGlueInfo->rHifInfo;
931
932     sdio_claim_host(prHifInfo->func);
933     ret = sdio_release_irq(prHifInfo->func);
934     sdio_release_host(prHifInfo->func);
935 #else
936     /* hif_sdio case */
937     struct net_device *prNetDevice = NULL;
938     P_GLUE_INFO_T prGlueInfo = NULL;
939
940     ASSERT(pvData);
941     if (!pvData) {
942         //printk(KERN_INFO DRV_NAME"%s null pvData\n", __FUNCTION__);
943         return;
944     }
945     prNetDevice = (struct net_device *) pvData;
946
947     prGlueInfo = (P_GLUE_INFO_T) pvCookie;
948     ASSERT(prGlueInfo);
949     if (!prGlueInfo) {
950         //printk(KERN_INFO DRV_NAME"%s no glue info\n", __FUNCTION__);
951         return;
952     }
953
954     mtk_wcn_hif_sdio_enable_irq(prGlueInfo->rHifInfo.cltCtx, MTK_WCN_BOOL_FALSE);
955 #endif
956
957     return;
958 } /* end of glBusreeIrq() */
959
960
961 /*----------------------------------------------------------------------------*/
962 /*!
963 * \brief Read a 32-bit device register
964 *
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
968 *
969 * \retval TRUE          operation success
970 * \retval FALSE         operation fail
971 */
972 /*----------------------------------------------------------------------------*/
973 BOOL
974 kalDevRegRead (
975     IN  P_GLUE_INFO_T   prGlueInfo,
976     IN  UINT_32         u4Register,
977     OUT PUINT_32        pu4Value
978     )
979 {
980     int ret = 0;
981         int a = 0;
982
983     ASSERT(prGlueInfo);
984     ASSERT(pu4Value);
985
986 #if MTK_WCN_HIF_SDIO
987     ret = mtk_wcn_hif_sdio_readl(prGlueInfo->rHifInfo.cltCtx, u4Register, (PUINT32) pu4Value);
988 #else
989     if (!in_interrupt) {
990         sdio_claim_host(prGlueInfo->rHifInfo.func);
991     }
992
993 retry:
994     *pu4Value = sdio_readl(prGlueInfo->rHifInfo.func, u4Register, &ret);
995         if (ret && a < 10) {
996                 a++;
997                 printk("gwl =-==============> sdio_readl retry %d!\n", a);
998                 msleep(1);
999                 goto retry;
1000         }       
1001
1002     if (!in_interrupt) {
1003         sdio_release_host(prGlueInfo->rHifInfo.func);
1004     }
1005 #endif
1006
1007     if (ret) {
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));
1010     }
1011
1012     return (ret) ? FALSE : TRUE;
1013 } /* end of kalDevRegRead() */
1014
1015
1016 /*----------------------------------------------------------------------------*/
1017 /*!
1018 * \brief Write a 32-bit device register
1019 *
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
1023 *
1024 * \retval TRUE          operation success
1025 * \retval FALSE         operation fail
1026 */
1027 /*----------------------------------------------------------------------------*/
1028 BOOL
1029 kalDevRegWrite (
1030     IN P_GLUE_INFO_T  prGlueInfo,
1031     IN UINT_32        u4Register,
1032     IN UINT_32        u4Value
1033     )
1034 {
1035     int ret = 0;
1036         int a = 0;
1037
1038     ASSERT(prGlueInfo);
1039
1040 #if MTK_WCN_HIF_SDIO
1041     ret = mtk_wcn_hif_sdio_writel(prGlueInfo->rHifInfo.cltCtx, u4Register, u4Value);
1042 #else
1043     if (!in_interrupt) {
1044         sdio_claim_host(prGlueInfo->rHifInfo.func);
1045     }
1046
1047 retry:
1048     sdio_writel(prGlueInfo->rHifInfo.func, u4Value, u4Register, &ret);
1049         if (ret && a < 10) {
1050                 a++;
1051                 printk("gwl =-==============> sdio_writel retry %d!\n", a);
1052                 msleep(1);
1053                 goto retry;
1054         }
1055
1056     if (!in_interrupt) {
1057         sdio_release_host(prGlueInfo->rHifInfo.func);
1058     }
1059 #endif
1060
1061     if (ret) {
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));
1064     }
1065
1066     return (ret) ? FALSE : TRUE;
1067 } /* end of kalDevRegWrite() */
1068
1069
1070 /*----------------------------------------------------------------------------*/
1071 /*!
1072 * \brief Read device I/O port
1073 *
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
1079 *
1080 * \retval TRUE          operation success
1081 * \retval FALSE         operation fail
1082 */
1083 /*----------------------------------------------------------------------------*/
1084 BOOL
1085 kalDevPortRead (
1086     IN  P_GLUE_INFO_T   prGlueInfo,
1087     IN  UINT_16         u2Port,
1088     IN  UINT_16         u2Len,
1089     OUT PUINT_8         pucBuf,
1090     IN  UINT_16         u2ValidOutBufSize
1091     )
1092 {
1093     P_GL_HIF_INFO_T prHifInfo = NULL;
1094     PUINT_8 pucDst = NULL;
1095     int count = u2Len;
1096     int ret = 0;
1097     int bNum = 0;
1098
1099 #if (MTK_WCN_HIF_SDIO == 0)
1100     struct sdio_func *prSdioFunc = NULL;
1101 #endif
1102
1103     #if DBG
1104     //printk(KERN_INFO DRV_NAME"++kalDevPortRead++ buf:0x%p, port:0x%x, length:%d\n", pucBuf, u2Port, u2Len);
1105     #endif
1106
1107     ASSERT(prGlueInfo);
1108     prHifInfo = &prGlueInfo->rHifInfo;
1109
1110     ASSERT(pucBuf);
1111     pucDst = pucBuf;
1112
1113     ASSERT(u2Len <= u2ValidOutBufSize);
1114
1115 #if (MTK_WCN_HIF_SDIO == 0)
1116     prSdioFunc = prHifInfo->func;
1117
1118     ASSERT(prSdioFunc->cur_blksize > 0);
1119
1120     if (!in_interrupt) {
1121         sdio_claim_host(prSdioFunc);
1122     }
1123
1124     /* Split buffer into multiple single block to workaround hifsys */
1125     while (count >= prSdioFunc->cur_blksize) {
1126         count -= prSdioFunc->cur_blksize;
1127         bNum++;
1128     }
1129     if (count > 0 && bNum > 0) {
1130         bNum++;
1131     }
1132
1133     if (bNum > 0) {
1134         ret = sdio_readsb(prSdioFunc, pucDst, u2Port, prSdioFunc->cur_blksize * bNum);
1135
1136 #ifdef CONFIG_X86
1137         /* ENE workaround */
1138         {
1139             int tmp;
1140             sdio_writel(prSdioFunc, 0x0, SDIO_X86_WORKAROUND_WRITE_MCR, &tmp);
1141         }
1142 #endif
1143
1144     }
1145     else {
1146         if(count & 0x3L) {
1147             int aligned_count = (count+3) & (~0x3L);
1148             ret = sdio_readsb(prSdioFunc, pucDst, u2Port, aligned_count);
1149         } else {
1150             ret = sdio_readsb(prSdioFunc, pucDst, u2Port, count);
1151         }       
1152     }
1153
1154     if (!in_interrupt) {
1155         sdio_release_host(prSdioFunc);
1156     }
1157 #else
1158
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);
1162         bNum++;
1163     }
1164     if (count > 0 && bNum > 0) {
1165         bNum++;
1166     }
1167
1168     if (bNum > 0) {
1169         ret = mtk_wcn_hif_sdio_read_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucDst,
1170                  ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz) * bNum);
1171     }
1172     else {
1173         ret = mtk_wcn_hif_sdio_read_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucDst, count);
1174     }
1175 #endif
1176
1177     if (ret) {
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));
1180     }
1181
1182     return (ret) ? FALSE : TRUE;
1183 } /* end of kalDevPortRead() */
1184
1185
1186 /*----------------------------------------------------------------------------*/
1187 /*!
1188 * \brief Write device I/O port
1189 *
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
1195 *
1196 * \retval TRUE          operation success
1197 * \retval FALSE         operation fail
1198 */
1199 /*----------------------------------------------------------------------------*/
1200 BOOL
1201 kalDevPortWrite (
1202     IN P_GLUE_INFO_T  prGlueInfo,
1203     IN UINT_16        u2Port,
1204     IN UINT_16        u2Len,
1205     IN PUINT_8        pucBuf,
1206     IN UINT_16        u2ValidInBufSize
1207     )
1208 {
1209     P_GL_HIF_INFO_T prHifInfo = NULL;
1210     PUINT_8 pucSrc = NULL;
1211     int count = u2Len;
1212     int ret = 0;
1213     int bNum = 0;
1214
1215 #if (MTK_WCN_HIF_SDIO == 0)
1216     struct sdio_func *prSdioFunc = NULL;
1217 #endif
1218
1219     #if DBG
1220     //printk(KERN_INFO DRV_NAME"++kalDevPortWrite++ buf:0x%p, port:0x%x, length:%d\n", pucBuf, u2Port, u2Len);
1221     #endif
1222
1223     ASSERT(prGlueInfo);
1224     prHifInfo = &prGlueInfo->rHifInfo;
1225
1226     ASSERT(pucBuf);
1227     pucSrc = pucBuf;
1228
1229     ASSERT(u2Len <= u2ValidInBufSize);
1230
1231 #if (MTK_WCN_HIF_SDIO == 0)
1232     prSdioFunc = prHifInfo->func;
1233     ASSERT(prSdioFunc->cur_blksize > 0);
1234
1235     if (!in_interrupt) {
1236         sdio_claim_host(prSdioFunc);
1237     }
1238
1239     /* Split buffer into multiple single block to workaround hifsys */
1240     while (count >= prSdioFunc->cur_blksize) {
1241         count -= prSdioFunc->cur_blksize;
1242         bNum++;
1243     }
1244     if (count > 0 && bNum > 0) {
1245         bNum++;
1246     }
1247
1248     if (bNum > 0) { // block mode
1249         ret = sdio_writesb(prSdioFunc, u2Port, pucSrc, prSdioFunc->cur_blksize * bNum);
1250
1251 #ifdef CONFIG_X86
1252         /* ENE workaround */
1253         {
1254             int tmp;
1255             sdio_writel(prSdioFunc, 0x0, SDIO_X86_WORKAROUND_WRITE_MCR, &tmp);
1256         }
1257 #endif
1258
1259     }
1260     else {  // byte mode
1261         if(count & 0x3L) {
1262             int aligned_count = (count+3) & (~0x3L);
1263             ret = sdio_writesb(prSdioFunc, u2Port, pucSrc, aligned_count);
1264         } else {
1265             ret = sdio_writesb(prSdioFunc, u2Port, pucSrc, count);
1266         }
1267     }
1268
1269     if (!in_interrupt) {
1270         sdio_release_host(prSdioFunc);
1271     }
1272 #else
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);
1276         bNum++;
1277     }
1278     if (count > 0 && bNum > 0) {
1279         bNum++;
1280     }
1281
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);
1285     }
1286     else {  // byte mode
1287         ret = mtk_wcn_hif_sdio_write_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucSrc, count);
1288     }
1289 #endif
1290
1291     if (ret) {
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));
1294     }
1295
1296     return (ret) ? FALSE : TRUE;
1297 } /* end of kalDevPortWrite() */
1298
1299
1300 /*----------------------------------------------------------------------------*/
1301 /*!
1302 * \brief Write device I/O port in byte with CMD52
1303 *
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
1307 *
1308 * \retval TRUE          operation success
1309 * \retval FALSE         operation fail
1310 */
1311 /*----------------------------------------------------------------------------*/
1312 BOOL
1313 kalDevWriteWithSdioCmd52 (
1314     IN P_GLUE_INFO_T    prGlueInfo,
1315     IN UINT_32          u4Addr,
1316     IN UINT_8           ucData
1317     )
1318 {
1319     int ret = 0;
1320
1321 #if (MTK_WCN_HIF_SDIO == 0)
1322     if (!in_interrupt) {
1323         sdio_claim_host(prGlueInfo->rHifInfo.func);
1324     }
1325
1326     sdio_writeb(prGlueInfo->rHifInfo.func, ucData, u4Addr, &ret);
1327
1328     if (!in_interrupt) {
1329         sdio_release_host(prGlueInfo->rHifInfo.func);
1330     }
1331 #else
1332     ret = mtk_wcn_hif_sdio_writeb(prGlueInfo->rHifInfo.cltCtx, u4Addr, ucData);
1333 #endif
1334
1335     if (ret) {
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));
1338     }
1339
1340     return (ret) ? FALSE : TRUE;
1341
1342 } /* end of kalDevWriteWithSdioCmd52() */
1343
1344
1345 VOID
1346 glSetPowerState (
1347     IN P_GLUE_INFO_T  prGlueInfo,
1348     IN UINT_32 ePowerMode
1349     )
1350 {
1351     return;
1352 }
1353