support different wifi bt chip auto compatible
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / mt5931_kk / drv_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 * LEGAL DISCLAIMER
15 *
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.
29 *
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.
35 *
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
41 * (ICC).
42 ********************************************************************************
43 */
44
45 /*
46 ** $Log: sdio.c $
47 ** 
48 ** 08 24 2012 cp.wu
49 ** [WCXRP00001269] [MT6620 Wi-Fi][Driver] cfg80211 porting merge back to DaVinci
50 ** .
51 ** 
52 ** 08 24 2012 cp.wu
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.
55  *
56  * 04 12 2012 terry.wu
57  * NULL
58  * Add AEE message support
59  * 1) Show AEE warning(red screen) if SDIO access error occurs
60
61  *
62  * 02 14 2012 cp.wu
63  * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree
64  * include correct header file upon setting.
65  *
66  * 11 10 2011 cp.wu
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.
70  *
71  * 09 20 2011 cp.wu
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
75  *
76  * 08 17 2011 cp.wu
77  * [WCXRP00000851] [MT6628 Wi-Fi][Driver] Add HIFSYS related definition to driver source tree
78  * add MT6628 related definitions for Linux/Android driver.
79  *
80  * 05 18 2011 cp.wu
81  * [WCXRP00000702] [MT5931][Driver] Modify initialization sequence for E1 ASIC
82  * add device ID for MT5931.
83  *
84  * 04 08 2011 pat.lu
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
87  *
88  * 03 22 2011 pat.lu
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.
91  *
92  * 03 18 2011 cp.wu
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.
95  *
96  * 03 15 2011 cp.wu
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
100  *
101  *
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.
105  *
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
109  *
110  * 11 08 2010 cp.wu
111  * [WCXRP00000166] [MT6620 Wi-Fi][Driver] use SDIO CMD52 for enabling/disabling interrupt to reduce transaction period
112  * correct typo
113  *
114  * 11 08 2010 cp.wu
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
117  *
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.
121  *
122  * 10 19 2010 cp.wu
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.
125  *
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
129  *
130  * 08 21 2010 jeffrey.chang
131  * NULL
132  * 1) add sdio two setting
133  * 2) bug fix of sdio glue
134  *
135  * 08 18 2010 jeffrey.chang
136  * NULL
137  * support multi-function sdio
138  *
139  * 08 18 2010 cp.wu
140  * NULL
141  * #if defined(__X86__) is not working, change to use #ifdef CONFIG_X86.
142  *
143  * 08 17 2010 cp.wu
144  * NULL
145  * add ENE SDIO host workaround for x86 linux platform.
146  *
147  * 07 08 2010 cp.wu
148  *
149  * [WPD00003833] [MT6620 and MT5931] Driver migration - move to new repository.
150  *
151  * 06 06 2010 kevin.huang
152  * [WPD00003832][MT6620 5931] Create driver base
153  * [MT6620 5931] Create driver base
154  *
155  * 05 07 2010 jeffrey.chang
156  * [WPD00003826]Initial import for Linux port
157  * Fix hotplug bug
158  *
159  * 03 28 2010 jeffrey.chang
160  * [WPD00003826]Initial import for Linux port
161  * clear sdio interrupt
162  *
163  * 03 24 2010 jeffrey.chang
164  * [WPD00003826]Initial import for Linux port
165  * initial import for Linux port
166 **
167 */
168
169 /*******************************************************************************
170 *                         C O M P I L E R   F L A G S
171 ********************************************************************************
172 */
173
174 /*******************************************************************************
175 *                    E X T E R N A L   R E F E R E N C E S
176 ********************************************************************************
177 */
178
179 #include "gl_os.h"
180
181 #if MTK_WCN_HIF_SDIO
182 #include "hif_sdio.h"
183 #else
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>
189 #endif
190
191 #include <linux/mm.h>
192 #ifndef CONFIG_X86
193 #include <asm/memory.h>
194 #endif
195
196 #if defined(MT6620)
197     #include "mt6620_reg.h"
198 #elif defined(MT5931)
199     #include "mt5931_reg.h"
200 #elif defined(MT6628)
201     #include "mt6628_reg.h"
202 #endif
203
204 #if CFG_DBG_GPIO_PINS/* FIXME: move to platform or custom header */
205 #include <mach/mt6516_gpio.h>
206 #endif
207
208 /*******************************************************************************
209 *                              C O N S T A N T S
210 ********************************************************************************
211 */
212
213 #define HIF_SDIO_ERR_TITLE_STR              "["CHIP_NAME"] SDIO Access Error!"
214 #define HIF_SDIO_ERR_DESC_STR               "**SDIO Access Error**\n"
215
216 #if MTK_WCN_HIF_SDIO
217
218
219 /*
220  * function prototypes
221  *
222  */
223
224 static INT32
225 mtk_sdio_probe(MTK_WCN_HIF_SDIO_CLTCTX, const MTK_WCN_HIF_SDIO_FUNCINFO *);
226
227 static INT32
228 mtk_sdio_remove(MTK_WCN_HIF_SDIO_CLTCTX);
229 static INT32 mtk_sdio_interrupt(MTK_WCN_HIF_SDIO_CLTCTX);
230
231 /*
232  * sdio function info table
233  */
234
235 static MTK_WCN_HIF_SDIO_FUNCINFO funcInfo[] = {
236 #if defined(MT6620)
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) },
245 #endif
246 };
247
248
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,
255 };
256
257 #else
258
259 static const struct sdio_device_id mtk_sdio_ids[] = {
260 #if defined(MT6620)
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 */
268 #endif
269         { /* end: all zeroes */ },
270 };
271
272 MODULE_DEVICE_TABLE(sdio, mtk_sdio_ids);
273
274 #endif
275
276 /*******************************************************************************
277 *                             D A T A   T Y P E S
278 ********************************************************************************
279 */
280
281
282 /*******************************************************************************
283 *                            P U B L I C   D A T A
284 ********************************************************************************
285 */
286
287 /*******************************************************************************
288 *                           P R I V A T E   D A T A
289 ********************************************************************************
290 */
291 static probe_card pfWlanProbe = NULL;
292 static remove_card pfWlanRemove = NULL;
293
294
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,
299         .probe          = NULL,
300         .remove         = NULL,
301 };
302 #endif
303
304
305 #if CFG_DBG_GPIO_PINS
306
307 /* debug 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 */
330 };
331 #endif
332 /*******************************************************************************
333 *                                 M A C R O S
334 ********************************************************************************
335 */
336
337 /*******************************************************************************
338 *                   F U N C T I O N   D E C L A R A T I O N S
339 ********************************************************************************
340 */
341
342 /*******************************************************************************
343 *                              F U N C T I O N S
344 ********************************************************************************
345 */
346 #if CFG_DBG_GPIO_PINS
347 void debug_gpio_init(void)
348 {
349     int i;
350
351     for (i = 0; i < sizeof(dbgPinSTP)/sizeof(dbgPinSTP[0]); ++i) {
352         if (GPIO_INVALID == dbgPinSTP[i]) {
353             continue;
354         }
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 */
359
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*/
365     }
366     //printk(KERN_INFO "[%s] initialization ok \n", __FUNCTION__);
367 }
368
369 void debug_gpio_deinit(void)
370 {
371     int i;
372     for (i = 0; i < sizeof(dbgPinSTP)/sizeof(dbgPinSTP[0]); ++i) {
373         if (GPIO_INVALID == dbgPinSTP[i]) {
374             continue;
375         }
376         //printk(KERN_INFO "[%s] %ld \n", __FUNCTION__, dbgPinSTP[i]);
377         mt_set_gpio_dir(dbgPinSTP[i], GPIO_DIR_IN);
378     }
379
380     //printk(KERN_INFO "[%s] k\n", __FUNCTION__);
381 }
382
383 void mtk_wcn_stp_debug_gpio_assert(UINT_32 dwIndex, UINT_32 dwMethod)
384 {
385     unsigned int i;
386
387     if (dwIndex >= (sizeof(dbgPinSTP)/sizeof(dbgPinSTP[0]))) {
388         //printk(KERN_INFO "[%s] invalid dwIndex(%ld) \n", __FUNCTION__, dwIndex);
389         return;
390     }
391
392     if (dwIndex > IDX_STP_MAX) {
393         //printk(KERN_INFO "[%s] dwIndex(%ld) > IDX_STP_MAX(%d) \n", __FUNCTION__, dwIndex, IDX_STP_MAX);
394     }
395
396     if (GPIO_INVALID == dbgPinSTP[dwIndex]) {
397         return;
398     }
399
400     if (dwMethod & DBG_TIE_DIR) {
401         if (dwMethod & DBG_HIGH) {
402             mt_set_gpio_out(dbgPinSTP[dwIndex], GPIO_OUT_ONE);
403         }
404         else {
405             mt_set_gpio_out(dbgPinSTP[dwIndex], GPIO_OUT_ZERO);
406         }
407         return;
408     }
409
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);
414         }
415         return;
416     }
417
418     return;
419 }
420 #endif
421
422 /*----------------------------------------------------------------------------*/
423 /*!
424 * \brief This function is a SDIO interrupt callback function
425 *
426 * \param[in] func  pointer to SDIO handle
427 *
428 * \return void
429 */
430 /*----------------------------------------------------------------------------*/
431
432 #if MTK_WCN_HIF_SDIO
433
434 static INT32 mtk_sdio_interrupt(MTK_WCN_HIF_SDIO_CLTCTX cltCtx)
435 {
436     P_GLUE_INFO_T prGlueInfo = NULL;
437     INT32 ret = 0;
438
439     prGlueInfo = mtk_wcn_hif_sdio_get_drvdata(cltCtx);
440
441     ASSERT(prGlueInfo);
442
443     if (!prGlueInfo) {
444         //printk(KERN_INFO DRV_NAME"No glue info in mtk_sdio_interrupt()\n");
445         return (-HIF_SDIO_ERR_FAIL);
446     }
447
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);
451         return ret;
452     }
453
454     ret = mtk_wcn_hif_sdio_writel(cltCtx, MCR_WHLPCR, WHLPCR_INT_EN_CLR);
455
456     set_bit (GLUE_FLAG_INT_BIT, &prGlueInfo->u4Flag);
457
458     /* when we got sdio interrupt, we wake up the tx servie thread*/
459     wake_up_interruptible(&prGlueInfo->waitq);
460
461     return ret;
462 }
463
464 #else
465
466 static unsigned int in_interrupt = 0;
467
468 static void mtk_sdio_interrupt(struct sdio_func *func)
469 {
470     P_GLUE_INFO_T prGlueInfo = NULL;
471
472     int ret = 0;
473
474     prGlueInfo = sdio_get_drvdata(func);
475     ASSERT(prGlueInfo);
476
477     if (!prGlueInfo) {
478         //printk(KERN_INFO DRV_NAME"No glue info in mtk_sdio_interrupt()\n");
479         return;
480     }
481
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");
485         return;
486     }
487
488     sdio_writel(prGlueInfo->rHifInfo.func, WHLPCR_INT_EN_CLR, MCR_WHLPCR, &ret);
489
490     #if 0
491     wlanISR(prGlueInfo->prAdapter, TRUE);
492
493     if (prGlueInfo->u4Flag & GLUE_FLAG_HALT) {
494         /* Should stop now... skip pending interrupt */
495         //printk(KERN_INFO DRV_NAME"ignore pending interrupt\n");
496     }
497     else {
498         wlanIST(prGlueInfo->prAdapter);
499     }
500     #endif
501
502     set_bit (GLUE_FLAG_INT_BIT, &prGlueInfo->u4Flag);
503
504     /* when we got sdio interrupt, we wake up the tx servie thread*/
505     wake_up_interruptible(&prGlueInfo->waitq);
506 }
507 #endif
508
509 /*----------------------------------------------------------------------------*/
510 /*!
511 * \brief This function is a SDIO probe function
512 *
513 * \param[in] func   pointer to SDIO handle
514 * \param[in] id     pointer to SDIO device id table
515 *
516 * \return void
517 */
518 /*----------------------------------------------------------------------------*/
519
520 #if MTK_WCN_HIF_SDIO
521
522 // FIXME: global variable
523 static const MTK_WCN_HIF_SDIO_FUNCINFO *prFunc;
524
525
526 static INT32
527 mtk_sdio_probe(MTK_WCN_HIF_SDIO_CLTCTX cltCtx, const MTK_WCN_HIF_SDIO_FUNCINFO *prFuncInfo)
528 {
529     INT32 ret = HIF_SDIO_ERR_SUCCESS;
530
531     prFunc = prFuncInfo;
532
533     if (pfWlanProbe((PVOID) &cltCtx) != WLAN_STATUS_SUCCESS) {
534         //printk(KERN_WARNING DRV_NAME"pfWlanProbe fail!call pfWlanRemove()\n");
535         pfWlanRemove();
536         ret = -(HIF_SDIO_ERR_FAIL);
537     } else {
538         //printk(KERN_INFO DRV_NAME"mtk_wifi_sdio_probe() done(%d)\n", ret);
539     }
540     return ret;
541 }
542 #else
543 static int mtk_sdio_probe (
544     struct sdio_func *func,
545     const struct sdio_device_id *id
546     )
547 {
548     int ret = 0;
549     int i = 0;
550
551     //printk(KERN_INFO DRV_NAME "mtk_sdio_probe()\n");
552
553     ASSERT(func);
554     ASSERT(id);
555
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));
565
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);
569
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]);
572     }
573
574     sdio_claim_host(func);
575     ret = sdio_enable_func(func);
576     sdio_release_host(func);
577
578     if (ret) {
579         //printk(KERN_INFO DRV_NAME"sdio_enable_func failed!\n");
580         goto out;
581     }
582     //printk(KERN_INFO DRV_NAME"sdio_enable_func done!\n");
583
584     if (pfWlanProbe((PVOID)func) != WLAN_STATUS_SUCCESS) {
585         //printk(KERN_WARNING DRV_NAME"pfWlanProbe fail!call pfWlanRemove()\n");
586         pfWlanRemove();
587         ret = -1;
588     }
589     else {
590 #if CFG_DBG_GPIO_PINS
591     //printk(KERN_INFO "[%s] init debug gpio, 20100815 \n", __FUNCTION__);
592     /* Debug pins initialization */
593     debug_gpio_init();
594 #endif
595     }
596
597 out:
598     //printk(KERN_INFO DRV_NAME"mtk_sdio_probe() done(%d)\n", ret);
599     return ret;
600 }
601 #endif
602
603
604 #if MTK_WCN_HIF_SDIO
605 static INT32
606 mtk_sdio_remove(MTK_WCN_HIF_SDIO_CLTCTX cltCtx)
607 {
608     INT32 ret = HIF_SDIO_ERR_SUCCESS;
609     //printk(KERN_INFO DRV_NAME"pfWlanRemove done\n");
610     pfWlanRemove();
611
612     return ret;
613 }
614 #else
615 static void
616 mtk_sdio_remove (
617     struct sdio_func *func
618     )
619 {
620     //printk(KERN_INFO DRV_NAME"mtk_sdio_remove()\n");
621
622 #if CFG_DBG_GPIO_PINS
623     //printk(KERN_INFO "[%s] deinit debug gpio \n", __FUNCTION__);
624     debug_gpio_deinit();
625 #endif
626
627     ASSERT(func);
628     //printk(KERN_INFO DRV_NAME"pfWlanRemove done\n");
629     pfWlanRemove();
630
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);
635
636     //printk(KERN_INFO DRV_NAME"mtk_sdio_remove() done\n");
637 }
638 #endif
639
640 #if (MTK_WCN_HIF_SDIO == 0)
641 static int
642 mtk_sdio_suspend (
643     struct device * pDev,
644     pm_message_t state
645     )
646 {
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");
649
650     return 0;
651 }
652
653 int mtk_sdio_resume (
654     struct device * pDev
655     )
656 {
657     //printk(KERN_INFO "mtk_sdio: mtk_sdio_resume dev(0x%p)\n", pDev);
658
659     return 0;
660 }
661 #endif
662
663 static const struct dev_pm_ops mtk_sdio_pmops = {
664         .suspend = mtk_sdio_suspend,
665         .resume = mtk_sdio_resume,
666 };
667 /*----------------------------------------------------------------------------*/
668 /*!
669 * \brief This function will register sdio bus to the os
670 *
671 * \param[in] pfProbe    Function pointer to detect card
672 * \param[in] pfRemove   Function pointer to remove card
673 *
674 * \return The result of registering sdio bus
675 */
676 /*----------------------------------------------------------------------------*/
677 WLAN_STATUS
678 glRegisterBus (
679     probe_card pfProbe,
680     remove_card pfRemove
681     )
682 {
683     int ret = 0;
684
685     ASSERT(pfProbe);
686     ASSERT(pfRemove);
687
688     //printk(KERN_INFO "mtk_sdio: MediaTek SDIO WLAN driver\n");
689     //printk(KERN_INFO "mtk_sdio: Copyright MediaTek Inc.\n");
690
691     pfWlanProbe = pfProbe;
692     pfWlanRemove = pfRemove;
693
694 #if MTK_WCN_HIF_SDIO
695     /* register MTK sdio client */
696     ret = ((mtk_wcn_hif_sdio_client_reg(&cltInfo) == HIF_SDIO_ERR_SUCCESS) ? WLAN_STATUS_SUCCESS : WLAN_STATUS_FAILURE);
697 #else
698     mtk_sdio_driver.probe = mtk_sdio_probe;
699     mtk_sdio_driver.remove = mtk_sdio_remove;
700
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;
705 #endif
706         
707
708     return ret;
709 } /* end of glRegisterBus() */
710
711
712 /*----------------------------------------------------------------------------*/
713 /*!
714 * \brief This function will unregister sdio bus to the os
715 *
716 * \param[in] pfRemove   Function pointer to remove card
717 *
718 * \return (none)
719 */
720 /*----------------------------------------------------------------------------*/
721 VOID
722 glUnregisterBus(
723     remove_card pfRemove
724     )
725 {
726     ASSERT(pfRemove);
727     pfRemove();
728
729 #if MTK_WCN_HIF_SDIO
730     /* unregister MTK sdio client */
731     mtk_wcn_hif_sdio_client_unreg(&cltInfo);
732 #else
733     sdio_unregister_driver(&mtk_sdio_driver);
734 #endif
735
736     return;
737 } /* end of glUnregisterBus() */
738
739
740 /*----------------------------------------------------------------------------*/
741 /*!
742 * \brief This function stores hif related info, which is initialized before.
743 *
744 * \param[in] prGlueInfo Pointer to glue info structure
745 * \param[in] u4Cookie   Pointer to UINT_32 memory base variable for _HIF_HPI
746 *
747 * \return (none)
748 */
749 /*----------------------------------------------------------------------------*/
750 VOID
751 glSetHifInfo (
752     P_GLUE_INFO_T prGlueInfo,
753     UINT_32 u4Cookie
754     )
755 {
756     P_GL_HIF_INFO_T prHif = NULL;
757
758     prHif = &prGlueInfo->rHifInfo;
759
760 #if MTK_WCN_HIF_SDIO
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);
765
766 #else
767     prHif->func = (struct sdio_func *) u4Cookie;
768
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);
773
774     sdio_set_drvdata(prHif->func, prGlueInfo);
775
776     SET_NETDEV_DEV(prGlueInfo->prDevHandler, &prHif->func->dev);
777 #endif
778
779     return;
780 } /* end of glSetHifInfo() */
781
782 /*----------------------------------------------------------------------------*/
783 /*!
784 * \brief This function clears hif related info.
785 *
786 * \param[in] prGlueInfo Pointer to glue info structure
787 *
788 * \return (none)
789 */
790 /*----------------------------------------------------------------------------*/
791 VOID
792 glClearHifInfo (
793     P_GLUE_INFO_T prGlueInfo
794     )
795 {
796     //P_GL_HIF_INFO_T prHif = NULL;
797     //ASSERT(prGlueInfo);
798     //prHif = &prGlueInfo->rHifInfo;
799
800     return;
801 } /* end of glClearHifInfo() */
802
803
804 /*----------------------------------------------------------------------------*/
805 /*!
806 * \brief Initialize bus operation and hif related information, request resources.
807 *
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.
811 *
812 * \return (none)
813 */
814 /*----------------------------------------------------------------------------*/
815 BOOL
816 glBusInit (
817     PVOID pvData
818     )
819 {
820 #if (MTK_WCN_HIF_SDIO == 0)
821     int ret = 0;
822     struct sdio_func *func = NULL;
823
824     ASSERT(pvData);
825
826     func = (struct sdio_func *) pvData;
827
828     sdio_claim_host(func);
829     ret = sdio_set_block_size(func, 512);
830     sdio_release_host(func);
831
832     if (ret) {
833         //printk(KERN_INFO DRV_NAME"sdio_set_block_size 512 failed!\n");
834     }
835     else {
836         //printk(KERN_INFO DRV_NAME"sdio_set_block_size 512 done!\n");
837     }
838
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);
843 #endif
844     return TRUE;
845 } /* end of glBusInit() */
846
847
848 /*----------------------------------------------------------------------------*/
849 /*!
850 * \brief Stop bus operation and release resources.
851 *
852 * \param[in] pvData A pointer to struct net_device.
853 *
854 * \return (none)
855 */
856 /*----------------------------------------------------------------------------*/
857 VOID
858 glBusRelease (
859     PVOID pvData
860     )
861 {
862
863     return;
864 } /* end of glBusRelease() */
865
866
867 /*----------------------------------------------------------------------------*/
868 /*!
869 * \brief Setup bus interrupt operation and interrupt handler for os.
870 *
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.
874 *
875 * \retval WLAN_STATUS_SUCCESS   if success
876 *         NEGATIVE_VALUE   if fail
877 */
878 /*----------------------------------------------------------------------------*/
879 INT_32
880 glBusSetIrq (
881     PVOID pvData,
882     PVOID pfnIsr,
883     PVOID pvCookie
884     )
885 {
886     int ret = 0;
887
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;
892
893     ASSERT(pvData);
894     if (!pvData) {
895         return -1;
896     }
897     prNetDevice = (struct net_device *) pvData;
898     prGlueInfo = (P_GLUE_INFO_T) pvCookie;
899     ASSERT(prGlueInfo);
900     if (!prGlueInfo) {
901         return -1;
902     }
903
904     prHifInfo = &prGlueInfo->rHifInfo;
905
906     sdio_claim_host(prHifInfo->func);
907     ret = sdio_claim_irq(prHifInfo->func, mtk_sdio_interrupt);
908     sdio_release_host(prHifInfo->func);
909 #endif
910     return ret;
911 } /* end of glBusSetIrq() */
912
913
914 /*----------------------------------------------------------------------------*/
915 /*!
916 * \brief Stop bus interrupt operation and disable interrupt handling for os.
917 *
918 * \param[in] pvData     A pointer to struct net_device.
919 * \param[in] pvCookie   Private data for pfnIsr function.
920 *
921 * \return (none)
922 */
923 /*----------------------------------------------------------------------------*/
924 VOID
925 glBusFreeIrq (
926     PVOID pvData,
927     PVOID pvCookie
928     )
929 {
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;
934     int ret = 0;
935
936     ASSERT(pvData);
937     if (!pvData) {
938         //printk(KERN_INFO DRV_NAME"%s null pvData\n", __FUNCTION__);
939         return;
940     }
941     prNetDevice = (struct net_device *) pvData;
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     prHifInfo = &prGlueInfo->rHifInfo;
950
951     sdio_claim_host(prHifInfo->func);
952     ret = sdio_release_irq(prHifInfo->func);
953     sdio_release_host(prHifInfo->func);
954 #endif
955
956     return;
957 } /* end of glBusreeIrq() */
958
959
960 /*----------------------------------------------------------------------------*/
961 /*!
962 * \brief Read a 32-bit device register
963 *
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
967 *
968 * \retval TRUE          operation success
969 * \retval FALSE         operation fail
970 */
971 /*----------------------------------------------------------------------------*/
972 BOOL
973 kalDevRegRead (
974     IN  P_GLUE_INFO_T   prGlueInfo,
975     IN  UINT_32         u4Register,
976     OUT PUINT_32        pu4Value
977     )
978 {
979     int ret = 0;
980
981     ASSERT(prGlueInfo);
982     ASSERT(pu4Value);
983
984 #if MTK_WCN_HIF_SDIO
985     ret = mtk_wcn_hif_sdio_readl(prGlueInfo->rHifInfo.cltCtx, u4Register, (PUINT32) pu4Value);
986 #else
987     if (!in_interrupt) {
988         sdio_claim_host(prGlueInfo->rHifInfo.func);
989     }
990
991     *pu4Value = sdio_readl(prGlueInfo->rHifInfo.func, u4Register, &ret);
992
993     if (!in_interrupt) {
994         sdio_release_host(prGlueInfo->rHifInfo.func);
995     }
996 #endif
997
998     if (ret) {
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));
1001     }
1002
1003     return (ret) ? FALSE : TRUE;
1004 } /* end of kalDevRegRead() */
1005
1006
1007 /*----------------------------------------------------------------------------*/
1008 /*!
1009 * \brief Write a 32-bit device register
1010 *
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
1014 *
1015 * \retval TRUE          operation success
1016 * \retval FALSE         operation fail
1017 */
1018 /*----------------------------------------------------------------------------*/
1019 BOOL
1020 kalDevRegWrite (
1021     IN P_GLUE_INFO_T  prGlueInfo,
1022     IN UINT_32        u4Register,
1023     IN UINT_32        u4Value
1024     )
1025 {
1026     int ret = 0;
1027
1028     ASSERT(prGlueInfo);
1029
1030 #if MTK_WCN_HIF_SDIO
1031     ret = mtk_wcn_hif_sdio_writel(prGlueInfo->rHifInfo.cltCtx, u4Register, u4Value);
1032 #else
1033     if (!in_interrupt) {
1034         sdio_claim_host(prGlueInfo->rHifInfo.func);
1035     }
1036
1037     sdio_writel(prGlueInfo->rHifInfo.func, u4Value, u4Register, &ret);
1038
1039     if (!in_interrupt) {
1040         sdio_release_host(prGlueInfo->rHifInfo.func);
1041     }
1042 #endif
1043
1044     if (ret) {
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));
1047     }
1048
1049     return (ret) ? FALSE : TRUE;
1050 } /* end of kalDevRegWrite() */
1051
1052
1053 /*----------------------------------------------------------------------------*/
1054 /*!
1055 * \brief Read device I/O port
1056 *
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
1062 *
1063 * \retval TRUE          operation success
1064 * \retval FALSE         operation fail
1065 */
1066 /*----------------------------------------------------------------------------*/
1067 BOOL
1068 kalDevPortRead (
1069     IN  P_GLUE_INFO_T   prGlueInfo,
1070     IN  UINT_16         u2Port,
1071     IN  UINT_16         u2Len,
1072     OUT PUINT_8         pucBuf,
1073     IN  UINT_16         u2ValidOutBufSize
1074     )
1075 {
1076     P_GL_HIF_INFO_T prHifInfo = NULL;
1077     PUINT_8 pucDst = NULL;
1078     int count = u2Len;
1079     int ret = 0;
1080     int bNum = 0;
1081
1082 #if (MTK_WCN_HIF_SDIO == 0)
1083     struct sdio_func *prSdioFunc = NULL;
1084 #endif
1085
1086     #if DBG
1087     //printk(KERN_INFO DRV_NAME"++kalDevPortRead++ buf:0x%p, port:0x%x, length:%d\n", pucBuf, u2Port, u2Len);
1088     #endif
1089
1090     ASSERT(prGlueInfo);
1091     prHifInfo = &prGlueInfo->rHifInfo;
1092
1093     ASSERT(pucBuf);
1094     pucDst = pucBuf;
1095
1096     ASSERT(u2Len <= u2ValidOutBufSize);
1097
1098 #if (MTK_WCN_HIF_SDIO == 0)
1099     prSdioFunc = prHifInfo->func;
1100
1101     ASSERT(prSdioFunc->cur_blksize > 0);
1102
1103     if (!in_interrupt) {
1104         sdio_claim_host(prSdioFunc);
1105     }
1106
1107     /* Split buffer into multiple single block to workaround hifsys */
1108     while (count >= prSdioFunc->cur_blksize) {
1109         count -= prSdioFunc->cur_blksize;
1110         bNum++;
1111     }
1112     if (count > 0 && bNum > 0) {
1113         bNum++;
1114     }
1115
1116     if (bNum > 0) {
1117         ret = sdio_readsb(prSdioFunc, pucDst, u2Port, prSdioFunc->cur_blksize * bNum);
1118
1119 #ifdef CONFIG_X86
1120         /* ENE workaround */
1121         {
1122             int tmp;
1123             sdio_writel(prSdioFunc, 0x0, SDIO_X86_WORKAROUND_WRITE_MCR, &tmp);
1124         }
1125 #endif
1126
1127     }
1128     else {
1129         ret = sdio_readsb(prSdioFunc, pucDst, u2Port, count);
1130     }
1131
1132     if (!in_interrupt) {
1133         sdio_release_host(prSdioFunc);
1134     }
1135 #else
1136
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);
1140         bNum++;
1141     }
1142     if (count > 0 && bNum > 0) {
1143         bNum++;
1144     }
1145
1146     if (bNum > 0) {
1147         ret = mtk_wcn_hif_sdio_read_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucDst,
1148                  ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz) * bNum);
1149     }
1150     else {
1151         ret = mtk_wcn_hif_sdio_read_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucDst, count);
1152     }
1153 #endif
1154
1155     if (ret) {
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));
1158     }
1159
1160     return (ret) ? FALSE : TRUE;
1161 } /* end of kalDevPortRead() */
1162
1163
1164 /*----------------------------------------------------------------------------*/
1165 /*!
1166 * \brief Write device I/O port
1167 *
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
1173 *
1174 * \retval TRUE          operation success
1175 * \retval FALSE         operation fail
1176 */
1177 /*----------------------------------------------------------------------------*/
1178 BOOL
1179 kalDevPortWrite (
1180     IN P_GLUE_INFO_T  prGlueInfo,
1181     IN UINT_16        u2Port,
1182     IN UINT_16        u2Len,
1183     IN PUINT_8        pucBuf,
1184     IN UINT_16        u2ValidInBufSize
1185     )
1186 {
1187     P_GL_HIF_INFO_T prHifInfo = NULL;
1188     PUINT_8 pucSrc = NULL;
1189     int count = u2Len;
1190     int ret = 0;
1191     int bNum = 0;
1192
1193 #if (MTK_WCN_HIF_SDIO == 0)
1194     struct sdio_func *prSdioFunc = NULL;
1195 #endif
1196
1197     #if DBG
1198     //printk(KERN_INFO DRV_NAME"++kalDevPortWrite++ buf:0x%p, port:0x%x, length:%d\n", pucBuf, u2Port, u2Len);
1199     #endif
1200
1201     ASSERT(prGlueInfo);
1202     prHifInfo = &prGlueInfo->rHifInfo;
1203
1204     ASSERT(pucBuf);
1205     pucSrc = pucBuf;
1206
1207     ASSERT(u2Len <= u2ValidInBufSize);
1208
1209 #if (MTK_WCN_HIF_SDIO == 0)
1210     prSdioFunc = prHifInfo->func;
1211     ASSERT(prSdioFunc->cur_blksize > 0);
1212
1213     if (!in_interrupt) {
1214         sdio_claim_host(prSdioFunc);
1215     }
1216
1217     /* Split buffer into multiple single block to workaround hifsys */
1218     while (count >= prSdioFunc->cur_blksize) {
1219         count -= prSdioFunc->cur_blksize;
1220         bNum++;
1221     }
1222     if (count > 0 && bNum > 0) {
1223         bNum++;
1224     }
1225
1226         count = (count+3)/4*4;
1227     if (bNum > 0) { // block mode
1228         ret = sdio_writesb(prSdioFunc, u2Port, pucSrc, prSdioFunc->cur_blksize * bNum);
1229
1230 #ifdef CONFIG_X86
1231         /* ENE workaround */
1232         {
1233             int tmp;
1234             sdio_writel(prSdioFunc, 0x0, SDIO_X86_WORKAROUND_WRITE_MCR, &tmp);
1235         }
1236 #endif
1237
1238     }
1239     else {  // byte mode
1240
1241         ret = sdio_writesb(prSdioFunc, u2Port, pucSrc, count);
1242     }
1243
1244     if (!in_interrupt) {
1245         sdio_release_host(prSdioFunc);
1246     }
1247 #else
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);
1251         bNum++;
1252     }
1253     if (count > 0 && bNum > 0) {
1254         bNum++;
1255     }
1256
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);
1260     }
1261     else {  // byte mode
1262         ret = mtk_wcn_hif_sdio_write_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucSrc, count);
1263     }
1264 #endif
1265
1266     if (ret) {
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));
1269     }
1270
1271     return (ret) ? FALSE : TRUE;
1272 } /* end of kalDevPortWrite() */
1273
1274
1275 /*----------------------------------------------------------------------------*/
1276 /*!
1277 * \brief Write device I/O port in byte with CMD52
1278 *
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
1282 *
1283 * \retval TRUE          operation success
1284 * \retval FALSE         operation fail
1285 */
1286 /*----------------------------------------------------------------------------*/
1287 BOOL
1288 kalDevWriteWithSdioCmd52 (
1289     IN P_GLUE_INFO_T    prGlueInfo,
1290     IN UINT_32          u4Addr,
1291     IN UINT_8           ucData
1292     )
1293 {
1294     int ret = 0;
1295
1296 #if (MTK_WCN_HIF_SDIO == 0)
1297     if (!in_interrupt) {
1298         sdio_claim_host(prGlueInfo->rHifInfo.func);
1299     }
1300
1301     sdio_writeb(prGlueInfo->rHifInfo.func, ucData, u4Addr, &ret);
1302
1303     if (!in_interrupt) {
1304         sdio_release_host(prGlueInfo->rHifInfo.func);
1305     }
1306 #else
1307     ret = mtk_wcn_hif_sdio_writeb(prGlueInfo->rHifInfo.cltCtx, u4Addr, ucData);
1308 #endif
1309
1310     if (ret) {
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));
1313     }
1314
1315     return (ret) ? FALSE : TRUE;
1316
1317 } /* end of kalDevWriteWithSdioCmd52() */
1318
1319
1320 VOID
1321 glSetPowerState (
1322     IN P_GLUE_INFO_T  prGlueInfo,
1323     IN UINT_32 ePowerMode
1324     )
1325 {
1326     return;
1327 }
1328