14 * 07 25 2010 george.kuo
16 * Move hif_sdio driver to linux directory.
18 * 07 23 2010 george.kuo
20 * Add MT6620 driver source tree
21 * , including char device driver (wmt, bt, gps), stp driver, interface driver (tty ldisc and hif_sdio), and bt hci driver.
27 /*******************************************************************************
28 * C O M P I L E R F L A G S
29 ********************************************************************************
31 #define HIF_SDIO_UPDATE (1)
32 #if (WMT_PLAT_APEX==1)
33 #define HIF_SDIO_SUPPORT_SUSPEND (1)
35 #define HIF_SDIO_SUPPORT_SUSPEND (0)
38 /*******************************************************************************
39 * E X T E R N A L R E F E R E N C E S
40 ********************************************************************************
46 #include "hif_sdio_chrdev.h"
49 extern void mmc_power_up_ext(struct mmc_host *host);
50 extern void mmc_power_off_ext(struct mmc_host *host);
52 #define mmc_power_up_ext(x)
53 #define mmc_power_off_ext(x)
56 /*******************************************************************************
58 ********************************************************************************
60 //#define DRV_NAME "[hif_sdio]"
62 /*******************************************************************************
64 ********************************************************************************
67 /*******************************************************************************
69 ********************************************************************************
72 * \brief A macro used to generate hif_sdio client's context
74 * Generate a context for hif_sdio client based on the following input parameters
75 * |<-card id (16bits)->|<-block size in unit of 256 bytes(8 bits)->|<-function number(4bits)->|<-index(4bits)->|
77 * \param manf the 16 bit manufacturer id
78 * \param card the 16 bit card id
79 * \param func the 16 bit function number
80 * \param b_sz the 16 bit function block size
82 #define CLTCTX(cid, func, blk_sz, idx) \
83 (MTK_WCN_HIF_SDIO_CLTCTX)( (((UINT32)(cid) & 0xFFFFUL) << 16) | \
84 (((UINT32)(func) & 0xFUL) << 4) | \
85 (((UINT32)(blk_sz) & 0xFF00UL) << 0) | \
86 (((UINT32)idx & 0xFUL) << 0) )
89 * \brief A set of macros used to get information out of an hif_sdio client context
91 * Generate a context for hif_sdio client based on the following input parameters
93 #define CLTCTX_CID(ctx) (((ctx) >> 16) & 0xFFFF)
94 #define CLTCTX_FUNC(ctx) (((ctx) >> 4) & 0xF)
95 #define CLTCTX_BLK_SZ(ctx) (((ctx) >> 0) & 0xFF00)
96 #define CLTCTX_IDX(ctx) ((ctx) & 0xF)
97 #define CLTCTX_IDX_VALID(idx) ((idx >= 0) && (idx < CFG_CLIENT_COUNT))
99 /*******************************************************************************
100 * F U N C T I O N D E C L A R A T I O N S
101 ********************************************************************************
103 #if HIF_SDIO_SUPPORT_SUSPEND
104 static int hif_sdio_suspend (
108 static int hif_sdio_resume (
112 static int hif_sdio_probe (
113 struct sdio_func *func,
114 const struct sdio_device_id *id
117 static void hif_sdio_remove (
118 struct sdio_func *func
121 static void hif_sdio_irq (
122 struct sdio_func *func
125 static int hif_sdio_clt_probe_func (
126 MTK_WCN_HIF_SDIO_REGISTINFO *registinfo_p,
130 static void hif_sdio_clt_probe_worker(
131 struct work_struct *work
134 static int hif_sdio_find_probed_list_index_by_func(
135 struct sdio_func *func
138 #if 0 // TODO:[ChangeFeature][George] remove obsolete function?
139 static int hif_sdio_find_probed_list_index_by_clt_index(
144 static int hif_sdio_find_probed_list_index_by_id_func(
150 static void hif_sdio_init_clt_list(
154 static int hif_sdio_find_clt_list_index (
160 static int hif_sdio_check_supported_sdio_id(
165 static int hif_sdio_check_duplicate_sdio_id(
171 static int hif_sdio_add_clt_list(
173 const MTK_WCN_HIF_SDIO_CLTINFO *pinfo,
177 static INT32 hif_sdio_stp_on(
181 static INT32 hif_sdio_stp_off(
185 static INT32 hif_sdio_wifi_on(
189 static INT32 hif_sdio_wifi_off(
193 /*******************************************************************************
194 * P R I V A T E D A T A
195 ********************************************************************************
198 /* Supported SDIO device table */
199 static const struct sdio_device_id mtk_sdio_id_tbl[] = {
200 /* MT6618 */ /* Not an SDIO standard class device */
201 { SDIO_DEVICE(0x037A, 0x018A) }, /* SDIO1:WIFI */
202 { SDIO_DEVICE(0x037A, 0x018B) }, /* SDIO2:FUNC1:BT+FM */
203 { SDIO_DEVICE(0x037A, 0x018C) }, /* 2-function (SDIO2:FUNC1:BT+FM, FUNC2:WIFI) */
205 /* MT6619 */ /* Not an SDIO standard class device */
206 { SDIO_DEVICE(0x037A, 0x6619) }, /* SDIO2:FUNC1:BT+FM+GPS */
208 /* MT6620 */ /* Not an SDIO standard class device */
209 { SDIO_DEVICE(0x037A, 0x020A) }, /* SDIO1:FUNC1:WIFI */
210 { SDIO_DEVICE(0x037A, 0x020B) }, /* SDIO2:FUNC1:BT+FM+GPS */
211 { SDIO_DEVICE(0x037A, 0x020C) }, /* 2-function (SDIO2:FUNC1:BT+FM+GPS, FUNC2:WIFI) */
213 /* MT5921 */ /* Not an SDIO standard class device */
214 { SDIO_DEVICE(0x037A, 0x5921) },
216 /* MT6628 */ /* SDIO1: Wi-Fi, SDIO2: BGF */
217 { SDIO_DEVICE(0x037A, 0x6628) },
218 { /* end: all zeroes */ },
221 #if HIF_SDIO_SUPPORT_SUSPEND
222 static const struct dev_pm_ops mtk_sdio_pmops = {
223 .suspend = hif_sdio_suspend,
224 .resume = hif_sdio_resume,
228 static struct sdio_driver mtk_sdio_client_drv = {
229 .name = "mtk_sdio_client", /* MTK SDIO Client Driver */
230 .id_table = mtk_sdio_id_tbl, /* all supported struct sdio_device_id table */
231 .probe = hif_sdio_probe,
232 .remove = hif_sdio_remove,
233 #if HIF_SDIO_SUPPORT_SUSPEND
235 .pm = &mtk_sdio_pmops,
240 /* Registered client driver list */
241 /* static list g_hif_sdio_clt_drv_list */
242 static MTK_WCN_HIF_SDIO_REGISTINFO g_hif_sdio_clt_drv_list[CFG_CLIENT_COUNT];
244 /* MMC probed function list */
245 /* static list g_hif_sdio_probed_func_list */
246 static MTK_WCN_HIF_SDIO_PROBEINFO g_hif_sdio_probed_func_list[CFG_CLIENT_COUNT];
248 /* spin lock info for g_hif_sdio_clt_drv_list and g_hif_sdio_probed_func_list */
249 static MTK_WCN_HIF_SDIO_LOCKINFO g_hif_sdio_lock_info;
251 /* reference count, debug information? */
252 static int gRefCount;
253 static int (*fp_wmt_tra_sdio_update)(void) = NULL;
256 /*******************************************************************************
257 * P U B L I C D A T A
258 ********************************************************************************
260 MODULE_LICENSE("GPL");
261 MODULE_AUTHOR("MediaTek Inc WCN_SE_CS3");
262 MODULE_DESCRIPTION("MediaTek MT6620 HIF SDIO Driver");
264 MODULE_DEVICE_TABLE(sdio, mtk_sdio_id_tbl);
266 UINT32 gHifSdioDbgLvl = HIF_SDIO_LOG_INFO;
268 /*******************************************************************************
270 ********************************************************************************
273 #if (WMT_PLAT_APEX==0)
274 extern int mtk_wcn_sdio_irq_flag_set (int falg);
276 int mtk_wcn_sdio_irq_flag_set (int falg)
285 * \brief register the callback funciton for record the timestamp of sdio access
287 * \param callback function
289 * \retval -EINVAL, when registered callback is invalid
290 * \retval 0, when registered callback is valid
292 extern INT32 mtk_wcn_hif_sdio_update_cb_reg(int (*ts_update)(void))
295 fp_wmt_tra_sdio_update = ts_update;
305 * \brief update the accessing time of SDIO via callback function
309 * \retval -EINVAL, when callback is not registered
310 * \retval returned value of callback
312 static INT32 wmt_tra_sdio_update(VOID)
314 if(fp_wmt_tra_sdio_update){
315 return (*fp_wmt_tra_sdio_update)();
318 //HIF_SDIO_WARN_FUNC("wmt_tra_sdio_update == NULL\n");
323 * \brief Translate CLTCTX into a pointer to struct sdio_func if it is valid
325 * Translate a CLTCTX into a pointer to struct sdio_func if it is
326 * 1) probed by mmc_core, and
327 * 2) client driver is registered, and
328 * 3) clt_idx of client driver is valid
330 * \param ctx a context provided by client driver
332 * \retval null if any condition is not valie
333 * \retval a pointer to a struct sdio_func mapped by provided ctx
335 static inline struct sdio_func* hif_sdio_ctx_to_func (
336 MTK_WCN_HIF_SDIO_CLTCTX ctx)
340 //4 <1> check if ctx is valid, registered, and probed
341 probe_index = CLTCTX_IDX(ctx);
342 if (unlikely(!CLTCTX_IDX_VALID(probe_index))) /* invalid index in CLTCTX */
344 HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx);
349 if (unlikely(g_hif_sdio_probed_func_list[probe_index].clt_idx < 0)) /* the client has not been registered */
351 HIF_SDIO_WARN_FUNC("can't find client idx in probed list!ctx(0x%x) prob_idx(%d) clt_idx(%d)\n",
352 ctx, probe_index, g_hif_sdio_probed_func_list[probe_index].clt_idx);
356 return g_hif_sdio_probed_func_list[probe_index].func;
360 * \brief MTK hif sdio client registration function
362 * Client uses this function to register itself to hif_sdio driver
364 * \param pinfo a pointer of client's information
366 * \retval 0 register successfully
367 * \retval < 0 list error code here
369 INT32 mtk_wcn_hif_sdio_client_reg (
370 const MTK_WCN_HIF_SDIO_CLTINFO *pinfo
373 INT32 ret = -HIF_SDIO_ERR_FAIL;
374 INT32 clt_index = -1;
377 MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_probe_worker_info = 0;
379 HIF_SDIO_INFO_FUNC("start!\n");
381 //4 <1> check input pointer is valid
382 HIF_SDIO_ASSERT( pinfo );
384 //4 <2> check if input parameters are all supported and valid
385 for ( i=0; i<pinfo->func_tbl_size; i++ )
387 ret = hif_sdio_check_supported_sdio_id( pinfo->func_tbl[i].manf_id, pinfo->func_tbl[i].card_id );
390 HIF_SDIO_WARN_FUNC("vendor id(0x%x) and device id(0x%x) of sdio_func are not supported in mtk_sdio_id_tbl!\n",
391 pinfo->func_tbl[i].manf_id,
392 pinfo->func_tbl[i].card_id);
396 HIF_SDIO_DBG_FUNC("hif_sdio_check_supported_sdio_id() done!\n");
398 //4 <3> check if the specific {manf id, card id, function number} tuple is
399 //4 already resigstered
400 for ( i=0; i<pinfo->func_tbl_size; i++ )
402 ret = hif_sdio_check_duplicate_sdio_id( pinfo->func_tbl[i].manf_id, pinfo->func_tbl[i].card_id, pinfo->func_tbl[i].func_num );
405 HIF_SDIO_WARN_FUNC("vendor id(0x%x), device id(0x%x), and fun_num(%d) of sdio_func are duplicated in g_hif_sdio_clt_drv_list!\n",
406 pinfo->func_tbl[i].manf_id,
407 pinfo->func_tbl[i].card_id,
408 pinfo->func_tbl[i].func_num );
412 HIF_SDIO_DBG_FUNC("hif_sdio_check_duplicate_sdio_id() done!\n");
414 //4 <4> add the specified {manf id, card id, function number} tuple to registered client list
415 HIF_SDIO_DBG_FUNC("pinfo->func_tbl_size:%d\n", pinfo->func_tbl_size);
416 for ( i=0; i<pinfo->func_tbl_size; i++ )
418 ret = hif_sdio_add_clt_list( &clt_index, pinfo, i );
421 HIF_SDIO_WARN_FUNC("client's info are added in registed client list failed (buffer is full)!\n");
424 HIF_SDIO_DBG_FUNC("hif_sdio_add_clt_list() done (gRefCount=%d)!\n", gRefCount);
426 //4 <5> if the specific {manf id, card id, function number} tuple has already
427 //4 been probed by mmc, schedule another task to call client's .hif_clt_probe()
428 for ( j=0; j<CFG_CLIENT_COUNT; j++ )
431 spin_lock_bh( &g_hif_sdio_lock_info.probed_list_lock );
432 if ( g_hif_sdio_probed_func_list[j].func == 0 )
434 // probed spin unlock
435 spin_unlock_bh( &g_hif_sdio_lock_info.probed_list_lock );
438 /* the function has been probed */
439 if ( (g_hif_sdio_clt_drv_list[clt_index].func_info->manf_id == g_hif_sdio_probed_func_list[j].func->vendor) &&\
440 (g_hif_sdio_clt_drv_list[clt_index].func_info->card_id == g_hif_sdio_probed_func_list[j].func->device) &&\
441 (g_hif_sdio_clt_drv_list[clt_index].func_info->func_num == g_hif_sdio_probed_func_list[j].func->num) )
443 g_hif_sdio_probed_func_list[j].clt_idx = clt_index;
444 // probed spin unlock
445 spin_unlock_bh( &g_hif_sdio_lock_info.probed_list_lock );
447 /* use worker thread to perform the client's .hif_clt_probe() */
448 clt_probe_worker_info = vmalloc( sizeof(MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO) );
449 INIT_WORK( &clt_probe_worker_info->probe_work, hif_sdio_clt_probe_worker );
450 clt_probe_worker_info->registinfo_p = &g_hif_sdio_clt_drv_list[clt_index];
451 clt_probe_worker_info->probe_idx = j;
452 schedule_work( &clt_probe_worker_info->probe_work );
454 //4 <5.1> remember to do claim_irq for the func if it's irq had been released.
455 if ( !(g_hif_sdio_probed_func_list[j].func->irq_handler) )
457 sdio_claim_host(g_hif_sdio_probed_func_list[j].func);
458 ret = sdio_claim_irq(g_hif_sdio_probed_func_list[j].func, hif_sdio_irq);
459 mtk_wcn_sdio_irq_flag_set (1);
460 sdio_release_host(g_hif_sdio_probed_func_list[j].func);
461 HIF_SDIO_INFO_FUNC("sdio_claim_irq for func(0x%p) j(%d) v(0x%x) d(0x%x) ok\n",
462 g_hif_sdio_probed_func_list[j].func, j,
463 g_hif_sdio_probed_func_list[j].func->vendor,
464 g_hif_sdio_probed_func_list[j].func->device
467 //4 <5.2> Reset the block size of the function provided by client
468 HIF_SDIO_INFO_FUNC("Reset sdio block size: %d!\n", g_hif_sdio_clt_drv_list[clt_index].func_info->blk_sz);
469 sdio_claim_host(g_hif_sdio_probed_func_list[j].func);
470 ret = sdio_set_block_size(g_hif_sdio_probed_func_list[j].func,\
471 g_hif_sdio_clt_drv_list[clt_index].func_info->blk_sz);
472 sdio_release_host(g_hif_sdio_probed_func_list[j].func);
476 // probed spin unlock
477 spin_unlock_bh( &g_hif_sdio_lock_info.probed_list_lock );
480 HIF_SDIO_DBG_FUNC("map g_hif_sdio_clt_drv_list to g_hif_sdio_probed_func_list done!\n");
482 ret = HIF_SDIO_ERR_SUCCESS;
486 //4 <last> error handling
488 HIF_SDIO_DBG_FUNC("end!\n");
490 } /* end of mtk_wcn_hif_sdio_client_reg() */
493 * \brief MTK hif sdio client un-registration function
495 * Client uses this function to un-register itself
497 * \param pinfo a pointer of client's information
499 * \retval 0 register successfully
500 * \retval < 0 list error code here
502 INT32 mtk_wcn_hif_sdio_client_unreg (
503 const MTK_WCN_HIF_SDIO_CLTINFO *pinfo
506 INT32 ret = -HIF_SDIO_ERR_FAIL;
507 INT32 clt_list_index = 0;
511 HIF_SDIO_INFO_FUNC("start!\n");
513 //4 <1> check if input pointer is valid
514 HIF_SDIO_ASSERT( pinfo );
516 //4 <2> check if input parameters are all supported and valid
517 for ( i=0; i<pinfo->func_tbl_size; i++ )
519 ret = hif_sdio_check_supported_sdio_id( pinfo->func_tbl[i].manf_id, pinfo->func_tbl[i].card_id );
522 HIF_SDIO_WARN_FUNC("vendor id(0x%x) and device id(0x%x) of sdio_func are not supported in mtk_sdio_id_tbl!\n",
523 pinfo->func_tbl[i].manf_id,
524 pinfo->func_tbl[i].card_id);
529 //4 <3> check if the specific {manf id, card id, function number} tuple is already resigstered
530 //4 and find the corresponding client ctx and call client's .hif_clt_remove() in THIS context
531 for ( i=0; i<pinfo->func_tbl_size; i++ )
533 clt_list_index = hif_sdio_find_clt_list_index(pinfo->func_tbl[i].manf_id, pinfo->func_tbl[i].card_id, pinfo->func_tbl[i].func_num);
534 if ( clt_list_index < 0 )
536 HIF_SDIO_WARN_FUNC("vendor id(0x%x), device id(0x%x), and fun_num(%d) client info is not in the client's registed list!\n",
537 pinfo->func_tbl[i].manf_id,
538 pinfo->func_tbl[i].card_id,
539 pinfo->func_tbl[i].func_num );
540 ret = -HIF_SDIO_ERR_FAIL;
544 //4 <4> mark the specified {manf id, card id, function number} tuple as
545 //4 un-registered and invalidate client's context
546 hif_sdio_init_clt_list( clt_list_index );
548 /* un-map g_hif_sdio_clt_drv_list index in g_hif_sdio_probed_func_list */
549 for ( j=0; j<CFG_CLIENT_COUNT; j++ )
551 if ( g_hif_sdio_probed_func_list[j].clt_idx == clt_list_index )
553 g_hif_sdio_probed_func_list[j].clt_idx = -1;
559 ret = HIF_SDIO_ERR_SUCCESS;
561 HIF_SDIO_INFO_FUNC("end (gRefCount=%d) !\n", gRefCount);
563 }/* end of mtk_wcn_hif_sdio_client_unreg() */
568 * detailed descriptions
570 * \param ctx client's context variable
572 * \retval 0 register successfully
573 * \retval < 0 list error code here
575 INT32 mtk_wcn_hif_sdio_readb (
576 MTK_WCN_HIF_SDIO_CLTCTX ctx,
583 struct sdio_func* func;
585 INT32 ret = -HIF_SDIO_ERR_FAIL;
586 int probe_index = -1;
587 struct sdio_func* func = 0;
590 HIF_SDIO_DBG_FUNC("start!\n");
591 HIF_SDIO_ASSERT( pvb );
593 //4 <1> check if ctx is valid, registered, and probed
595 ret = -HIF_SDIO_ERR_FAIL;
596 func = hif_sdio_ctx_to_func(ctx);
598 ret = -HIF_SDIO_ERR_FAIL;
602 probe_index = CLTCTX_IDX(ctx);
603 if( probe_index < 0 ) /* the function has not been probed */
605 HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
606 ret = -HIF_SDIO_ERR_FAIL;
611 if ( g_hif_sdio_probed_func_list[probe_index].clt_idx < 0 ) /* the client has not been registered */
613 HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
614 ret = -HIF_SDIO_ERR_FAIL;
618 func = g_hif_sdio_probed_func_list[probe_index].func;
622 sdio_claim_host(func);
623 *pvb = sdio_readb(func, offset, &ret);
624 sdio_release_host(func);
626 //4 <3> check result code and return proper error code
629 HIF_SDIO_DBG_FUNC("end!\n");
631 } /* end of mtk_wcn_hif_sdio_client_unreg() */
636 * detailed descriptions
638 * \param ctx client's context variable
640 * \retval 0 register successfully
641 * \retval < 0 list error code here
643 INT32 mtk_wcn_hif_sdio_writeb (
644 MTK_WCN_HIF_SDIO_CLTCTX ctx,
651 struct sdio_func* func;
653 INT32 ret = -HIF_SDIO_ERR_FAIL;
654 int probe_index = -1;
655 struct sdio_func* func = 0;
658 HIF_SDIO_DBG_FUNC("start!\n");
660 //4 <1> check if ctx is valid, registered, and probed
662 ret = -HIF_SDIO_ERR_FAIL;
663 func = hif_sdio_ctx_to_func(ctx);
665 ret = -HIF_SDIO_ERR_FAIL;
669 probe_index = CLTCTX_IDX(ctx);
670 if( probe_index < 0 ) /* the function has not been probed */
672 HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
673 ret = -HIF_SDIO_ERR_FAIL;
678 if ( g_hif_sdio_probed_func_list[probe_index].clt_idx < 0 ) /* the client has not been registered */
680 HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
681 ret = -HIF_SDIO_ERR_FAIL;
685 func = g_hif_sdio_probed_func_list[probe_index].func;
688 //4 <1.1> check if input parameters are valid
691 wmt_tra_sdio_update();
692 sdio_claim_host(func);
693 sdio_writeb(func, vb, offset, &ret);
694 sdio_release_host(func);
696 //4 <3> check result code and return proper error code
699 HIF_SDIO_DBG_FUNC("end!\n");
701 } /* end of mtk_wcn_hif_sdio_client_unreg() */
706 * detailed descriptions
708 * \param ctx client's context variable
710 * \retval 0 register successfully
711 * \retval < 0 list error code here
713 INT32 mtk_wcn_hif_sdio_readl (
714 MTK_WCN_HIF_SDIO_CLTCTX ctx,
721 struct sdio_func* func;
723 INT32 ret = -HIF_SDIO_ERR_FAIL;
724 int probe_index = -1;
725 struct sdio_func* func = 0;
728 HIF_SDIO_DBG_FUNC("start!\n");
729 HIF_SDIO_ASSERT( pvl );
731 //4 <1> check if ctx is valid, registered, and probed
733 ret = -HIF_SDIO_ERR_FAIL;
734 func = hif_sdio_ctx_to_func(ctx);
736 ret = -HIF_SDIO_ERR_FAIL;
740 probe_index = CLTCTX_IDX(ctx);
741 if( probe_index < 0 ) /* the function has not been probed */
743 HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
744 ret = -HIF_SDIO_ERR_FAIL;
749 if ( g_hif_sdio_probed_func_list[probe_index].clt_idx < 0 ) /* the client has not been registered */
751 HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
752 ret = -HIF_SDIO_ERR_FAIL;
756 func = g_hif_sdio_probed_func_list[probe_index].func;
758 //4 <1.1> check if input parameters are valid
761 sdio_claim_host(func);
762 *pvl = sdio_readl(func, offset, &ret);
763 sdio_release_host(func);
765 //4 <3> check result code and return proper error code
768 HIF_SDIO_DBG_FUNC("end!\n");
770 } /* end of mtk_wcn_hif_sdio_client_unreg() */
775 * detailed descriptions
777 * \param ctx client's context variable
779 * \retval 0 register successfully
780 * \retval < 0 list error code here
782 INT32 mtk_wcn_hif_sdio_writel (
783 MTK_WCN_HIF_SDIO_CLTCTX ctx,
790 struct sdio_func* func;
792 INT32 ret = -HIF_SDIO_ERR_FAIL;
793 int probe_index = -1;
794 struct sdio_func* func = 0;
797 HIF_SDIO_DBG_FUNC("start!\n");
799 //4 <1> check if ctx is valid, registered, and probed
801 ret = -HIF_SDIO_ERR_FAIL;
802 func = hif_sdio_ctx_to_func(ctx);
804 ret = -HIF_SDIO_ERR_FAIL;
808 probe_index = CLTCTX_IDX(ctx);
809 if( probe_index < 0 ) /* the function has not been probed */
811 HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
812 ret = -HIF_SDIO_ERR_FAIL;
817 if ( g_hif_sdio_probed_func_list[probe_index].clt_idx < 0 ) /* the client has not been registered */
819 HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
820 ret = -HIF_SDIO_ERR_FAIL;
824 func = g_hif_sdio_probed_func_list[probe_index].func;
826 //4 <1.1> check if input parameters are valid
829 wmt_tra_sdio_update();
830 sdio_claim_host(func);
831 sdio_writel(func, vl, offset, &ret);
832 sdio_release_host(func);
834 //4 <3> check result code and return proper error code
837 HIF_SDIO_DBG_FUNC("end!\n");
839 } /* end of mtk_wcn_hif_sdio_client_unreg() */
844 * detailed descriptions
846 * \param ctx client's context variable
848 * \retval 0 register successfully
849 * \retval < 0 list error code here
851 INT32 mtk_wcn_hif_sdio_read_buf (
852 MTK_WCN_HIF_SDIO_CLTCTX ctx,
860 struct sdio_func* func;
862 INT32 ret = -HIF_SDIO_ERR_FAIL;
863 int probe_index = -1;
864 struct sdio_func* func = 0;
867 HIF_SDIO_DBG_FUNC("start!\n");
868 HIF_SDIO_ASSERT( pbuf );
870 //4 <1> check if ctx is valid, registered, and probed
872 ret = -HIF_SDIO_ERR_FAIL;
873 func = hif_sdio_ctx_to_func(ctx);
875 ret = -HIF_SDIO_ERR_FAIL;
879 probe_index = CLTCTX_IDX(ctx);
880 if( probe_index < 0 ) /* the function has not been probed */
882 HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
883 ret = -HIF_SDIO_ERR_FAIL;
888 if ( g_hif_sdio_probed_func_list[probe_index].clt_idx < 0 ) /* the client has not been registered */
890 HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
891 ret = -HIF_SDIO_ERR_FAIL;
895 func = g_hif_sdio_probed_func_list[probe_index].func;
897 //4 <1.1> check if input parameters are valid
900 sdio_claim_host(func);
901 ret = sdio_readsb(func, pbuf, offset, len);
902 sdio_release_host(func);
904 //4 <3> check result code and return proper error code
907 HIF_SDIO_DBG_FUNC("end!\n");
909 } /* end of mtk_wcn_hif_sdio_read_buf() */
915 * detailed descriptions
917 * \param ctx client's context variable
919 * \retval 0 register successfully
920 * \retval < 0 list error code here
922 INT32 mtk_wcn_hif_sdio_write_buf (
923 MTK_WCN_HIF_SDIO_CLTCTX ctx,
931 struct sdio_func* func;
933 INT32 ret = -HIF_SDIO_ERR_FAIL;
934 int probe_index = -1;
935 struct sdio_func* func = 0;
938 HIF_SDIO_DBG_FUNC("start!\n");
939 HIF_SDIO_ASSERT( pbuf );
941 //4 <1> check if ctx is valid, registered, and probed
943 ret = -HIF_SDIO_ERR_FAIL;
944 func = hif_sdio_ctx_to_func(ctx);
946 ret = -HIF_SDIO_ERR_FAIL;
950 probe_index = CLTCTX_IDX(ctx);
951 if( probe_index < 0 ) /* the function has not been probed */
953 HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
954 ret = -HIF_SDIO_ERR_FAIL;
959 if ( g_hif_sdio_probed_func_list[probe_index].clt_idx < 0 ) /* the client has not been registered */
961 HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
962 ret = -HIF_SDIO_ERR_FAIL;
966 func = g_hif_sdio_probed_func_list[probe_index].func;
968 //4 <1.1> check if input parameters are valid
971 wmt_tra_sdio_update();
972 sdio_claim_host(func);
973 ret = sdio_writesb(func, offset, pbuf, len);
974 sdio_release_host(func);
976 //4 <3> check result code and return proper error code
979 HIF_SDIO_DBG_FUNC("ret(%d) end!\n", ret);
982 } /* end of mtk_wcn_hif_sdio_write_buf() */
985 * \brief store client driver's private data function.
988 * \param clent's MTK_WCN_HIF_SDIO_CLTCTX.
992 void mtk_wcn_hif_sdio_set_drvdata(
993 MTK_WCN_HIF_SDIO_CLTCTX ctx,
997 UINT8 probed_idx = CLTCTX_IDX(ctx);
999 if (unlikely(!CLTCTX_IDX_VALID(probed_idx))) { /* invalid index in CLTCTX */
1000 HIF_SDIO_WARN_FUNC("invalid idx in ctx(0x%x), private_data_p not stored!\n", ctx);
1003 /* store client driver's private data to dev driver */
1004 g_hif_sdio_probed_func_list[probed_idx].private_data_p = private_data_p;
1005 HIF_SDIO_DBG_FUNC("private_data_p(0x%p) for ctx(0x%x) probed idx(%d) stored!\n",
1006 private_data_p, ctx, probed_idx);
1011 * \brief get client driver's private data function.
1014 * \param clent's MTK_WCN_HIF_SDIO_CLTCTX.
1016 * \retval private data pointer.
1018 void* mtk_wcn_hif_sdio_get_drvdata(
1019 MTK_WCN_HIF_SDIO_CLTCTX ctx
1022 UINT8 probed_idx = CLTCTX_IDX(ctx);
1024 /* get client driver's private data to dev driver */
1025 if (likely(CLTCTX_IDX_VALID(probed_idx)))
1027 return g_hif_sdio_probed_func_list[probed_idx].private_data_p;
1031 /* invalid index in CLTCTX */
1032 HIF_SDIO_WARN_FUNC("invalid idx in ctx(0x%x), return null!\n", ctx);
1038 * \brief control stp/wifi on/off from wmt.
1041 * \param (1)control function type, (2)on/off control.
1043 * \retval (1)control results ,(2)unknow type: -5.
1044 * \retval 0:success, -11:not probed, -12:already on, -13:not registered, other errors.
1047 mtk_wcn_hif_sdio_wmt_control (
1048 WMT_SDIO_FUNC_TYPE func_type,
1052 // TODO:[FixMe][George]: return value of this function shall distinguish
1053 // 1) not probed by mmc_core yet or
1054 // 2) probed by mmc_core but init fail...
1055 switch (func_type) {
1056 case WMT_SDIO_FUNC_STP:
1057 if (is_on == MTK_WCN_BOOL_TRUE) {
1058 return hif_sdio_stp_on();
1061 return hif_sdio_stp_off();
1065 case WMT_SDIO_FUNC_WIFI:
1066 if (is_on == MTK_WCN_BOOL_TRUE) {
1067 return hif_sdio_wifi_on();
1070 return hif_sdio_wifi_off();
1075 HIF_SDIO_WARN_FUNC("unknown type(%d)\n", func_type);
1076 return HIF_SDIO_ERR_INVALID_PARAM;
1085 * \param ctx a context provided by client driver
1086 * \param struct device ** ???
1090 void mtk_wcn_hif_sdio_get_dev(
1091 MTK_WCN_HIF_SDIO_CLTCTX ctx,
1096 struct sdio_func* func;
1098 UINT8 probe_index = CLTCTX_IDX(ctx);
1102 *dev = NULL; //ensure we does not return any invalid value back.
1103 func = hif_sdio_ctx_to_func(ctx);
1104 if (unlikely(!func)) {
1105 HIF_SDIO_WARN_FUNC("no valid *func with ctx(0x%x)\n", ctx);
1109 *dev = &(func->dev);
1110 HIF_SDIO_DBG_FUNC("return *dev(0x%p) for ctx(0x%x)\n", *dev, ctx);
1113 if (probe_index < 0) {
1114 HIF_SDIO_WARN_FUNC("func not probed, probe_index = %d", probe_index);
1118 *dev = &g_hif_sdio_probed_func_list[probe_index].func->dev;
1124 * \brief client's probe() function.
1127 * \param work queue structure.
1131 static int hif_sdio_clt_probe_func (
1132 MTK_WCN_HIF_SDIO_REGISTINFO *registinfo_p,
1137 UINT16 func_num = 0;
1141 HIF_SDIO_DBG_FUNC("start!\n");
1142 HIF_SDIO_ASSERT( registinfo_p );
1143 if (!registinfo_p) {
1144 HIF_SDIO_WARN_FUNC("registinfo_p NULL!!!\n");
1148 /* special case handling: if the clt's unregister is called during probe procedures */
1149 if ( !registinfo_p->func_info || !registinfo_p->sdio_cltinfo) {
1150 HIF_SDIO_WARN_FUNC("client's registinfo_p is cleared !!!\n");
1154 card_id = registinfo_p->func_info->card_id;
1155 func_num = registinfo_p->func_info->func_num;
1156 blk_sz = registinfo_p->func_info->blk_sz;
1157 ret = registinfo_p->sdio_cltinfo->hif_clt_probe( CLTCTX(card_id, func_num, blk_sz, probe_idx),\
1158 registinfo_p->func_info );
1160 HIF_SDIO_INFO_FUNC("clt_probe_func card_id(%x) func_num(%x) blk_sz(%d) prob_idx(%x) ret(%d) %s\n",
1161 card_id, func_num, blk_sz, probe_idx, ret, (ret) ? "fail" : "ok");
1167 * \brief client's probe() worker.
1170 * \param work queue structure.
1174 static void hif_sdio_clt_probe_worker(
1175 struct work_struct *work
1178 MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_worker_info_p = 0;
1180 UINT16 func_num = 0;
1184 HIF_SDIO_DBG_FUNC("start!\n");
1186 HIF_SDIO_ASSERT( work );
1188 /* get client's information */
1189 clt_worker_info_p = container_of( work, MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO, probe_work );
1190 HIF_SDIO_ASSERT( clt_worker_info_p );
1191 HIF_SDIO_ASSERT( clt_worker_info_p->registinfo_p );
1193 /* special case handling: if the clt's unregister is called during probe procedures */
1194 if ( (clt_worker_info_p->registinfo_p->func_info == 0) || (clt_worker_info_p->registinfo_p->sdio_cltinfo==0) )
1196 HIF_SDIO_WARN_FUNC("client's registinfo_p is cleared !!!\n");
1197 vfree( clt_worker_info_p );
1201 card_id = clt_worker_info_p->registinfo_p->func_info->card_id;
1202 func_num = clt_worker_info_p->registinfo_p->func_info->func_num;
1203 blk_sz = clt_worker_info_p->registinfo_p->func_info->blk_sz;
1204 prob_idx = clt_worker_info_p->probe_idx;
1206 /* Execute client's probe() func */
1207 clt_worker_info_p->registinfo_p->sdio_cltinfo->hif_clt_probe( CLTCTX(card_id, func_num, blk_sz, prob_idx),\
1208 clt_worker_info_p->registinfo_p->func_info );
1210 vfree( clt_worker_info_p );
1212 HIF_SDIO_DBG_FUNC("card_id(0x%x) func_num(0x%x) blk_sz(0x%x) prob_idx(0x%x)\n", card_id, func_num, blk_sz, prob_idx);
1213 HIF_SDIO_DBG_FUNC("end!\n");
1217 * \brief client's probe() worker.
1220 * \param work queue structure.
1225 hif_sdio_dump_probe_list (void)
1229 HIF_SDIO_DBG_FUNC("== DUMP probed list start ==\n");
1231 for (i = 0; i < CFG_CLIENT_COUNT; i++) {
1232 if (g_hif_sdio_probed_func_list[i].func) {
1233 HIF_SDIO_DBG_FUNC("index(%d) func(0x%p) clt_idx(%d)\n",
1234 i, g_hif_sdio_probed_func_list[i].func,
1235 g_hif_sdio_probed_func_list[i].clt_idx);
1237 HIF_SDIO_DBG_FUNC("vendor(0x%x) device(0x%x) num(0x%x) state(%d)\n",
1238 g_hif_sdio_probed_func_list[i].func->vendor,
1239 g_hif_sdio_probed_func_list[i].func->device,
1240 g_hif_sdio_probed_func_list[i].func->num,
1241 g_hif_sdio_probed_func_list[i].on_by_wmt);
1246 HIF_SDIO_DBG_FUNC("== DUMP probed list end ==\n");
1251 * \brief Initialize g_hif_sdio_probed_func_list
1254 * \param index of g_hif_sdio_probed_func_list.
1258 static void hif_sdio_init_probed_list(
1262 if ( (index >= 0) && (index < CFG_CLIENT_COUNT) )
1264 /* probed spin lock */
1265 spin_lock_bh( &g_hif_sdio_lock_info.probed_list_lock );
1266 g_hif_sdio_probed_func_list[index].func = 0;
1267 g_hif_sdio_probed_func_list[index].clt_idx = -1;
1268 g_hif_sdio_probed_func_list[index].private_data_p = 0;
1269 g_hif_sdio_probed_func_list[index].on_by_wmt = MTK_WCN_BOOL_FALSE;
1270 /* probed spin unlock */
1271 spin_unlock_bh( &g_hif_sdio_lock_info.probed_list_lock );
1275 HIF_SDIO_ERR_FUNC("index is out of g_hif_sdio_probed_func_list[] boundary!\n");
1281 * \brief Initialize g_hif_sdio_clt_drv_list
1284 * \param index of g_hif_sdio_clt_drv_list.
1288 static void hif_sdio_init_clt_list(
1292 // client list spin lock
1293 spin_lock_bh( &g_hif_sdio_lock_info.clt_list_lock );
1294 if ( (index >= 0) && (index < CFG_CLIENT_COUNT) )
1296 g_hif_sdio_clt_drv_list[index].sdio_cltinfo = 0;
1297 g_hif_sdio_clt_drv_list[index].func_info = 0;
1301 HIF_SDIO_ERR_FUNC("index is out of g_hif_sdio_clt_drv_list[] boundary!\n");
1303 // client list spin unlock
1304 spin_unlock_bh( &g_hif_sdio_lock_info.clt_list_lock );
1309 * \brief find matched g_hif_sdio_probed_func_list index from sdio function handler
1312 * \param sdio function handler
1314 * \retval -1 index not found
1315 * \retval >= 0 return found index
1317 static int hif_sdio_find_probed_list_index_by_func(
1318 struct sdio_func* func
1323 HIF_SDIO_ASSERT( func );
1325 for( i=0; i<CFG_CLIENT_COUNT; i++ )
1327 if ( g_hif_sdio_probed_func_list[i].func == func )
1337 * \brief find matched g_hif_sdio_probed_func_list from vendor_id, device_id, and function number
1340 * \param vendor id, device id, and function number of the sdio card.
1342 * \retval -1 index not found
1343 * \retval >= 0 return found index
1345 static int hif_sdio_find_probed_list_index_by_id_func(
1352 for (i = 0; i < CFG_CLIENT_COUNT; i++) {
1353 if (g_hif_sdio_probed_func_list[i].func) {
1354 HIF_SDIO_DBG_FUNC("probed entry: vendor(0x%x) device(0x%x) num(0x%x)\n",
1355 g_hif_sdio_probed_func_list[i].func->vendor,
1356 g_hif_sdio_probed_func_list[i].func->device,
1357 g_hif_sdio_probed_func_list[i].func->num);
1360 for (i = 0; i < CFG_CLIENT_COUNT; i++) {
1361 if (!g_hif_sdio_probed_func_list[i].func) {
1364 else if ( (g_hif_sdio_probed_func_list[i].func->vendor == vendor) &&
1365 (g_hif_sdio_probed_func_list[i].func->device == device) &&
1366 (g_hif_sdio_probed_func_list[i].func->num == func_num) )
1372 if (i == CFG_CLIENT_COUNT ) {
1374 printk(KERN_INFO DRV_NAME "Cannot find vendor:0x%x, device:0x%x, func_num:0x%x, i=%d\n",
1375 vendor, device, func_num, i);
1377 /* client func has not been probed */
1384 * \brief find matched g_hif_sdio_clt_drv_list index
1386 * find the matched g_hif_sdio_clt_drv_list index from card_id and function number.
1388 * \param vendor id, device id, and function number of the sdio card
1390 * \retval -1 index not found
1391 * \retval >= 0 return found index
1393 static int hif_sdio_find_clt_list_index (
1401 for( i=0; i<CFG_CLIENT_COUNT; i++ )
1403 if ( g_hif_sdio_clt_drv_list[i].func_info != 0 )
1405 if ( (g_hif_sdio_clt_drv_list[i].func_info->manf_id == vendor ) &&\
1406 (g_hif_sdio_clt_drv_list[i].func_info->card_id == device ) &&\
1407 (g_hif_sdio_clt_drv_list[i].func_info->func_num == func_num ) )
1419 * \brief check if the vendor, device ids are supported in mtk_sdio_id_tbl.
1422 * \param vendor id and device id of the sdio card
1424 * \retval (-HIF_SDIO_ERR_FAIL) vendor, device ids are not suppported
1425 * \retval HIF_SDIO_ERR_SUCCESS vendor, device ids are suppported
1427 static int hif_sdio_check_supported_sdio_id(
1434 for ( i=0; i<CFG_CLIENT_COUNT; i++ )
1436 if ( (mtk_sdio_id_tbl[i].vendor == vendor) && (mtk_sdio_id_tbl[i].device == device) )
1438 return HIF_SDIO_ERR_SUCCESS; /* mtk_sdio_id is supported */
1441 return (-HIF_SDIO_ERR_FAIL); /* mtk_sdio_id is not supported */
1446 * \brief check if the vendor, device ids are duplicated in g_hif_sdio_clt_drv_list.
1449 * \param vendor id, device id, and function number of the sdio card
1451 * \retval (-HIF_SDIO_ERR_DUPLICATED) vendor, device, func_num are duplicated
1452 * \retval HIF_SDIO_ERR_SUCCESS vendor, device, func_num are not duplicated
1454 static int hif_sdio_check_duplicate_sdio_id(
1462 for ( i=0; i<CFG_CLIENT_COUNT; i++ )
1464 if( g_hif_sdio_clt_drv_list[i].func_info != 0 )
1466 if ( ( g_hif_sdio_clt_drv_list[i].func_info->manf_id == vendor ) &&\
1467 ( g_hif_sdio_clt_drv_list[i].func_info->card_id == device ) &&\
1468 ( g_hif_sdio_clt_drv_list[i].func_info->func_num == func_num ) )
1470 return (-HIF_SDIO_ERR_DUPLICATED); /* duplicated */
1474 return HIF_SDIO_ERR_SUCCESS; /* Not duplicated */
1479 * \brief Add the client info into g_hif_sdio_clt_drv_list.
1482 * \param [output] client's index pointer.
1483 * \param MTK_WCN_HIF_SDIO_CLTINFO of client's contex.
1485 * \retval (-HIF_SDIO_ERR_FAIL) Add to clt_list successfully
1486 * \retval HIF_SDIO_ERR_SUCCESS Add to clt_list failed (buffer is full)
1488 static int hif_sdio_add_clt_list(
1490 const MTK_WCN_HIF_SDIO_CLTINFO *pinfo,
1496 HIF_SDIO_ASSERT( clt_index_p );
1497 HIF_SDIO_ASSERT( pinfo );
1499 for( i=0; i<CFG_CLIENT_COUNT; i++ )
1501 // client list spin lock
1502 spin_lock_bh( &g_hif_sdio_lock_info.clt_list_lock );
1503 if( g_hif_sdio_clt_drv_list[i].func_info == 0 )
1505 g_hif_sdio_clt_drv_list[i].func_info = &(pinfo->func_tbl[tbl_index]);
1506 g_hif_sdio_clt_drv_list[i].sdio_cltinfo = pinfo;
1507 // client list spin unlock
1508 spin_unlock_bh( &g_hif_sdio_lock_info.clt_list_lock );
1510 return HIF_SDIO_ERR_SUCCESS; /* Add to client list successfully */
1512 // client list spin unlock
1513 spin_unlock_bh( &g_hif_sdio_lock_info.clt_list_lock );
1515 return (-HIF_SDIO_ERR_FAIL); /* Add to client list failed (buffer is full) */
1518 #if HIF_SDIO_SUPPORT_SUSPEND
1519 static int hif_sdio_suspend (struct device *dev)
1521 struct sdio_func* func;
1529 func = dev_to_sdio_func(dev);
1530 HIF_SDIO_DBG_FUNC("prepare for func(0x%p)\n", func);
1532 flag = sdio_get_host_pm_caps(func);
1533 if (!(flag & MMC_PM_KEEP_POWER) || !(flag & MMC_PM_WAKE_SDIO_IRQ)) {
1534 HIF_SDIO_WARN_FUNC("neither MMC_PM_KEEP_POWER nor MMC_PM_WAKE_SDIO_IRQ is supported by host, return -ENOTSUPP\n");
1539 flag = MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ;
1540 ret = sdio_set_host_pm_flags(func, flag);
1542 HIF_SDIO_INFO_FUNC("set MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ to host fail(%d)\n", ret);
1545 sdio_claim_host(func);
1546 HIF_SDIO_INFO_FUNC("set MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ ok\n");
1550 static int hif_sdio_resume (struct device *dev)
1552 struct sdio_func* func;
1555 HIF_SDIO_WARN_FUNC("null dev!\n");
1558 func = dev_to_sdio_func(dev);
1559 sdio_release_host(func);
1560 HIF_SDIO_DBG_FUNC("do nothing for func(0x%p)\n", func);
1567 * \brief hif_sdio probe function
1569 * hif_sdio probe function called by mmc driver when any matched SDIO function
1570 * is detected by it.
1575 * \retval 0 register successfully
1576 * \retval < 0 list error code here
1578 static int hif_sdio_probe (
1579 struct sdio_func *func,
1580 const struct sdio_device_id *id
1585 MTK_WCN_HIF_SDIO_PROBEINFO* hif_sdio_probed_funcp = 0;
1586 INT32 probe_index = -1;
1588 INT32 clt_index = -1;
1589 MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_probe_worker_info = 0;
1592 HIF_SDIO_INFO_FUNC("start!\n");
1593 HIF_SDIO_ASSERT( func );
1594 hif_sdio_match_chipid_by_dev_id(id);
1595 //4 <0> display debug information
1596 HIF_SDIO_INFO_FUNC("vendor(0x%x) device(0x%x) num(0x%x)\n", func->vendor, func->device, func->num);
1597 for (i = 0;i < func->card->num_info;i++) {
1598 HIF_SDIO_INFO_FUNC("card->info[%d]: %s\n", i, func->card->info[i]);
1601 //4 <1> Check if this is supported by us (mtk_sdio_id_tbl)
1602 ret = hif_sdio_check_supported_sdio_id( func->vendor, func->device );
1604 HIF_SDIO_WARN_FUNC("vendor id and device id of sdio_func are not supported in mtk_sdio_id_tbl!\n");
1608 //4 <2> Add this struct sdio_func *func to g_hif_sdio_probed_func_list
1609 for( i=0; i<CFG_CLIENT_COUNT; i++ )
1611 /* probed spin lock */
1612 spin_lock_bh( &g_hif_sdio_lock_info.probed_list_lock );
1613 if ( g_hif_sdio_probed_func_list[i].func == 0 )
1615 hif_sdio_probed_funcp = &g_hif_sdio_probed_func_list[i];
1616 hif_sdio_probed_funcp->func = func;
1617 hif_sdio_probed_funcp->clt_idx = hif_sdio_find_clt_list_index(func->vendor, func->device, func->num);
1618 hif_sdio_probed_funcp->on_by_wmt = MTK_WCN_BOOL_FALSE;
1619 hif_sdio_probed_funcp->sdio_irq_enabled = MTK_WCN_BOOL_FALSE;
1620 /* probed spin unlock */
1621 spin_unlock_bh( &g_hif_sdio_lock_info.probed_list_lock );
1627 /* probed spin unlock */
1628 spin_unlock_bh( &g_hif_sdio_lock_info.probed_list_lock );
1631 if ( (probe_index < 0) || (probe_index >= CFG_CLIENT_COUNT) )
1633 HIF_SDIO_ERR_FUNC("probe function list if full!\n");
1637 //4 <3> Initialize this function
1638 if ( g_hif_sdio_probed_func_list[probe_index].clt_idx < 0 )
1640 for( i=0; i<CFG_CLIENT_COUNT; i++ )
1642 // client list spin lock
1643 spin_lock_bh( &g_hif_sdio_lock_info.clt_list_lock );
1644 if ( g_hif_sdio_clt_drv_list[i].func_info == 0 )
1646 // client list spin unlock
1647 spin_unlock_bh( &g_hif_sdio_lock_info.clt_list_lock );
1650 HIF_SDIO_INFO_FUNC("manf_id:%x, card_id:%x, func_num:%d\n", g_hif_sdio_clt_drv_list[i].func_info->manf_id, g_hif_sdio_clt_drv_list[i].func_info->card_id, g_hif_sdio_clt_drv_list[i].func_info->func_num );
1651 if ( (g_hif_sdio_clt_drv_list[i].func_info->manf_id == g_hif_sdio_probed_func_list[probe_index].func->vendor)&&\
1652 (g_hif_sdio_clt_drv_list[i].func_info->card_id == g_hif_sdio_probed_func_list[probe_index].func->device)&&\
1653 (g_hif_sdio_clt_drv_list[i].func_info->func_num == g_hif_sdio_probed_func_list[probe_index].func->num) )
1655 g_hif_sdio_probed_func_list[probe_index].clt_idx = i;
1656 // client list spin unlock
1657 spin_unlock_bh( &g_hif_sdio_lock_info.clt_list_lock );
1662 // client list spin unlock
1663 spin_unlock_bh( &g_hif_sdio_lock_info.clt_list_lock );
1666 HIF_SDIO_INFO_FUNC("map to g_hif_sdio_clt_drv_list[] done: %d\n", g_hif_sdio_probed_func_list[probe_index].clt_idx );
1669 //4 <3.1> enable this function
1670 sdio_claim_host(func);
1671 ret = sdio_enable_func(func);
1672 sdio_release_host(func);
1674 HIF_SDIO_ERR_FUNC("sdio_enable_func failed!\n");
1678 //4 <3.2> set block size according to the table storing function characteristics
1679 if ( hif_sdio_probed_funcp == 0 )
1681 HIF_SDIO_ERR_FUNC("hif_sdio_probed_funcp is null!\n");
1684 if ( hif_sdio_probed_funcp->clt_idx >= 0 ) /* The clt contex has been registed */
1686 sdio_claim_host(func);
1687 ret = sdio_set_block_size(func, g_hif_sdio_clt_drv_list[hif_sdio_probed_funcp->clt_idx].func_info->blk_sz);
1688 sdio_release_host(func);
1690 else /* The clt contex has not been registed */
1692 sdio_claim_host(func);
1693 ret = sdio_set_block_size(func, HIF_DEFAULT_BLK_SIZE);
1694 sdio_release_host(func);
1697 HIF_SDIO_ERR_FUNC("set sdio block size failed!\n");
1701 HIF_SDIO_INFO_FUNC("cur_blksize(%d) max(%d), host max blk_size(%d) blk_count(%d)\n",
1702 func->cur_blksize, func->max_blksize,
1703 func->card->host->max_blk_size, func->card->host->max_blk_count
1706 // TODO:[ChangeFeature][George]: explain why this block is marked
1708 //4 <3.3> claim irq for this function
1709 sdio_claim_host(func);
1710 ret = sdio_claim_irq(func, hif_sdio_irq);
1711 sdio_release_host(func);
1712 printk(KERN_INFO "sdio_claim_irq ret=%d\n", ret);
1714 //4 <3.4> If this struct sdio_func *func is supported by any driver in
1715 //4 g_hif_sdio_clt_drv_list, schedule another task to call client's .hif_clt_probe()
1716 if ( (clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx) >= 0 ) /* the function has been registered */
1718 /* use worker thread to perform the client's .hif_clt_probe() */
1719 clt_probe_worker_info = vmalloc( sizeof(MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO) );
1720 INIT_WORK( &clt_probe_worker_info->probe_work, hif_sdio_clt_probe_worker );
1721 clt_probe_worker_info->registinfo_p = &g_hif_sdio_clt_drv_list[clt_index];
1722 clt_probe_worker_info->probe_idx = probe_index;
1723 schedule_work( &clt_probe_worker_info->probe_work );
1727 hif_sdio_dump_probe_list();
1730 //4 <last> error handling
1736 * \brief hif_sdio remove function
1738 * hif_sdio probe function called by mmc driver when the probed func should be
1744 static void hif_sdio_remove (
1745 struct sdio_func *func
1748 int probed_list_index = 0;
1750 int registed_list_index = 0;
1753 HIF_SDIO_INFO_FUNC("start!\n");
1754 HIF_SDIO_ASSERT( func );
1756 //4 <1> check input parameter is valid and has been probed previously
1758 HIF_SDIO_ERR_FUNC("func null(%p)\n", func);
1762 //4 <2> if this function has been initialized by any client driver,
1763 //4 call client's .hif_clt_remove() call back in THIS context.
1764 probed_list_index = hif_sdio_find_probed_list_index_by_func( func );
1765 if ( probed_list_index < 0 )
1767 HIF_SDIO_WARN_FUNC("sdio function pointer is not in g_hif_sdio_probed_func_list!\n");
1771 registed_list_index = g_hif_sdio_probed_func_list[probed_list_index].clt_idx;
1772 if ( registed_list_index >= 0 )
1774 g_hif_sdio_clt_drv_list[registed_list_index].sdio_cltinfo->hif_clt_remove( CLTCTX(func->device, func->num,\
1775 func->cur_blksize, probed_list_index) );
1779 //4 <3> mark this function as de-initialized and invalidate client's context
1780 hif_sdio_init_probed_list(probed_list_index);
1783 //4 <4> release irq for this function
1784 sdio_claim_host(func);
1785 sdio_release_irq(func);
1786 sdio_release_host(func);
1789 //4 <5> disable this function
1790 sdio_claim_host(func);
1791 sdio_disable_func(func);
1792 sdio_release_host(func);
1794 //4 <6> mark this function as removed
1796 HIF_SDIO_INFO_FUNC("sdio func(0x%p) is removed successfully!\n", func);
1800 * \brief hif_sdio interrupt handler
1802 * detailed descriptions
1804 * \param ctx client's context variable
1807 static void hif_sdio_irq (
1808 struct sdio_func *func
1811 int probed_list_index = -1;
1812 int registed_list_index = -1;
1814 HIF_SDIO_DBG_FUNC("start!\n");
1816 //4 <1> check if func is valid
1817 HIF_SDIO_ASSERT( func );
1819 //4 <2> if func has valid corresponding hif_sdio client's context, mark it
1820 //4 host-locked, use it to call client's .hif_clt_irq() callback function in
1822 probed_list_index = hif_sdio_find_probed_list_index_by_func( func );
1823 if ( (probed_list_index < 0) || (probed_list_index >= CFG_CLIENT_COUNT) )
1825 HIF_SDIO_ERR_FUNC("probed_list_index not found!\n");
1828 /* [George] added for sdio irq sync and mmc single_irq workaround. It's set
1829 * enabled later by client driver call mtk_wcn_hif_sdio_enable_irq()
1831 /* skip smp_rmb() here */
1832 if (MTK_WCN_BOOL_FALSE == g_hif_sdio_probed_func_list[probed_list_index].sdio_irq_enabled) {
1833 HIF_SDIO_WARN_FUNC("func(0x%p),probed_idx(%d) sdio irq not enabled yet\n",
1834 func, probed_list_index);
1838 registed_list_index = g_hif_sdio_probed_func_list[probed_list_index].clt_idx;
1839 // g_hif_sdio_probed_func_list[probed_list_index].interrupted = MTK_WCN_BOOL_TRUE;
1840 if ( (registed_list_index >= 0)
1841 && (registed_list_index < CFG_CLIENT_COUNT) ) {
1842 g_hif_sdio_clt_drv_list[registed_list_index].sdio_cltinfo->hif_clt_irq( CLTCTX(func->device,\
1843 func->num, func->cur_blksize, probed_list_index) );
1846 //4 <3> if func has no VALID hif_sdio client's context, release irq for this
1847 //4 func and mark it in g_hif_sdio_probed_func_list (remember: donnot claim host in irq contex).
1848 HIF_SDIO_WARN_FUNC("release irq (func:0x%p) v(0x%x) d(0x%x) n(0x%x)\n",
1849 func, func->vendor, func->device, func->num);
1850 mtk_wcn_sdio_irq_flag_set (0);
1851 sdio_release_irq(func);
1858 * \brief hif_sdio init function
1860 * detailed descriptions
1864 static int __init hif_sdio_init(void)
1869 HIF_SDIO_INFO_FUNC("start!\n");
1871 //4 <1> init all private variables
1872 /* init reference count to 0 */
1875 /* init spin lock information */
1876 spin_lock_init( &g_hif_sdio_lock_info.probed_list_lock );
1877 spin_lock_init( &g_hif_sdio_lock_info.clt_list_lock );
1879 /* init probed function list and g_hif_sdio_clt_drv_list */
1880 for ( i=0; i<CFG_CLIENT_COUNT; i++ )
1882 hif_sdio_init_probed_list(i);
1883 hif_sdio_init_clt_list(i);
1886 //4 <2> register to mmc driver
1887 ret = sdio_register_driver(&mtk_sdio_client_drv);
1888 HIF_SDIO_INFO_FUNC("sdio_register_driver() ret=%d\n", ret);
1890 //4 <3> create thread for query chip id and device node for launcher to access
1891 if (0 == hifsdiod_start())
1893 hif_sdio_create_dev_node();
1895 HIF_SDIO_DBG_FUNC("end!\n");
1900 * \brief hif_sdio init function
1902 * detailed descriptions
1906 static VOID __exit hif_sdio_exit(void)
1908 HIF_SDIO_INFO_FUNC("start!\n");
1910 hif_sdio_remove_dev_node();
1913 //4 <0> if client driver is not removed yet, we shall NOT be called...
1915 //4 <1> check reference count
1916 if ( gRefCount !=0 )
1918 HIF_SDIO_WARN_FUNC("gRefCount=%d !!!\n", gRefCount);
1921 //4 <2> check if there is any hif_sdio-registered clients. There should be
1922 //4 no registered client...
1924 //4 <3> Reregister with mmc driver. Our remove handler hif_sdio_remove()
1925 //4 will be called later by mmc_core. Clean up driver resources there.
1926 sdio_unregister_driver(&mtk_sdio_client_drv);
1928 HIF_SDIO_DBG_FUNC("end!\n");
1930 } /* end of exitWlan() */
1933 * \brief stp on by wmt (probe client driver).
1938 * \retval 0:success, -11:not probed, -12:already on, -13:not registered, other errors.
1940 INT32 hif_sdio_stp_on(
1945 MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_probe_worker_info = 0;
1947 INT32 clt_index = -1;
1948 INT32 probe_index = -1;
1949 struct sdio_func *func = 0;
1953 HIF_SDIO_INFO_FUNC("start!\n");
1955 //4 <1> If stp client drv has not been probed, return error code
1957 if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020B, 1)) >= 0 )
1961 if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020C, 1)) >= 0 )
1967 if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6628, 2)) >= 0 )
1972 if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6619, 1)) >= 0 )
1978 if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018B, 1)) >= 0 )
1982 if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018C, 1)) >= 0 )
1988 //4 <2> If stp client drv has not been probed, return error code
1989 /* client func has not been probed */
1990 HIF_SDIO_INFO_FUNC("no supported func probed \n");
1991 return HIF_SDIO_ERR_NOT_PROBED;
1995 //4 <3> If stp client drv has been on by wmt, return error code
1996 if (MTK_WCN_BOOL_FALSE != g_hif_sdio_probed_func_list[probe_index].on_by_wmt) {
1997 HIF_SDIO_INFO_FUNC("already on...\n");
1998 return HIF_SDIO_ERR_ALRDY_ON;
2001 g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_TRUE;
2004 if ( (clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx) >= 0 ) /* the function has been registered */
2006 g_hif_sdio_probed_func_list[probe_index].sdio_irq_enabled = MTK_WCN_BOOL_FALSE;
2007 //4 <4> claim irq for this function
2008 func = g_hif_sdio_probed_func_list[probe_index].func;
2009 sdio_claim_host(func);
2010 ret = sdio_claim_irq(func, hif_sdio_irq);
2011 mtk_wcn_sdio_irq_flag_set (1);
2012 sdio_release_host(func);
2014 HIF_SDIO_WARN_FUNC("sdio_claim_irq() for stp fail(%d)\n", ret);
2017 HIF_SDIO_INFO_FUNC("sdio_claim_irq() for stp ok\n");
2019 //4 <5> If this struct sdio_func *func is supported by any driver in
2020 //4 g_hif_sdio_clt_drv_list, schedule another task to call client's .hif_clt_probe()
2021 // TODO: [FixMe][George] WHY probe worker is removed???
2023 /* Call client's .hif_clt_probe() */
2024 ret = hif_sdio_clt_probe_func(&g_hif_sdio_clt_drv_list[clt_index], probe_index);
2026 HIF_SDIO_WARN_FUNC("clt_probe_func() for stp fail(%d) release irq\n", ret);
2027 sdio_claim_host(func);
2028 mtk_wcn_sdio_irq_flag_set (0);
2029 ret2 = sdio_release_irq(func);
2030 sdio_release_host(func);
2032 HIF_SDIO_WARN_FUNC("sdio_release_irq() for stp fail(%d)\n", ret2);
2035 g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_FALSE;
2038 HIF_SDIO_INFO_FUNC("ok!\n");
2042 /* use worker thread to perform the client's .hif_clt_probe() */
2043 clt_probe_worker_info = vmalloc( sizeof(MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO) );
2044 INIT_WORK( &clt_probe_worker_info->probe_work, hif_sdio_clt_probe_worker );
2045 clt_probe_worker_info->registinfo_p = &g_hif_sdio_clt_drv_list[clt_index];
2046 clt_probe_worker_info->probe_idx = probe_index;
2047 schedule_work( &clt_probe_worker_info->probe_work );
2051 // TODO: [FixMe][George] check if clt_index is cleared in client's unregister function
2052 HIF_SDIO_WARN_FUNC("probed but not registered yet (%d)\n", ret);
2053 return HIF_SDIO_ERR_CLT_NOT_REG;
2058 * \brief stp off by wmt (remove client driver).
2063 * \retval 0:success, -11:not probed, -12:already off, -13:not registered, other errors.
2065 INT32 hif_sdio_stp_off(
2069 INT32 clt_index = -1;
2070 INT32 probe_index = -1;
2071 struct sdio_func *func = 0;
2075 HIF_SDIO_INFO_FUNC("start!\n");
2077 //4 <1> If stp client drv has not been probed, return error code
2079 if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020B, 1)) >= 0 )
2083 if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020C, 1)) >= 0 )
2089 if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6628, 2)) >= 0 )
2095 if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6619, 1)) >= 0 )
2101 if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018B, 1)) >= 0 )
2105 if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018C, 1)) >= 0 )
2111 //4 <2> If stp client drv has not been probed, return error code
2112 /* client func has not been probed */
2113 return HIF_SDIO_ERR_NOT_PROBED;
2117 //4 <3> If stp client drv has been off by wmt, return error code
2118 if (MTK_WCN_BOOL_FALSE == g_hif_sdio_probed_func_list[probe_index].on_by_wmt) {
2119 HIF_SDIO_WARN_FUNC("already off...\n");
2120 return HIF_SDIO_ERR_ALRDY_OFF;
2123 g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_FALSE;
2126 #if 0 // TODO: [FixMe][George] moved below as done in stp_on.
2127 //4 <4> release irq for this function
2128 func = g_hif_sdio_probed_func_list[probe_index].func;
2129 sdio_claim_host(func);
2130 ret = sdio_release_irq(func);
2131 sdio_release_host(func);
2133 printk(KERN_WARNING DRV_NAME "sdio_release_irq for stp fail(%d)\n", ret);
2136 printk(KERN_INFO DRV_NAME "sdio_release_irq for stp ok\n");
2140 if ( (clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx) >= 0 ) /* the function has been registered */
2142 func = g_hif_sdio_probed_func_list[probe_index].func;
2144 //4 <4> Callback to client driver's remove() func
2145 ret = g_hif_sdio_clt_drv_list[clt_index].sdio_cltinfo->hif_clt_remove(
2146 CLTCTX(func->device, func->num, func->cur_blksize, probe_index) );
2148 HIF_SDIO_WARN_FUNC("clt_remove for stp fail(%d)\n", ret);
2151 HIF_SDIO_INFO_FUNC("ok!\n");
2154 //4 <5> release irq for this function
2155 sdio_claim_host(func);
2156 mtk_wcn_sdio_irq_flag_set (0);
2157 ret2 = sdio_release_irq(func);
2158 sdio_release_host(func);
2160 g_hif_sdio_probed_func_list[probe_index].sdio_irq_enabled = MTK_WCN_BOOL_FALSE;
2162 HIF_SDIO_WARN_FUNC("sdio_release_irq() for stp fail(%d)\n", ret2);
2165 HIF_SDIO_INFO_FUNC("sdio_release_irq() for stp ok\n");
2168 return (ret + ret2);
2171 // TODO: [FixMe][George] check if clt_index is cleared in client's unregister function
2172 HIF_SDIO_WARN_FUNC("probed but not registered yet (%d)\n", ret);
2173 return HIF_SDIO_ERR_CLT_NOT_REG;
2178 * \brief wifi on by wmt (probe client driver).
2183 * \retval 0:success, -11:not probed, -12:already on, -13:not registered, other errors.
2186 hif_sdio_wifi_on (void)
2189 MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_probe_worker_info = 0;
2191 INT32 clt_index = -1;
2192 INT32 probe_index = -1;
2193 struct sdio_func *func = 0;
2197 HIF_SDIO_INFO_FUNC("start!\n");
2199 //4 <1> If wifi client drv has not been probed, return error code
2201 if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020A, 1)) >= 0 )
2205 if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020C, 2)) >= 0 )
2210 if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6628, 1)) >= 0 )
2215 if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018A, 1)) >= 0 )
2219 if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018C, 2)) >= 0 )
2225 //4 <2> If wifi client drv has not been probed, return error code
2226 /* client func has not been probed */
2227 return HIF_SDIO_ERR_NOT_PROBED;
2231 //4 <3> If wifi client drv has been on by wmt, return error code
2232 if (g_hif_sdio_probed_func_list[probe_index].on_by_wmt) {
2233 HIF_SDIO_INFO_FUNC("probe_index (%d), already on...\n", probe_index);
2234 return HIF_SDIO_ERR_ALRDY_ON;
2237 if ( (clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx) >= 0 ) /* the function has been registered */
2239 g_hif_sdio_probed_func_list[probe_index].sdio_irq_enabled = MTK_WCN_BOOL_FALSE;
2240 //4 <4> claim irq for this function
2241 func = g_hif_sdio_probed_func_list[probe_index].func;
2242 sdio_claim_host(func);
2243 ret = sdio_claim_irq(func, hif_sdio_irq);
2244 mtk_wcn_sdio_irq_flag_set (1);
2245 sdio_release_host(func);
2247 HIF_SDIO_WARN_FUNC("sdio_claim_irq() for wifi fail(%d)\n", ret);
2250 HIF_SDIO_INFO_FUNC("sdio_claim_irq() for wifi ok\n");
2252 //4 <5> If this struct sdio_func *func is supported by any driver in
2253 //4 g_hif_sdio_clt_drv_list, schedule another task to call client's .hif_clt_probe()
2254 // TODO: [FixMe][George] WHY probe worker is removed???
2256 /* Call client's .hif_clt_probe() */
2257 ret = hif_sdio_clt_probe_func(&g_hif_sdio_clt_drv_list[clt_index], probe_index);
2259 HIF_SDIO_WARN_FUNC("clt_probe_func() for wifi fail(%d) release irq\n", ret);
2260 sdio_claim_host(func);
2261 mtk_wcn_sdio_irq_flag_set (0);
2262 ret2 = sdio_release_irq(func);
2263 sdio_release_host(func);
2265 HIF_SDIO_WARN_FUNC("sdio_release_irq() for wifi fail(%d)\n", ret2);
2268 g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_FALSE;
2273 g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_TRUE;
2275 HIF_SDIO_INFO_FUNC("ok!\n");
2278 /* use worker thread to perform the client's .hif_clt_probe() */
2279 clt_probe_worker_info = vmalloc( sizeof(MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO) );
2280 INIT_WORK( &clt_probe_worker_info->probe_work, hif_sdio_clt_probe_worker );
2281 clt_probe_worker_info->registinfo_p = &g_hif_sdio_clt_drv_list[clt_index];
2282 clt_probe_worker_info->probe_idx = probe_index;
2283 schedule_work( &clt_probe_worker_info->probe_work );
2287 // TODO: [FixMe][George] check if clt_index is cleared in client's unregister function
2288 HIF_SDIO_WARN_FUNC("probed but not registered yet (%d)\n", ret);
2289 return HIF_SDIO_ERR_CLT_NOT_REG;
2294 * \brief wifi off by wmt (remove client driver).
2299 * \retval 0:success, -11:not probed, -12:already off, -13:not registered, other errors.
2301 INT32 hif_sdio_wifi_off(
2305 INT32 clt_index = -1;
2306 INT32 probe_index = -1;
2307 struct sdio_func *func = 0;
2311 HIF_SDIO_INFO_FUNC("start!\n");
2313 //4 <1> If wifi client drv has not been probed, return error code
2315 if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020A, 1)) >= 0 )
2317 goto wifi_off_exist;
2319 if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020C, 2)) >= 0 )
2321 goto wifi_off_exist;
2325 if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6628, 1)) >= 0 )
2327 goto wifi_off_exist;
2331 if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018A, 1)) >= 0 )
2333 goto wifi_off_exist;
2335 if ( (probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018C, 2)) >= 0 )
2337 goto wifi_off_exist;
2341 //4 <2> If wifi client drv has not been probed, return error code
2342 /* client func has not been probed */
2343 return HIF_SDIO_ERR_NOT_PROBED;
2347 //4 <3> If wifi client drv has been off by wmt, return error code
2348 if (MTK_WCN_BOOL_FALSE == g_hif_sdio_probed_func_list[probe_index].on_by_wmt) {
2349 HIF_SDIO_WARN_FUNC("already off...\n");
2350 return HIF_SDIO_ERR_ALRDY_OFF;
2353 g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_FALSE;
2356 #if 0 // TODO: [FixMe][George] moved below as done in wifi_on.
2357 //4 <4> release irq for this function
2358 func = g_hif_sdio_probed_func_list[probe_index].func;
2359 sdio_claim_host(func);
2360 ret = sdio_release_irq(func);
2361 sdio_release_host(func);
2363 printk(KERN_WARNING DRV_NAME "sdio_release_irq for wifi fail(%d)\n", ret);
2366 printk(KERN_INFO DRV_NAME "sdio_release_irq for wifi ok\n");
2370 if ( (clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx) >= 0 ) /* the function has been registered */
2372 func = g_hif_sdio_probed_func_list[probe_index].func;
2374 //4 <4> Callback to client driver's remove() func
2375 ret = g_hif_sdio_clt_drv_list[clt_index].sdio_cltinfo->hif_clt_remove(
2376 CLTCTX(func->device, func->num, func->cur_blksize, probe_index) );
2378 HIF_SDIO_WARN_FUNC("clt_remove for wifi fail(%d)\n", ret);
2381 HIF_SDIO_INFO_FUNC("ok!\n");
2384 //4 <5> release irq for this function
2385 sdio_claim_host(func);
2386 mtk_wcn_sdio_irq_flag_set (0);
2387 ret2 = sdio_release_irq(func);
2388 sdio_release_host(func);
2389 g_hif_sdio_probed_func_list[probe_index].sdio_irq_enabled = MTK_WCN_BOOL_FALSE;
2391 HIF_SDIO_WARN_FUNC("sdio_release_irq() for wifi fail(%d)\n", ret2);
2394 HIF_SDIO_INFO_FUNC("sdio_release_irq() for wifi ok\n");
2396 return (ret + ret2);
2399 // TODO: [FixMe][George] check if clt_index is cleared in client's unregister function
2400 HIF_SDIO_WARN_FUNC("probed but not registered yet (%d)\n", ret);
2401 return HIF_SDIO_ERR_CLT_NOT_REG;
2406 * \brief set mmc power up/off
2408 * detailed descriptions
2410 * \param: 1. ctx client's context variable, 2.power state: 1:power up, other:power off
2412 * \retval 0:success, -1:fail
2414 INT32 mtk_wcn_hif_sdio_bus_set_power (
2415 MTK_WCN_HIF_SDIO_CLTCTX ctx,
2419 int probe_index = -1;
2420 struct sdio_func *func = 0;
2422 HIF_SDIO_INFO_FUNC("turn Bus Power to: %d\n", pwrState);
2424 probe_index = CLTCTX_IDX(ctx);
2425 func = g_hif_sdio_probed_func_list[probe_index].func;
2429 HIF_SDIO_WARN_FUNC("Cannot find sdio_func !!!\n");
2433 if ( 1 == pwrState )
2435 sdio_claim_host( func );
2436 mmc_power_up_ext( func->card->host );
2437 sdio_release_host( func );
2438 HIF_SDIO_WARN_FUNC("SDIO BUS Power UP\n");
2442 sdio_claim_host( func );
2443 mmc_power_off_ext( func->card->host );
2444 sdio_release_host( func );
2445 HIF_SDIO_WARN_FUNC("SDIO BUS Power OFF\n");
2451 void mtk_wcn_hif_sdio_enable_irq(
2452 MTK_WCN_HIF_SDIO_CLTCTX ctx,
2456 UINT8 probed_idx = CLTCTX_IDX(ctx);
2458 if (unlikely(!CLTCTX_IDX_VALID(probed_idx))) { /* invalid index in CLTCTX */
2459 HIF_SDIO_WARN_FUNC("invalid idx in ctx(0x%x), sdio_irq no change\n", ctx);
2463 /* store client driver's private data to dev driver */
2464 g_hif_sdio_probed_func_list[probed_idx].sdio_irq_enabled = enable;
2466 HIF_SDIO_INFO_FUNC("ctx(0x%x) sdio irq enable(%d)\n",
2467 ctx, (MTK_WCN_BOOL_FALSE == enable) ? 0 : 1);
2472 module_init(hif_sdio_init);
2473 module_exit(hif_sdio_exit);
2475 EXPORT_SYMBOL(mtk_wcn_hif_sdio_update_cb_reg);
2476 EXPORT_SYMBOL(mtk_wcn_hif_sdio_client_reg);
2477 EXPORT_SYMBOL(mtk_wcn_hif_sdio_client_unreg);
2478 EXPORT_SYMBOL(mtk_wcn_hif_sdio_readb);
2479 EXPORT_SYMBOL(mtk_wcn_hif_sdio_writeb);
2480 EXPORT_SYMBOL(mtk_wcn_hif_sdio_readl);
2481 EXPORT_SYMBOL(mtk_wcn_hif_sdio_writel);
2482 EXPORT_SYMBOL(mtk_wcn_hif_sdio_read_buf);
2483 EXPORT_SYMBOL(mtk_wcn_hif_sdio_write_buf);
2484 EXPORT_SYMBOL(mtk_wcn_hif_sdio_set_drvdata);
2485 EXPORT_SYMBOL(mtk_wcn_hif_sdio_get_drvdata);
2486 EXPORT_SYMBOL(mtk_wcn_hif_sdio_wmt_control);
2487 EXPORT_SYMBOL(mtk_wcn_hif_sdio_bus_set_power);
2488 EXPORT_SYMBOL(mtk_wcn_hif_sdio_get_dev);
2489 EXPORT_SYMBOL(mtk_wcn_hif_sdio_enable_irq);