| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785 |
- /*
- *
- * 07 25 2010 george.kuo
- *
- * Move hif_sdio driver to linux directory.
- *
- * 07 23 2010 george.kuo
- *
- * Add MT6620 driver source tree
- * , including char device driver (wmt, bt, gps), stp driver,
- * interface driver (tty ldisc and hif_sdio), and bt hci driver.
- **
- **
- */
- /*******************************************************************************
- * C O M P I L E R F L A G S
- ********************************************************************************
- */
- #define HIF_SDIO_UPDATE (1)
- #define HIF_SDIO_SUPPORT_SUSPEND (1)
- #define HIF_SDIO_SUPPORT_WAKEUP (0)
- /*******************************************************************************
- * E X T E R N A L R E F E R E N C E S
- ********************************************************************************
- */
- #include <linux/proc_fs.h>
- #include "hif_sdio.h"
- #include "hif_sdio_chrdev.h"
- #if MTK_HIF_SDIO_AUTOK_ENABLED
- #include <mt_boot.h>
- #endif
- #define mmc_power_up_ext(x)
- #define mmc_power_off_ext(x)
- /*******************************************************************************
- * C O N S T A N T S
- ********************************************************************************
- */
- /* #define DRV_NAME "[hif_sdio]" */
- /*******************************************************************************
- * D A T A T Y P E S
- ********************************************************************************
- */
- /*******************************************************************************
- * M A C R O S
- ********************************************************************************
- */
- /*******************************************************************************
- * F U N C T I O N D E C L A R A T I O N S
- ********************************************************************************
- */
- #if HIF_SDIO_SUPPORT_SUSPEND
- static INT32 hif_sdio_suspend(struct device *dev);
- static INT32 hif_sdio_resume(struct device *dev);
- #endif
- static INT32 hif_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id);
- static VOID hif_sdio_remove(struct sdio_func *func);
- static VOID hif_sdio_irq(struct sdio_func *func);
- static INT32 hif_sdio_clt_probe_func(MTK_WCN_HIF_SDIO_REGISTINFO *registinfo_p, INT8 probe_idx);
- static VOID hif_sdio_clt_probe_worker(struct work_struct *work);
- static INT32 hif_sdio_find_probed_list_index_by_func(struct sdio_func *func);
- #if 0 /* TODO:[ChangeFeature][George] remove obsolete function? */
- static INT32 hif_sdio_find_probed_list_index_by_clt_index(INT32 clt_index);
- #endif
- static INT32 hif_sdio_find_probed_list_index_by_id_func(UINT16 vendor,
- UINT16 device, UINT16 func_num);
- static VOID hif_sdio_init_clt_list(INT32 index);
- static INT32 hif_sdio_find_clt_list_index(UINT16 vendor, UINT16 device, UINT16 func_num);
- static INT32 hif_sdio_check_supported_sdio_id(UINT16 vendor, UINT16 device);
- static INT32 hif_sdio_check_duplicate_sdio_id(UINT16 vendor, UINT16 device, UINT16 func_num);
- static INT32 hif_sdio_add_clt_list(PINT32 clt_index_p,
- const MTK_WCN_HIF_SDIO_CLTINFO *pinfo, UINT32 tbl_index);
- static INT32 hif_sdio_stp_on(VOID);
- static INT32 hif_sdio_stp_off(VOID);
- static INT32 hif_sdio_wifi_on(VOID);
- static INT32 hif_sdio_wifi_off(VOID);
- static INT32 _hif_sdio_do_autok(struct sdio_func *func);
- #if 0
- static INT32 _hif_sdio_is_autok_support(struct sdio_func *func);
- #endif
- static INT32 _hif_sdio_deep_sleep_info_init(VOID);
- static INT32 _hif_sdio_deep_sleep_info_set_act(UINT32 chipid,
- UINT16 func_num,
- MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT8 act_flag);
- static INT32 _hif_sdio_deep_sleep_ctrl(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT8 en_flag);
- /*******************************************************************************
- * P R I V A T E D A T A
- ********************************************************************************
- */
- /* Supported SDIO device table */
- static const struct sdio_device_id mtk_sdio_id_tbl[] = {
- /* MT6618 *//* Not an SDIO standard class device */
- {SDIO_DEVICE(0x037A, 0x018A)}, /* SDIO1:WIFI */
- {SDIO_DEVICE(0x037A, 0x018B)}, /* SDIO2:FUNC1:BT+FM */
- {SDIO_DEVICE(0x037A, 0x018C)}, /* 2-function (SDIO2:FUNC1:BT+FM, FUNC2:WIFI) */
- /* MT6619 *//* Not an SDIO standard class device */
- {SDIO_DEVICE(0x037A, 0x6619)}, /* SDIO2:FUNC1:BT+FM+GPS */
- /* MT6620 *//* Not an SDIO standard class device */
- {SDIO_DEVICE(0x037A, 0x020A)}, /* SDIO1:FUNC1:WIFI */
- {SDIO_DEVICE(0x037A, 0x020B)}, /* SDIO2:FUNC1:BT+FM+GPS */
- {SDIO_DEVICE(0x037A, 0x020C)}, /* 2-function (SDIO2:FUNC1:BT+FM+GPS, FUNC2:WIFI) */
- /* MT5921 *//* Not an SDIO standard class device */
- {SDIO_DEVICE(0x037A, 0x5921)},
- /* MT6628 *//* SDIO1: Wi-Fi, SDIO2: BGF */
- {SDIO_DEVICE(0x037A, 0x6628)},
- /* MT6630 *//* SDIO1: Wi-Fi, SDIO2: BGF */
- {SDIO_DEVICE(0x037A, 0x6630)},
- { /* end: all zeroes */ },
- };
- #if HIF_SDIO_SUPPORT_SUSPEND
- static const struct dev_pm_ops mtk_sdio_pmops = {
- .suspend = hif_sdio_suspend,
- .resume = hif_sdio_resume,
- };
- #endif
- static struct sdio_driver mtk_sdio_client_drv = {
- .name = "mtk_sdio_client", /* MTK SDIO Client Driver */
- .id_table = mtk_sdio_id_tbl, /* all supported struct sdio_device_id table */
- .probe = hif_sdio_probe,
- .remove = hif_sdio_remove,
- #if HIF_SDIO_SUPPORT_SUSPEND
- .drv = {
- .pm = &mtk_sdio_pmops,
- },
- #endif
- };
- /* Registered client driver list */
- /* static list g_hif_sdio_clt_drv_list */
- static MTK_WCN_HIF_SDIO_REGISTINFO g_hif_sdio_clt_drv_list[CFG_CLIENT_COUNT];
- /* MMC probed function list */
- /* static list g_hif_sdio_probed_func_list */
- static MTK_WCN_HIF_SDIO_PROBEINFO g_hif_sdio_probed_func_list[CFG_CLIENT_COUNT];
- /* spin lock info for g_hif_sdio_clt_drv_list and g_hif_sdio_probed_func_list */
- static MTK_WCN_HIF_SDIO_LOCKINFO g_hif_sdio_lock_info;
- /* reference count, debug information? */
- static INT32 gRefCount;
- static INT32 (*fp_wmt_tra_sdio_update)(VOID);
- static atomic_t hif_sdio_irq_enable_flag = ATOMIC_INIT(0);
- /*deep sleep related information*/
- MTK_WCN_HIF_SDIO_DS_INFO g_hif_sdio_ds_info_list[] = {
- {
- .chip_id = 0x6630,
- .reg_offset = 0xF1,
- .value = 0x1,
- },
- { /* end: all zeroes */ }
- };
- /*******************************************************************************
- * P U B L I C D A T A
- ********************************************************************************
- */
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("MediaTek Inc WCN_SE_CS3");
- MODULE_DESCRIPTION("MediaTek MT6620 HIF SDIO Driver");
- MODULE_DEVICE_TABLE(sdio, mtk_sdio_id_tbl);
- UINT32 gHifSdioDbgLvl = HIF_SDIO_LOG_INFO;
- /*******************************************************************************
- * F U N C T I O N S
- ********************************************************************************
- */
- INT32 __weak mtk_wcn_sdio_irq_flag_set(INT32 falg)
- {
- return 0;
- }
- INT32 mtk_wcn_hif_sdio_irq_flag_set(INT32 flag)
- {
- if (0 == flag) {
- atomic_dec(&hif_sdio_irq_enable_flag);
- if (0 == atomic_read(&hif_sdio_irq_enable_flag))
- mtk_wcn_sdio_irq_flag_set(0);
- } else {
- atomic_inc(&hif_sdio_irq_enable_flag);
- if (1 == atomic_read(&hif_sdio_irq_enable_flag))
- mtk_wcn_sdio_irq_flag_set(1);
- }
- return 0;
- }
- /*!
- * \brief register the callback funciton for record the timestamp of sdio access
- *
- * \param callback function
- *
- * \retval -EINVAL, when registered callback is invalid
- * \retval 0, when registered callback is valid
- */
- extern INT32 mtk_wcn_hif_sdio_update_cb_reg(INT32(*ts_update) (VOID))
- {
- if (ts_update) {
- fp_wmt_tra_sdio_update = ts_update;
- return 0;
- } else {
- return -EINVAL;
- }
- }
- EXPORT_SYMBOL(mtk_wcn_hif_sdio_update_cb_reg);
- /*!
- * \brief update the accessing time of SDIO via callback function
- *
- * \param void
- *
- * \retval -EINVAL, when callback is not registered
- * \retval returned value of callback
- */
- static INT32 wmt_tra_sdio_update(VOID)
- {
- if (fp_wmt_tra_sdio_update)
- return (*fp_wmt_tra_sdio_update) ();
- /* HIF_SDIO_WARN_FUNC("wmt_tra_sdio_update == NULL\n"); */
- return -EINVAL;
- }
- /*!
- * \brief Translate CLTCTX into a pointer to struct sdio_func if it is valid
- *
- * Translate a CLTCTX into a pointer to struct sdio_func if it is
- * 1) probed by mmc_core, and
- * 2) client driver is registered, and
- * 3) clt_idx of client driver is valid
- *
- * \param ctx a context provided by client driver
- *
- * \retval null if any condition is not valie
- * \retval a pointer to a struct sdio_func mapped by provided ctx
- */
- static _osal_inline_ struct sdio_func *hif_sdio_ctx_to_func(MTK_WCN_HIF_SDIO_CLTCTX ctx)
- {
- UINT32 probe_index;
- /* 4 <1> check if ctx is valid, registered, and probed */
- probe_index = CLTCTX_IDX(ctx);
- if (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */
- HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx);
- return NULL;
- }
- /* the client has not been registered */
- if (unlikely(g_hif_sdio_probed_func_list[probe_index].clt_idx < 0)) {
- HIF_SDIO_WARN_FUNC
- ("can't find client idx in probed list!ctx(0x%x) prob_idx(%d) clt_idx(%d)\n",
- ctx, probe_index, g_hif_sdio_probed_func_list[probe_index].clt_idx);
- return NULL;
- }
- return g_hif_sdio_probed_func_list[probe_index].func;
- }
- static INT32 _hif_sdio_deep_sleep_info_dmp(MTK_WCN_HIF_SDIO_DS_INFO *p_ds_info)
- {
- UINT32 i = 0;
- MTK_WCN_HIF_SDIO_DS_CLT_INFO *ctl_info = NULL;
- UINT32 ctl_info_array_size = ARRAY_SIZE(p_ds_info->clt_info);
- mutex_lock(&p_ds_info->lock);
- HIF_SDIO_INFO_FUNC("p_ds_info: 0x%08x, chipid:0x%x, reg_offset:0x%x, value:0x%x\n",
- p_ds_info, p_ds_info->chip_id, p_ds_info->reg_offset, p_ds_info->value);
- for (i = 0; i < ctl_info_array_size; i++) {
- ctl_info = &p_ds_info->clt_info[i];
- HIF_SDIO_INFO_FUNC
- ("ctl_info[%d]--ctx:0x%08x, func_num:%d, act_flag:%d, en_flag:%d\n", i,
- ctl_info->ctx, ctl_info->func_num, ctl_info->act_flag, ctl_info->ds_en_flag);
- }
- mutex_unlock(&p_ds_info->lock);
- return 0;
- }
- static INT32 _hif_sdio_deep_sleep_info_init(VOID)
- {
- UINT32 array_size = 0;
- UINT32 clt_info_size = 0;
- UINT32 i = 0;
- UINT32 j = 0;
- array_size = ARRAY_SIZE(g_hif_sdio_ds_info_list);
- /*set clt_info segment to 0 by default, when do stp/wifi on, write real information back */
- for (i = 0; i < array_size; i++) {
- mutex_init(&g_hif_sdio_ds_info_list[i].lock);
- clt_info_size = ARRAY_SIZE(g_hif_sdio_ds_info_list[i].clt_info);
- mutex_lock(&g_hif_sdio_ds_info_list[i].lock);
- for (j = 0; j < clt_info_size; j++)
- memset(&g_hif_sdio_ds_info_list[i].clt_info[j],
- 0, sizeof(MTK_WCN_HIF_SDIO_DS_CLT_INFO));
- mutex_unlock(&g_hif_sdio_ds_info_list[i].lock);
- _hif_sdio_deep_sleep_info_dmp(&g_hif_sdio_ds_info_list[i]);
- }
- return 0;
- }
- static INT32 _hif_sdio_deep_sleep_info_set_act(UINT32 chipid, UINT16 func_num,
- MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT8 act_flag)
- {
- UINT32 i = 0;
- UINT32 array_size = 0;
- UINT32 clt_info_size = 0;
- UINT32 idx = 0;
- MTK_WCN_HIF_SDIO_DS_CLT_INFO *p_ds_clt_info = NULL;
- array_size = ARRAY_SIZE(g_hif_sdio_ds_info_list);
- /*search write index */
- for (i = 0; i < array_size; i++) {
- if (g_hif_sdio_ds_info_list[i].chip_id == chipid)
- break;
- }
- if (i >= array_size) {
- HIF_SDIO_WARN_FUNC("no valid ds info found for 0x%x\n", chipid);
- return -1;
- }
- HIF_SDIO_DBG_FUNC("valid ds info found for 0x%x\n", chipid);
- clt_info_size = ARRAY_SIZE(g_hif_sdio_ds_info_list[i].clt_info);
- if (func_num > clt_info_size) {
- HIF_SDIO_WARN_FUNC("func num <%d> exceed max clt info size <%d>\n", func_num,
- clt_info_size);
- return -2;
- }
- idx = func_num - 1;
- p_ds_clt_info = &g_hif_sdio_ds_info_list[i].clt_info[idx];
- mutex_lock(&g_hif_sdio_ds_info_list[i].lock);
- p_ds_clt_info->func_num = func_num;
- p_ds_clt_info->ctx = ctx;
- p_ds_clt_info->act_flag = act_flag;
- p_ds_clt_info->ds_en_flag = 0;
- mutex_unlock(&g_hif_sdio_ds_info_list[i].lock);
- HIF_SDIO_INFO_FUNC("set act_flag to %d for ctx:0x%x whose chipid:0x%x, func_num:%d done\n",
- act_flag, ctx, chipid, func_num);
- /* _hif_sdio_deep_sleep_info_dmp(&g_hif_sdio_ds_info_list[0]); */
- return 0;
- }
- static INT32 _hif_sdio_deep_sleep_ctrl(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT8 en_flag)
- {
- UINT32 i = 0;
- UINT32 j = 0;
- INT32 ret = 0;
- UINT32 array_size = 0;
- UINT32 clt_info_size = 0;
- MTK_WCN_HIF_SDIO_DS_CLT_INFO *p_ds_clt_info = NULL;
- MTK_WCN_HIF_SDIO_DS_INFO *p_ds_info = NULL;
- UINT8 do_ds_op_flag = 0;
- array_size = ARRAY_SIZE(g_hif_sdio_ds_info_list);
- /*search write index */
- for (i = 0; i < array_size; i++) {
- mutex_lock(&g_hif_sdio_ds_info_list[i].lock);
- /* _hif_sdio_deep_sleep_info_dmp(&g_hif_sdio_ds_info_list[i]); */
- clt_info_size = ARRAY_SIZE(g_hif_sdio_ds_info_list[i].clt_info);
- for (j = 0; j < clt_info_size; j++) {
- if (g_hif_sdio_ds_info_list[i].clt_info[j].ctx == ctx) {
- do_ds_op_flag = 1;
- break;
- }
- }
- if (0 != do_ds_op_flag)
- break;
- mutex_unlock(&g_hif_sdio_ds_info_list[i].lock);
- }
- if ((i >= array_size) || (j >= clt_info_size)) {
- HIF_SDIO_DBG_FUNC("no valid ds info found for ctx 0x%08x\n, en_flag:%d", ctx,
- en_flag);
- return -1;
- }
- HIF_SDIO_DBG_FUNC("valid ds info found for ctx 0x%08x, en_flag:%d\n", ctx, en_flag);
- p_ds_info = &g_hif_sdio_ds_info_list[i];
- p_ds_clt_info = &p_ds_info->clt_info[j];
- if (0 != p_ds_clt_info->act_flag)
- p_ds_clt_info->ds_en_flag = en_flag;
- else
- HIF_SDIO_DBG_FUNC("!!!!!----this case should never happen----!!!!!\n");
- /*check if deep sleep operation is needed or not */
- do_ds_op_flag = 1;
- for (j = 0; j < clt_info_size; j++) {
- if ((p_ds_info->clt_info[j].ds_en_flag == 0)
- && (p_ds_info->clt_info[j].act_flag == 1)) {
- do_ds_op_flag = 0;
- break;
- }
- }
- if (0 != do_ds_op_flag) {
- #if 0
- ret = mtk_wcn_hif_sdio_f0_writeb(ctx, p_ds_info->reg_offset, p_ds_info->value);
- if (0 == ret) {
- func = hif_sdio_ctx_to_func(ctx);
- HIF_SDIO_DBG_FUNC("msdc_sdio_deep_sleep++\n");
- msdc_sdio_deep_sleep(func->card->host, 0);
- HIF_SDIO_DBG_FUNC("msdc_sdio_deep_sleep--\n");
- HIF_SDIO_DBG_FUNC
- ("write deep sleep register:0x%x with value:0x%x succeed\n",
- p_ds_info->reg_offset, p_ds_info->value);
- } else {
- HIF_SDIO_ERR_FUNC("write deep sleep register:0x%x with value:0x%x failed\n",
- p_ds_info->reg_offset, p_ds_info->value);
- }
- #endif
- } else {
- HIF_SDIO_DBG_FUNC("no need to do deep sleep operation\n");
- }
- mutex_unlock(&g_hif_sdio_ds_info_list[i].lock);
- return ret;
- }
- /*!
- * \brief MTK hif sdio client registration function
- *
- * Client uses this function to register itself to hif_sdio driver
- *
- * \param pinfo a pointer of client's information
- *
- * \retval 0 register successfully
- * \retval < 0 list error code here
- */
- INT32 mtk_wcn_hif_sdio_client_reg(const MTK_WCN_HIF_SDIO_CLTINFO *pinfo)
- {
- INT32 ret = -HIF_SDIO_ERR_FAIL;
- INT32 clt_index = -1;
- UINT32 i = 0;
- UINT32 j = 0;
- MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_probe_worker_info = 0;
- HIF_SDIO_INFO_FUNC("start!\n");
- /* 4 <1> check input pointer is valid */
- HIF_SDIO_ASSERT(pinfo);
- /* 4 <2> check if input parameters are all supported and valid */
- for (i = 0; i < pinfo->func_tbl_size; i++) {
- ret =
- hif_sdio_check_supported_sdio_id(pinfo->func_tbl[i].manf_id,
- pinfo->func_tbl[i].card_id);
- if (ret) {
- HIF_SDIO_WARN_FUNC
- ("vendor id(0x%x) and device id(0x%x) of sdio_func are not supported!\n",
- pinfo->func_tbl[i].manf_id, pinfo->func_tbl[i].card_id);
- goto out;
- }
- }
- HIF_SDIO_DBG_FUNC("hif_sdio_check_supported_sdio_id() done!\n");
- /* 4 <3> check if the specific {manf id, card id, function number} tuple is */
- /* 4 already resigstered */
- for (i = 0; i < pinfo->func_tbl_size; i++) {
- 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);
- if (ret) {
- HIF_SDIO_WARN_FUNC("vendor id(0x%x), device id(0x%x), and fun_num(%d) of\n",
- pinfo->func_tbl[i].manf_id, pinfo->func_tbl[i].card_id,
- pinfo->func_tbl[i].func_num);
- HIF_SDIO_WARN_FUNC("sdio_func are duplicated in g_hif_sdio_clt_drv_list!\n");
- goto out;
- }
- }
- HIF_SDIO_DBG_FUNC("hif_sdio_check_duplicate_sdio_id() done!\n");
- /* 4 <4> add the specified {manf id, card id, function number}
- * tuple to registered client list */
- HIF_SDIO_DBG_FUNC("pinfo->func_tbl_size:%d\n", pinfo->func_tbl_size);
- for (i = 0; i < pinfo->func_tbl_size; i++) {
- ret = hif_sdio_add_clt_list(&clt_index, pinfo, i);
- if (ret) {
- HIF_SDIO_WARN_FUNC
- ("client's info are added in registed client list failed (buffer is full)!\n");
- goto out;
- }
- HIF_SDIO_DBG_FUNC("hif_sdio_add_clt_list() done (gRefCount=%d)!\n", gRefCount);
- /* 4 <5> if the specific {manf id, card id, function number} tuple has already */
- /* 4 been probed by mmc, schedule another task to call client's .hif_clt_probe() */
- for (j = 0; j < CFG_CLIENT_COUNT; j++) {
- /* probed spin lock */
- spin_lock_bh(&g_hif_sdio_lock_info.probed_list_lock);
- if (g_hif_sdio_probed_func_list[j].func == 0) {
- /* probed spin unlock */
- spin_unlock_bh(&g_hif_sdio_lock_info.probed_list_lock);
- continue;
- }
- /* the function has been probed */
- if ((g_hif_sdio_clt_drv_list[clt_index].func_info->manf_id ==
- g_hif_sdio_probed_func_list[j].func->vendor)
- && (g_hif_sdio_clt_drv_list[clt_index].func_info->card_id ==
- g_hif_sdio_probed_func_list[j].func->device)
- && (g_hif_sdio_clt_drv_list[clt_index].func_info->func_num ==
- g_hif_sdio_probed_func_list[j].func->num)) {
- g_hif_sdio_probed_func_list[j].clt_idx = clt_index;
- /* probed spin unlock */
- spin_unlock_bh(&g_hif_sdio_lock_info.probed_list_lock);
- /* use worker thread to perform the client's .hif_clt_probe() */
- clt_probe_worker_info =
- vmalloc(sizeof(MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO));
- if (clt_probe_worker_info) {
- INIT_WORK(&clt_probe_worker_info->probe_work,
- hif_sdio_clt_probe_worker);
- clt_probe_worker_info->registinfo_p =
- &g_hif_sdio_clt_drv_list[clt_index];
- clt_probe_worker_info->probe_idx = j;
- schedule_work(&clt_probe_worker_info->probe_work);
- }
- /* 4 <5.1> remember to do claim_irq for the func if it's irq had been released. */
- if (!(g_hif_sdio_probed_func_list[j].func->irq_handler)) {
- sdio_claim_host(g_hif_sdio_probed_func_list[j].func);
- ret =
- sdio_claim_irq(g_hif_sdio_probed_func_list[j].func,
- hif_sdio_irq);
- mtk_wcn_hif_sdio_irq_flag_set(1);
- sdio_release_host(g_hif_sdio_probed_func_list[j].func);
- HIF_SDIO_INFO_FUNC
- ("sdio_claim_irq for func(0x%p) j(%d) v(0x%x) d(0x%x) ok\n",
- g_hif_sdio_probed_func_list[j].func, j,
- g_hif_sdio_probed_func_list[j].func->vendor,
- g_hif_sdio_probed_func_list[j].func->device);
- }
- /* 4 <5.2> Reset the block size of the function provided by client */
- HIF_SDIO_INFO_FUNC("Reset sdio block size: %d!\n",
- g_hif_sdio_clt_drv_list[clt_index].
- func_info->blk_sz);
- sdio_claim_host(g_hif_sdio_probed_func_list[j].func);
- ret = sdio_set_block_size(g_hif_sdio_probed_func_list[j].func,
- g_hif_sdio_clt_drv_list
- [clt_index].func_info->blk_sz);
- sdio_release_host(g_hif_sdio_probed_func_list[j].func);
- } else {
- /* probed spin unlock */
- spin_unlock_bh(&g_hif_sdio_lock_info.probed_list_lock);
- }
- }
- HIF_SDIO_DBG_FUNC
- ("map g_hif_sdio_clt_drv_list to g_hif_sdio_probed_func_list done!\n");
- }
- ret = HIF_SDIO_ERR_SUCCESS;
- gRefCount++;
- out:
- /* 4 <last> error handling */
- HIF_SDIO_DBG_FUNC("end!\n");
- return ret;
- } /* end of mtk_wcn_hif_sdio_client_reg() */
- EXPORT_SYMBOL(mtk_wcn_hif_sdio_client_reg);
- /*!
- * \brief MTK hif sdio client un-registration function
- *
- * Client uses this function to un-register itself
- *
- * \param pinfo a pointer of client's information
- *
- * \retval 0 register successfully
- * \retval < 0 list error code here
- */
- INT32 mtk_wcn_hif_sdio_client_unreg(const MTK_WCN_HIF_SDIO_CLTINFO *pinfo)
- {
- INT32 ret = -HIF_SDIO_ERR_FAIL;
- INT32 clt_list_index = 0;
- UINT32 i = 0;
- UINT32 j = 0;
- HIF_SDIO_INFO_FUNC("start!\n");
- /* 4 <1> check if input pointer is valid */
- HIF_SDIO_ASSERT(pinfo);
- /* 4 <2> check if input parameters are all supported and valid */
- for (i = 0; i < pinfo->func_tbl_size; i++) {
- ret =
- hif_sdio_check_supported_sdio_id(pinfo->func_tbl[i].manf_id,
- pinfo->func_tbl[i].card_id);
- if (ret) {
- 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",
- pinfo->func_tbl[i].manf_id, pinfo->func_tbl[i].card_id);
- goto out;
- }
- }
- /* 4 <3> check if the specific {manf id, card id, function number} tuple is already resigstered */
- /* 4 and find the corresponding client ctx and call client's .hif_clt_remove() in THIS context */
- for (i = 0; i < pinfo->func_tbl_size; i++) {
- 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);
- if (clt_list_index < 0) {
- HIF_SDIO_WARN_FUNC("vendor id(0x%x),", pinfo->func_tbl[i].manf_id);
- HIF_SDIO_WARN_FUNC(" device id(0x%x),", pinfo->func_tbl[i].card_id);
- HIF_SDIO_WARN_FUNC(" and fun_num(%d)", pinfo->func_tbl[i].func_num);
- HIF_SDIO_WARN_FUNC(" client info is not in the client's registed list!\n");
- ret = -HIF_SDIO_ERR_FAIL;
- goto out;
- }
- /* 4 <4> mark the specified {manf id, card id, function number} tuple as */
- /* 4 un-registered and invalidate client's context */
- hif_sdio_init_clt_list(clt_list_index);
- /* un-map g_hif_sdio_clt_drv_list index in g_hif_sdio_probed_func_list */
- for (j = 0; j < CFG_CLIENT_COUNT; j++) {
- if (g_hif_sdio_probed_func_list[j].clt_idx == clt_list_index)
- g_hif_sdio_probed_func_list[j].clt_idx = -1;
- }
- }
- gRefCount--;
- ret = HIF_SDIO_ERR_SUCCESS;
- out:
- HIF_SDIO_INFO_FUNC("end (gRefCount=%d) !\n", gRefCount);
- return ret;
- } /* end of mtk_wcn_hif_sdio_client_unreg() */
- EXPORT_SYMBOL(mtk_wcn_hif_sdio_client_unreg);
- /*!
- * \brief
- *
- * detailed descriptions
- *
- * \param ctx client's context variable
- *
- * \retval 0 register successfully
- * \retval < 0 list error code here
- */
- INT32 mtk_wcn_hif_sdio_readb(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT32 offset, PUINT8 pvb)
- {
- #if HIF_SDIO_UPDATE
- INT32 ret;
- struct sdio_func *func;
- #else
- INT32 ret = -HIF_SDIO_ERR_FAIL;
- int probe_index = -1;
- struct sdio_func *func = 0;
- #endif
- HIF_SDIO_DBG_FUNC("start!\n");
- HIF_SDIO_ASSERT(pvb);
- /* 4 <1> check if ctx is valid, registered, and probed */
- #if HIF_SDIO_UPDATE
- ret = -HIF_SDIO_ERR_FAIL;
- func = hif_sdio_ctx_to_func(ctx);
- if (!func) {
- ret = -HIF_SDIO_ERR_FAIL;
- goto out;
- }
- #else
- probe_index = CLTCTX_IDX(ctx);
- if (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */
- HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx);
- goto out;
- }
- if (probe_index < 0 || probe_index >= CFG_CLIENT_COUNT) { /* the function has not been probed */
- HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
- ret = -HIF_SDIO_ERR_FAIL;
- goto out;
- } else {
- if (g_hif_sdio_probed_func_list[probe_index].clt_idx < 0) { /* the client has not been registered */
- HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
- ret = -HIF_SDIO_ERR_FAIL;
- goto out;
- }
- }
- func = g_hif_sdio_probed_func_list[probe_index].func;
- #endif
- /* 4 <2> */
- sdio_claim_host(func);
- *pvb = sdio_readb(func, offset, &ret);
- sdio_release_host(func);
- /* 4 <3> check result code and return proper error code */
- out:
- HIF_SDIO_DBG_FUNC("end!\n");
- return ret;
- } /* end of mtk_wcn_hif_sdio_client_unreg() */
- EXPORT_SYMBOL(mtk_wcn_hif_sdio_readb);
- /*!
- * \brief
- *
- * detailed descriptions
- *
- * \param ctx client's context variable
- *
- * \retval 0 register successfully
- * \retval < 0 list error code here
- */
- INT32 mtk_wcn_hif_sdio_writeb(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT32 offset, UINT8 vb)
- {
- #if HIF_SDIO_UPDATE
- INT32 ret;
- struct sdio_func *func;
- #else
- INT32 ret = -HIF_SDIO_ERR_FAIL;
- INT32 probe_index = -1;
- struct sdio_func *func = 0;
- #endif
- HIF_SDIO_DBG_FUNC("start!\n");
- /* 4 <1> check if ctx is valid, registered, and probed */
- #if HIF_SDIO_UPDATE
- ret = -HIF_SDIO_ERR_FAIL;
- func = hif_sdio_ctx_to_func(ctx);
- if (!func) {
- ret = -HIF_SDIO_ERR_FAIL;
- goto out;
- }
- #else
- probe_index = CLTCTX_IDX(ctx);
- if (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */
- HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx);
- goto out;
- }
- if (probe_index < 0 || probe_index >= CFG_CLIENT_COUNT) { /* the function has not been probed */
- HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
- ret = -HIF_SDIO_ERR_FAIL;
- goto out;
- } else {
- if (g_hif_sdio_probed_func_list[probe_index].clt_idx < 0) { /* the client has not been registered */
- HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
- ret = -HIF_SDIO_ERR_FAIL;
- goto out;
- }
- }
- func = g_hif_sdio_probed_func_list[probe_index].func;
- #endif
- /* 4 <1.1> check if input parameters are valid */
- /* 4 <2> */
- wmt_tra_sdio_update();
- sdio_claim_host(func);
- sdio_writeb(func, vb, offset, &ret);
- sdio_release_host(func);
- /* 4 <3> check result code and return proper error code */
- out:
- HIF_SDIO_DBG_FUNC("end!\n");
- return ret;
- } /* end of mtk_wcn_hif_sdio_client_unreg() */
- EXPORT_SYMBOL(mtk_wcn_hif_sdio_writeb);
- /*!
- * \brief
- *
- * detailed descriptions
- *
- * \param ctx client's context variable
- *
- * \retval 0 register successfully
- * \retval < 0 list error code here
- */
- INT32 mtk_wcn_hif_sdio_readl(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT32 offset, PUINT32 pvl)
- {
- #if HIF_SDIO_UPDATE
- INT32 ret;
- struct sdio_func *func;
- #else
- INT32 ret = -HIF_SDIO_ERR_FAIL;
- INT32 probe_index = -1;
- struct sdio_func *func = 0;
- #endif
- HIF_SDIO_DBG_FUNC("start!\n");
- HIF_SDIO_ASSERT(pvl);
- /* 4 <1> check if ctx is valid, registered, and probed */
- #if HIF_SDIO_UPDATE
- ret = -HIF_SDIO_ERR_FAIL;
- func = hif_sdio_ctx_to_func(ctx);
- if (!func) {
- ret = -HIF_SDIO_ERR_FAIL;
- goto out;
- }
- #else
- probe_index = CLTCTX_IDX(ctx);
- if (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */
- HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx);
- goto out;
- }
- if (probe_index < 0 || probe_index >= CFG_CLIENT_COUNT) { /* the function has not been probed */
- HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
- ret = -HIF_SDIO_ERR_FAIL;
- goto out;
- } else {
- if (g_hif_sdio_probed_func_list[probe_index].clt_idx < 0) { /* the client has not been registered */
- HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
- ret = -HIF_SDIO_ERR_FAIL;
- goto out;
- }
- }
- func = g_hif_sdio_probed_func_list[probe_index].func;
- #endif
- /* 4 <1.1> check if input parameters are valid */
- /* 4 <2> */
- sdio_claim_host(func);
- *pvl = sdio_readl(func, offset, &ret);
- sdio_release_host(func);
- /* 4 <3> check result code and return proper error code */
- out:
- HIF_SDIO_DBG_FUNC("end!\n");
- return ret;
- } /* end of mtk_wcn_hif_sdio_client_unreg() */
- EXPORT_SYMBOL(mtk_wcn_hif_sdio_readl);
- /*!
- * \brief
- *
- * detailed descriptions
- *
- * \param ctx client's context variable
- *
- * \retval 0 register successfully
- * \retval < 0 list error code here
- */
- INT32 mtk_wcn_hif_sdio_writel(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT32 offset, UINT32 vl)
- {
- #if HIF_SDIO_UPDATE
- INT32 ret;
- struct sdio_func *func;
- #else
- INT32 ret = -HIF_SDIO_ERR_FAIL;
- INT32 probe_index = -1;
- struct sdio_func *func = 0;
- #endif
- HIF_SDIO_DBG_FUNC("start!\n");
- /* 4 <1> check if ctx is valid, registered, and probed */
- #if HIF_SDIO_UPDATE
- ret = -HIF_SDIO_ERR_FAIL;
- func = hif_sdio_ctx_to_func(ctx);
- if (!func) {
- ret = -HIF_SDIO_ERR_FAIL;
- goto out;
- }
- #else
- probe_index = CLTCTX_IDX(ctx);
- if (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */
- HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx);
- goto out;
- }
- if (probe_index < 0 || probe_index >= CFG_CLIENT_COUNT) { /* the function has not been probed */
- HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
- ret = -HIF_SDIO_ERR_FAIL;
- goto out;
- } else {
- if (g_hif_sdio_probed_func_list[probe_index].clt_idx < 0) { /* the client has not been registered */
- HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
- ret = -HIF_SDIO_ERR_FAIL;
- goto out;
- }
- }
- func = g_hif_sdio_probed_func_list[probe_index].func;
- #endif
- /* 4 <1.1> check if input parameters are valid */
- /* 4 <2> */
- wmt_tra_sdio_update();
- sdio_claim_host(func);
- sdio_writel(func, vl, offset, &ret);
- sdio_release_host(func);
- /* 4 <3> check result code and return proper error code */
- out:
- HIF_SDIO_DBG_FUNC("end!\n");
- return ret;
- } /* end of mtk_wcn_hif_sdio_client_unreg() */
- EXPORT_SYMBOL(mtk_wcn_hif_sdio_writel);
- /*!
- * \brief
- *
- * detailed descriptions
- *
- * \param ctx client's context variable
- *
- * \retval 0 register successfully
- * \retval < 0 list error code here
- */
- INT32 mtk_wcn_hif_sdio_read_buf(MTK_WCN_HIF_SDIO_CLTCTX ctx,
- UINT32 offset, PUINT32 pbuf, UINT32 len)
- {
- #if HIF_SDIO_UPDATE
- INT32 ret;
- struct sdio_func *func;
- #else
- INT32 ret = -HIF_SDIO_ERR_FAIL;
- INT32 probe_index = -1;
- struct sdio_func *func = 0;
- #endif
- HIF_SDIO_DBG_FUNC("start!\n");
- HIF_SDIO_ASSERT(pbuf);
- /* 4 <1> check if ctx is valid, registered, and probed */
- #if HIF_SDIO_UPDATE
- ret = -HIF_SDIO_ERR_FAIL;
- func = hif_sdio_ctx_to_func(ctx);
- if (!func) {
- ret = -HIF_SDIO_ERR_FAIL;
- goto out;
- }
- #else
- probe_index = CLTCTX_IDX(ctx);
- if (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */
- HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx);
- goto out;
- }
- if (probe_index < 0 || probe_index >= CFG_CLIENT_COUNT) { /* the function has not been probed */
- HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
- ret = -HIF_SDIO_ERR_FAIL;
- goto out;
- } else {
- if (g_hif_sdio_probed_func_list[probe_index].clt_idx < 0) { /* the client has not been registered */
- HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
- ret = -HIF_SDIO_ERR_FAIL;
- goto out;
- }
- }
- func = g_hif_sdio_probed_func_list[probe_index].func;
- #endif
- /* 4 <1.1> check if input parameters are valid */
- /* 4 <2> */
- sdio_claim_host(func);
- ret = sdio_readsb(func, pbuf, offset, len);
- sdio_release_host(func);
- /* 4 <3> check result code and return proper error code */
- out:
- HIF_SDIO_DBG_FUNC("end!\n");
- return ret;
- } /* end of mtk_wcn_hif_sdio_read_buf() */
- EXPORT_SYMBOL(mtk_wcn_hif_sdio_read_buf);
- /*!
- * \brief
- *
- * detailed descriptions
- *
- * \param ctx client's context variable
- *
- * \retval 0 register successfully
- * \retval < 0 list error code here
- */
- INT32 mtk_wcn_hif_sdio_write_buf(MTK_WCN_HIF_SDIO_CLTCTX ctx,
- UINT32 offset, PUINT32 pbuf, UINT32 len)
- {
- #if HIF_SDIO_UPDATE
- INT32 ret;
- struct sdio_func *func;
- #else
- INT32 ret = -HIF_SDIO_ERR_FAIL;
- INT32 probe_index = -1;
- struct sdio_func *func = 0;
- #endif
- HIF_SDIO_DBG_FUNC("start!\n");
- HIF_SDIO_ASSERT(pbuf);
- /* 4 <1> check if ctx is valid, registered, and probed */
- #if HIF_SDIO_UPDATE
- ret = -HIF_SDIO_ERR_FAIL;
- func = hif_sdio_ctx_to_func(ctx);
- if (!func) {
- ret = -HIF_SDIO_ERR_FAIL;
- goto out;
- }
- #else
- probe_index = CLTCTX_IDX(ctx);
- if (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */
- HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx);
- goto out;
- }
- if (probe_index < 0 || probe_index >= CFG_CLIENT_COUNT) { /* the function has not been probed */
- HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
- ret = -HIF_SDIO_ERR_FAIL;
- goto out;
- } else {
- if (g_hif_sdio_probed_func_list[probe_index].clt_idx < 0) { /* the client has not been registered */
- HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
- ret = -HIF_SDIO_ERR_FAIL;
- goto out;
- }
- }
- func = g_hif_sdio_probed_func_list[probe_index].func;
- #endif
- /* 4 <1.1> check if input parameters are valid */
- /* 4 <2> */
- wmt_tra_sdio_update();
- sdio_claim_host(func);
- ret = sdio_writesb(func, offset, pbuf, len);
- sdio_release_host(func);
- /* 4 <3> check result code and return proper error code */
- out:
- HIF_SDIO_DBG_FUNC("ret(%d) end!\n", ret);
- return ret;
- } /* end of mtk_wcn_hif_sdio_write_buf() */
- EXPORT_SYMBOL(mtk_wcn_hif_sdio_write_buf);
- /*!
- * \brief store client driver's private data function.
- *
- *
- * \param clent's MTK_WCN_HIF_SDIO_CLTCTX.
- *
- * \retval none.
- */
- VOID mtk_wcn_hif_sdio_set_drvdata(MTK_WCN_HIF_SDIO_CLTCTX ctx, PVOID private_data_p)
- {
- UINT8 probed_idx = CLTCTX_IDX(ctx);
- if (unlikely(!CLTCTX_IDX_VALID(probed_idx))) { /* invalid index in CLTCTX */
- HIF_SDIO_WARN_FUNC("invalid idx in ctx(0x%x), private_data_p not stored!\n", ctx);
- } else {
- /* store client driver's private data to dev driver */
- g_hif_sdio_probed_func_list[probed_idx].private_data_p = private_data_p;
- HIF_SDIO_DBG_FUNC("private_data_p(0x%p) for ctx(0x%x) probed idx(%d) stored!\n",
- private_data_p, ctx, probed_idx);
- }
- }
- EXPORT_SYMBOL(mtk_wcn_hif_sdio_set_drvdata);
- /*!
- * \brief get client driver's private data function.
- *
- *
- * \param clent's MTK_WCN_HIF_SDIO_CLTCTX.
- *
- * \retval private data pointer.
- */
- PVOID mtk_wcn_hif_sdio_get_drvdata(MTK_WCN_HIF_SDIO_CLTCTX ctx)
- {
- UINT8 probed_idx = CLTCTX_IDX(ctx);
- /* get client driver's private data to dev driver */
- if (likely(CLTCTX_IDX_VALID(probed_idx)))
- return g_hif_sdio_probed_func_list[probed_idx].private_data_p;
- /* invalid index in CLTCTX */
- HIF_SDIO_WARN_FUNC("invalid idx in ctx(0x%x), return null!\n", ctx);
- return NULL;
- }
- EXPORT_SYMBOL(mtk_wcn_hif_sdio_get_drvdata);
- /*!
- * \brief control stp/wifi on/off from wmt.
- *
- *
- * \param (1)control function type, (2)on/off control.
- *
- * \retval (1)control results ,(2)unknown type: -5.
- * \retval 0:success, -11:not probed, -12:already on, -13:not registered, other errors.
- */
- INT32 mtk_wcn_hif_sdio_wmt_control(WMT_SDIO_FUNC_TYPE func_type, MTK_WCN_BOOL is_on)
- {
- /* TODO:[FixMe][George]: return value of this function shall distinguish */
- /* 1) not probed by mmc_core yet or */
- /* 2) probed by mmc_core but init fail... */
- switch (func_type) {
- case WMT_SDIO_FUNC_STP:
- if (is_on == MTK_WCN_BOOL_TRUE)
- return hif_sdio_stp_on();
- else
- return hif_sdio_stp_off();
- break;
- case WMT_SDIO_FUNC_WIFI:
- if (is_on == MTK_WCN_BOOL_TRUE)
- return hif_sdio_wifi_on();
- else
- return hif_sdio_wifi_off();
- break;
- default:
- HIF_SDIO_WARN_FUNC("unknown type(%d)\n", func_type);
- return HIF_SDIO_ERR_INVALID_PARAM;
- }
- }
- EXPORT_SYMBOL(mtk_wcn_hif_sdio_wmt_control);
- /*!
- * \brief ???
- *
- * \detail ???
- *
- * \param ctx a context provided by client driver
- * \param struct device ** ???
- *
- * \retval none
- */
- VOID mtk_wcn_hif_sdio_get_dev(MTK_WCN_HIF_SDIO_CLTCTX ctx, struct device **dev)
- {
- #if HIF_SDIO_UPDATE
- struct sdio_func *func;
- #else
- UINT8 probe_index = CLTCTX_IDX(ctx);
- #endif
- #if HIF_SDIO_UPDATE
- *dev = NULL; /* ensure we does not return any invalid value back. */
- func = hif_sdio_ctx_to_func(ctx);
- if (unlikely(!func)) {
- HIF_SDIO_WARN_FUNC("no valid *func with ctx(0x%x)\n", ctx);
- return;
- }
- *dev = &(func->dev);
- HIF_SDIO_DBG_FUNC("return *dev(0x%p) for ctx(0x%x)\n", *dev, ctx);
- #else
- if (probe_index < 0) {
- HIF_SDIO_WARN_FUNC("func not probed, probe_index = %d", probe_index);
- return;
- }
- *dev = &g_hif_sdio_probed_func_list[probe_index].func->dev;
- #endif
- }
- EXPORT_SYMBOL(mtk_wcn_hif_sdio_get_dev);
- /*!
- * \brief client's probe() function.
- *
- *
- * \param work queue structure.
- *
- * \retval none.
- */
- static INT32 hif_sdio_clt_probe_func(MTK_WCN_HIF_SDIO_REGISTINFO *registinfo_p, INT8 probe_idx)
- {
- UINT16 card_id = 0;
- UINT16 func_num = 0;
- UINT16 blk_sz = 0;
- INT32 ret;
- HIF_SDIO_DBG_FUNC("start!\n");
- HIF_SDIO_ASSERT(registinfo_p);
- if (!registinfo_p) {
- HIF_SDIO_WARN_FUNC("registinfo_p NULL!!!\n");
- return -1;
- }
- /* special case handling: if the clt's unregister is called during probe procedures */
- if (!registinfo_p->func_info || !registinfo_p->sdio_cltinfo) {
- HIF_SDIO_WARN_FUNC("client's registinfo_p is cleared !!!\n");
- return -1;
- }
- card_id = registinfo_p->func_info->card_id;
- func_num = registinfo_p->func_info->func_num;
- blk_sz = registinfo_p->func_info->blk_sz;
- ret =
- registinfo_p->sdio_cltinfo->hif_clt_probe(CLTCTX(card_id, func_num, blk_sz, probe_idx),
- registinfo_p->func_info);
- HIF_SDIO_INFO_FUNC
- ("clt_probe_func card_id(%x) func_num(%x) blk_sz(%d) prob_idx(%x) ret(%d) %s\n",
- card_id, func_num, blk_sz, probe_idx, ret, (ret) ? "fail" : "ok");
- return ret;
- }
- /*!
- * \brief client's probe() worker.
- *
- *
- * \param work queue structure.
- *
- * \retval none.
- */
- static VOID hif_sdio_clt_probe_worker(struct work_struct *work)
- {
- MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_worker_info_p = 0;
- UINT16 card_id = 0;
- UINT16 func_num = 0;
- UINT16 blk_sz = 0;
- INT8 prob_idx = 0;
- HIF_SDIO_DBG_FUNC("start!\n");
- HIF_SDIO_ASSERT(work);
- /* get client's information */
- clt_worker_info_p = container_of(work, MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO, probe_work);
- HIF_SDIO_ASSERT(clt_worker_info_p);
- HIF_SDIO_ASSERT(clt_worker_info_p->registinfo_p);
- /* special case handling: if the clt's unregister is called during probe procedures */
- if ((clt_worker_info_p->registinfo_p->func_info == 0)
- || (clt_worker_info_p->registinfo_p->sdio_cltinfo == 0)) {
- HIF_SDIO_WARN_FUNC("client's registinfo_p is cleared !!!\n");
- vfree(clt_worker_info_p);
- return;
- }
- card_id = clt_worker_info_p->registinfo_p->func_info->card_id;
- func_num = clt_worker_info_p->registinfo_p->func_info->func_num;
- blk_sz = clt_worker_info_p->registinfo_p->func_info->blk_sz;
- prob_idx = clt_worker_info_p->probe_idx;
- /* Execute client's probe() func */
- clt_worker_info_p->registinfo_p->
- sdio_cltinfo->hif_clt_probe(CLTCTX(card_id, func_num, blk_sz, prob_idx),
- clt_worker_info_p->registinfo_p->func_info);
- vfree(clt_worker_info_p);
- 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);
- HIF_SDIO_DBG_FUNC("end!\n");
- }
- /*!
- * \brief client's probe() worker.
- *
- *
- * \param work queue structure.
- *
- * \retval none.
- */
- static VOID hif_sdio_dump_probe_list(VOID)
- {
- int i;
- HIF_SDIO_DBG_FUNC("== DUMP probed list start ==\n");
- for (i = 0; i < CFG_CLIENT_COUNT; i++) {
- if (g_hif_sdio_probed_func_list[i].func) {
- HIF_SDIO_DBG_FUNC("index(%d) func(0x%p) clt_idx(%d)\n",
- i, g_hif_sdio_probed_func_list[i].func,
- g_hif_sdio_probed_func_list[i].clt_idx);
- HIF_SDIO_DBG_FUNC("vendor(0x%x) device(0x%x) num(0x%x) state(%d)\n",
- g_hif_sdio_probed_func_list[i].func->vendor,
- g_hif_sdio_probed_func_list[i].func->device,
- g_hif_sdio_probed_func_list[i].func->num,
- g_hif_sdio_probed_func_list[i].on_by_wmt);
- }
- }
- HIF_SDIO_DBG_FUNC("== DUMP probed list end ==\n");
- }
- /*!
- * \brief Initialize g_hif_sdio_probed_func_list
- *
- *
- * \param index of g_hif_sdio_probed_func_list.
- *
- * \retval none.
- */
- static VOID hif_sdio_init_probed_list(INT32 index)
- {
- if ((index >= 0) && (index < CFG_CLIENT_COUNT)) {
- /* probed spin lock */
- spin_lock_bh(&g_hif_sdio_lock_info.probed_list_lock);
- g_hif_sdio_probed_func_list[index].func = 0;
- g_hif_sdio_probed_func_list[index].clt_idx = -1;
- g_hif_sdio_probed_func_list[index].private_data_p = 0;
- g_hif_sdio_probed_func_list[index].on_by_wmt = MTK_WCN_BOOL_FALSE;
- /* probed spin unlock */
- spin_unlock_bh(&g_hif_sdio_lock_info.probed_list_lock);
- } else
- HIF_SDIO_ERR_FUNC("index is out of g_hif_sdio_probed_func_list[] boundary!\n");
- }
- /*!
- * \brief Initialize g_hif_sdio_clt_drv_list
- *
- *
- * \param index of g_hif_sdio_clt_drv_list.
- *
- * \retval none.
- */
- static VOID hif_sdio_init_clt_list(INT32 index)
- {
- /* client list spin lock */
- spin_lock_bh(&g_hif_sdio_lock_info.clt_list_lock);
- if ((index >= 0) && (index < CFG_CLIENT_COUNT)) {
- g_hif_sdio_clt_drv_list[index].sdio_cltinfo = 0;
- g_hif_sdio_clt_drv_list[index].func_info = 0;
- } else
- HIF_SDIO_ERR_FUNC("index is out of g_hif_sdio_clt_drv_list[] boundary!\n");
- /* client list spin unlock */
- spin_unlock_bh(&g_hif_sdio_lock_info.clt_list_lock);
- }
- /*!
- * \brief find matched g_hif_sdio_probed_func_list index from sdio function handler
- *
- *
- * \param sdio function handler
- *
- * \retval -1 index not found
- * \retval >= 0 return found index
- */
- static INT32 hif_sdio_find_probed_list_index_by_func(struct sdio_func *func)
- {
- INT32 i = 0;
- HIF_SDIO_ASSERT(func);
- for (i = 0; i < CFG_CLIENT_COUNT; i++) {
- if (g_hif_sdio_probed_func_list[i].func == func)
- return i;
- }
- return -1;
- }
- /*!
- * \brief find matched g_hif_sdio_probed_func_list from vendor_id, device_id, and function number
- *
- *
- * \param vendor id, device id, and function number of the sdio card.
- *
- * \retval -1 index not found
- * \retval >= 0 return found index
- */
- static INT32 hif_sdio_find_probed_list_index_by_id_func(UINT16 vendor, UINT16 device,
- UINT16 func_num)
- {
- INT32 i;
- for (i = 0; i < CFG_CLIENT_COUNT; i++) {
- if (g_hif_sdio_probed_func_list[i].func) {
- HIF_SDIO_DBG_FUNC("probed entry: vendor(0x%x) device(0x%x) num(0x%x)\n",
- g_hif_sdio_probed_func_list[i].func->vendor,
- g_hif_sdio_probed_func_list[i].func->device,
- g_hif_sdio_probed_func_list[i].func->num);
- }
- }
- for (i = 0; i < CFG_CLIENT_COUNT; i++) {
- if (!g_hif_sdio_probed_func_list[i].func) {
- continue;
- } else if ((g_hif_sdio_probed_func_list[i].func->vendor == vendor) &&
- (g_hif_sdio_probed_func_list[i].func->device == device) &&
- (g_hif_sdio_probed_func_list[i].func->num == func_num)) {
- return i;
- }
- }
- if (i == CFG_CLIENT_COUNT) {
- /*
- pr_warn(DRV_NAME "Cannot find vendor:0x%x, device:0x%x, func_num:0x%x, i=%d\n",
- vendor, device, func_num, i);
- */
- /* client func has not been probed */
- return -1;
- }
- return -1;
- }
- /*!
- * \brief find matched g_hif_sdio_clt_drv_list index
- *
- * find the matched g_hif_sdio_clt_drv_list index from card_id and function number.
- *
- * \param vendor id, device id, and function number of the sdio card
- *
- * \retval -1 index not found
- * \retval >= 0 return found index
- */
- static INT32 hif_sdio_find_clt_list_index(UINT16 vendor, UINT16 device, UINT16 func_num)
- {
- INT32 i = 0;
- for (i = 0; i < CFG_CLIENT_COUNT; i++) {
- if (g_hif_sdio_clt_drv_list[i].func_info != 0) {
- if ((g_hif_sdio_clt_drv_list[i].func_info->manf_id == vendor) &&
- (g_hif_sdio_clt_drv_list[i].func_info->card_id == device) &&
- (g_hif_sdio_clt_drv_list[i].func_info->func_num == func_num)) {
- return i;
- }
- }
- }
- return -1;
- }
- /*!
- * \brief check if the vendor, device ids are supported in mtk_sdio_id_tbl.
- *
- *
- * \param vendor id and device id of the sdio card
- *
- * \retval (-HIF_SDIO_ERR_FAIL) vendor, device ids are not supported
- * \retval HIF_SDIO_ERR_SUCCESS vendor, device ids are supported
- */
- static INT32 hif_sdio_check_supported_sdio_id(UINT16 vendor, UINT16 device)
- {
- INT32 i = 0;
- for (i = 0; i < CFG_CLIENT_COUNT; i++) {
- if ((mtk_sdio_id_tbl[i].vendor == vendor) && (mtk_sdio_id_tbl[i].device == device))
- return HIF_SDIO_ERR_SUCCESS; /* mtk_sdio_id is supported */
- }
- return -HIF_SDIO_ERR_FAIL; /* mtk_sdio_id is not supported */
- }
- /*!
- * \brief check if the vendor, device ids are duplicated in g_hif_sdio_clt_drv_list.
- *
- *
- * \param vendor id, device id, and function number of the sdio card
- *
- * \retval (-HIF_SDIO_ERR_DUPLICATED) vendor, device, func_num are duplicated
- * \retval HIF_SDIO_ERR_SUCCESS vendor, device, func_num are not duplicated
- */
- static INT32 hif_sdio_check_duplicate_sdio_id(UINT16 vendor, UINT16 device, UINT16 func_num)
- {
- INT32 i = 0;
- for (i = 0; i < CFG_CLIENT_COUNT; i++) {
- if (g_hif_sdio_clt_drv_list[i].func_info != 0) {
- if ((g_hif_sdio_clt_drv_list[i].func_info->manf_id == vendor) &&
- (g_hif_sdio_clt_drv_list[i].func_info->card_id == device) &&
- (g_hif_sdio_clt_drv_list[i].func_info->func_num == func_num)) {
- return -HIF_SDIO_ERR_DUPLICATED; /* duplicated */
- }
- }
- }
- return HIF_SDIO_ERR_SUCCESS; /* Not duplicated */
- }
- /*!
- * \brief Add the client info into g_hif_sdio_clt_drv_list.
- *
- *
- * \param [output] client's index pointer.
- * \param MTK_WCN_HIF_SDIO_CLTINFO of client's contex.
- *
- * \retval (-HIF_SDIO_ERR_FAIL) Add to clt_list successfully
- * \retval HIF_SDIO_ERR_SUCCESS Add to clt_list failed (buffer is full)
- */
- static INT32 hif_sdio_add_clt_list(INT32 *clt_index_p,
- const MTK_WCN_HIF_SDIO_CLTINFO *pinfo, UINT32 tbl_index)
- {
- INT32 i = 0;
- HIF_SDIO_ASSERT(clt_index_p);
- HIF_SDIO_ASSERT(pinfo);
- for (i = 0; i < CFG_CLIENT_COUNT; i++) {
- /* client list spin lock */
- spin_lock_bh(&g_hif_sdio_lock_info.clt_list_lock);
- if (g_hif_sdio_clt_drv_list[i].func_info == 0) {
- g_hif_sdio_clt_drv_list[i].func_info = &(pinfo->func_tbl[tbl_index]);
- g_hif_sdio_clt_drv_list[i].sdio_cltinfo = pinfo;
- /* client list spin unlock */
- spin_unlock_bh(&g_hif_sdio_lock_info.clt_list_lock);
- *clt_index_p = i;
- return HIF_SDIO_ERR_SUCCESS; /* Add to client list successfully */
- }
- /* client list spin unlock */
- spin_unlock_bh(&g_hif_sdio_lock_info.clt_list_lock);
- }
- return -HIF_SDIO_ERR_FAIL; /* Add to client list failed (buffer is full) */
- }
- #if HIF_SDIO_SUPPORT_SUSPEND
- static INT32 hif_sdio_suspend(struct device *dev)
- {
- struct sdio_func *func;
- mmc_pm_flag_t flag;
- INT32 ret;
- if (!dev)
- return -EINVAL;
- func = dev_to_sdio_func(dev);
- HIF_SDIO_DBG_FUNC("prepare for func(0x%p)\n", func);
- flag = sdio_get_host_pm_caps(func);
- #if HIF_SDIO_SUPPORT_WAKEUP
- if (!(flag & MMC_PM_KEEP_POWER) || !(flag & MMC_PM_WAKE_SDIO_IRQ)) {
- HIF_SDIO_WARN_FUNC
- ("neither MMC_PM_KEEP_POWER or MMC_PM_WAKE_SDIO_IRQ is supported by host, return -ENOTSUPP\n");
- return -ENOTSUPP;
- }
- /* set both */
- flag |= MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ;
- #else
- if (!(flag & MMC_PM_KEEP_POWER)) {
- HIF_SDIO_WARN_FUNC
- ("neither MMC_PM_KEEP_POWER is supported by host, return -ENOTSUPP\n");
- return -ENOTSUPP;
- }
- flag |= MMC_PM_KEEP_POWER;
- #endif
- ret = sdio_set_host_pm_flags(func, flag);
- if (ret) {
- HIF_SDIO_INFO_FUNC
- ("set MMC_PM_KEEP_POWER to host fail(%d)\n", ret);
- return -EFAULT;
- }
- #if HIF_SDIO_SUPPORT_WAKEUP
- sdio_claim_host(func);
- #endif
- HIF_SDIO_INFO_FUNC("set MMC_PM_KEEP_POWER ok\n");
- return 0;
- }
- static INT32 hif_sdio_resume(struct device *dev)
- {
- #if HIF_SDIO_SUPPORT_WAKEUP
- struct sdio_func *func;
- #endif
- if (!dev) {
- HIF_SDIO_WARN_FUNC("null dev!\n");
- return -EINVAL;
- }
- #if HIF_SDIO_SUPPORT_WAKEUP
- func = dev_to_sdio_func(dev);
- sdio_release_host(func);
- #endif
- HIF_SDIO_INFO_FUNC("do nothing\n");
- return 0;
- }
- #endif
- /*!
- * \brief hif_sdio probe function
- *
- * hif_sdio probe function called by mmc driver when any matched SDIO function
- * is detected by it.
- *
- * \param func
- * \param id
- *
- * \retval 0 register successfully
- * \retval < 0 list error code here
- */
- static INT32 hif_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
- {
- INT32 ret = 0;
- INT32 i = 0;
- MTK_WCN_HIF_SDIO_PROBEINFO *hif_sdio_probed_funcp = 0;
- INT32 probe_index = -1;
- INT32 idx;
- #if 0
- INT32 clt_index = -1;
- MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_probe_worker_info = 0;
- #endif
- HIF_SDIO_INFO_FUNC("start!\n");
- HIF_SDIO_ASSERT(func);
- #if !(DELETE_HIF_SDIO_CHRDEV)
- hif_sdio_match_chipid_by_dev_id(id);
- #endif
- /* 4 <0> display debug information */
- HIF_SDIO_INFO_FUNC("vendor(0x%x) device(0x%x) num(0x%x)\n", func->vendor, func->device,
- func->num);
- for (i = 0; i < func->card->num_info; i++)
- HIF_SDIO_INFO_FUNC("card->info[%d]: %s\n", i, func->card->info[i]);
- /* 4 <1> Check if this is supported by us (mtk_sdio_id_tbl) */
- ret = hif_sdio_check_supported_sdio_id(func->vendor, func->device);
- if (ret) {
- HIF_SDIO_WARN_FUNC
- ("vendor id and device id of sdio_func are not supported in mtk_sdio_id_tbl!\n");
- goto out;
- }
- /* 4 <2> Add this struct sdio_func *func to g_hif_sdio_probed_func_list */
- for (i = 0; i < CFG_CLIENT_COUNT; i++) {
- /* probed spin lock */
- spin_lock_bh(&g_hif_sdio_lock_info.probed_list_lock);
- if (g_hif_sdio_probed_func_list[i].func == 0) {
- hif_sdio_probed_funcp = &g_hif_sdio_probed_func_list[i];
- hif_sdio_probed_funcp->func = func;
- hif_sdio_probed_funcp->clt_idx =
- hif_sdio_find_clt_list_index(func->vendor, func->device, func->num);
- hif_sdio_probed_funcp->on_by_wmt = MTK_WCN_BOOL_FALSE;
- hif_sdio_probed_funcp->sdio_irq_enabled = MTK_WCN_BOOL_FALSE;
- /* probed spin unlock */
- spin_unlock_bh(&g_hif_sdio_lock_info.probed_list_lock);
- probe_index = i;
- break;
- }
- /* probed spin unlock */
- spin_unlock_bh(&g_hif_sdio_lock_info.probed_list_lock);
- }
- if ((probe_index < 0) || (probe_index >= CFG_CLIENT_COUNT)) {
- HIF_SDIO_ERR_FUNC("probe function list if full!\n");
- goto out;
- }
- /* 4 <3> Initialize this function */
- if (g_hif_sdio_probed_func_list[probe_index].clt_idx < 0) {
- for (i = 0; i < CFG_CLIENT_COUNT; i++) {
- /* client list spin lock */
- spin_lock_bh(&g_hif_sdio_lock_info.clt_list_lock);
- if (g_hif_sdio_clt_drv_list[i].func_info == 0) {
- /* client list spin unlock */
- spin_unlock_bh(&g_hif_sdio_lock_info.clt_list_lock);
- continue;
- }
- 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);
- if ((g_hif_sdio_clt_drv_list[i].func_info->manf_id ==
- g_hif_sdio_probed_func_list[probe_index].func->vendor)
- && (g_hif_sdio_clt_drv_list[i].func_info->card_id ==
- g_hif_sdio_probed_func_list[probe_index].func->device)
- && (g_hif_sdio_clt_drv_list[i].func_info->func_num ==
- g_hif_sdio_probed_func_list[probe_index].func->num)) {
- g_hif_sdio_probed_func_list[probe_index].clt_idx = i;
- /* client list spin unlock */
- spin_unlock_bh(&g_hif_sdio_lock_info.clt_list_lock);
- break;
- }
- /* client list spin unlock */
- spin_unlock_bh(&g_hif_sdio_lock_info.clt_list_lock);
- }
- 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);
- }
- /* 4 <3.1> enable this function */
- sdio_claim_host(func);
- ret = sdio_enable_func(func);
- sdio_release_host(func);
- if (ret) {
- HIF_SDIO_ERR_FUNC("sdio_enable_func failed!\n");
- goto out;
- }
- #if 0
- if (0 == _hif_sdio_is_autok_support(func))
- /* _hif_sdio_do_autok(func); */
- #endif
- /* 4 <3.2> set block size according to the table storing function characteristics */
- if (hif_sdio_probed_funcp == 0) {
- HIF_SDIO_ERR_FUNC("hif_sdio_probed_funcp is null!\n");
- goto out;
- }
- if (hif_sdio_probed_funcp->clt_idx >= 0 &&
- hif_sdio_probed_funcp->clt_idx < CFG_CLIENT_COUNT) {
- /* The clt contex has been registed */
- sdio_claim_host(func);
- idx = hif_sdio_probed_funcp->clt_idx;
- ret = sdio_set_block_size(func, g_hif_sdio_clt_drv_list[idx].func_info->blk_sz);
- sdio_release_host(func);
- } else { /* The clt contex has not been registed */
- sdio_claim_host(func);
- ret = sdio_set_block_size(func, HIF_DEFAULT_BLK_SIZE);
- sdio_release_host(func);
- }
- if (ret) {
- HIF_SDIO_ERR_FUNC("set sdio block size failed!\n");
- goto out;
- }
- HIF_SDIO_INFO_FUNC("cur_blksize(%d) max(%d), host max blk_size(%d) blk_count(%d)\n",
- func->cur_blksize, func->max_blksize,
- func->card->host->max_blk_size, func->card->host->max_blk_count);
- hif_sdio_dump_probe_list();
- out:
- /* 4 <last> error handling */
- return ret;
- }
- /*!
- * \brief hif_sdio remove function
- *
- * hif_sdio probe function called by mmc driver when the probed func should be
- * removed.
- *
- * \param func
- *
- */
- static VOID hif_sdio_remove(struct sdio_func *func)
- {
- INT32 probed_list_index = 0;
- #if 0
- INT32 registed_list_index = 0;
- #endif
- HIF_SDIO_INFO_FUNC("start!\n");
- HIF_SDIO_ASSERT(func);
- /* 4 <1> check input parameter is valid and has been probed previously */
- if (func == NULL) {
- HIF_SDIO_ERR_FUNC("func null(%p)\n", func);
- return;
- }
- /* 4 <2> if this function has been initialized by any client driver, */
- /* 4 call client's .hif_clt_remove() call back in THIS context. */
- probed_list_index = hif_sdio_find_probed_list_index_by_func(func);
- if (probed_list_index < 0) {
- HIF_SDIO_WARN_FUNC
- ("sdio function pointer is not in g_hif_sdio_probed_func_list!\n");
- return;
- }
- #if 0
- registed_list_index = g_hif_sdio_probed_func_list[probed_list_index].clt_idx;
- if (registed_list_index >= 0) {
- g_hif_sdio_clt_drv_list[registed_list_index].sdio_cltinfo->hif_clt_remove(CLTCTX
- (func->
- device,
- func->
- num,
- func->
- cur_blksize,
- probed_list_index));
- }
- #endif
- /* 4 <3> mark this function as de-initialized and invalidate client's context */
- hif_sdio_init_probed_list(probed_list_index);
- #if 0
- /* 4 <4> release irq for this function */
- sdio_claim_host(func);
- sdio_release_irq(func);
- sdio_release_host(func);
- #endif
- /* 4 <5> disable this function */
- sdio_claim_host(func);
- sdio_disable_func(func);
- sdio_release_host(func);
- /* 4 <6> mark this function as removed */
- HIF_SDIO_INFO_FUNC("sdio func(0x%p) is removed successfully!\n", func);
- }
- /*!
- * \brief hif_sdio interrupt handler
- *
- * detailed descriptions
- *
- * \param ctx client's context variable
- *
- */
- static VOID hif_sdio_irq(struct sdio_func *func)
- {
- INT32 probed_list_index = -1;
- INT32 registed_list_index = -1;
- HIF_SDIO_DBG_FUNC("start!\n");
- /* 4 <1> check if func is valid */
- HIF_SDIO_ASSERT(func);
- /* 4 <2> if func has valid corresponding hif_sdio client's context, mark it */
- /* 4 host-locked, use it to call client's .hif_clt_irq() callback function in */
- /* 4 THIS context. */
- probed_list_index = hif_sdio_find_probed_list_index_by_func(func);
- if ((probed_list_index < 0) || (probed_list_index >= CFG_CLIENT_COUNT)) {
- HIF_SDIO_ERR_FUNC("probed_list_index not found!\n");
- return;
- }
- /* [George] added for sdio irq sync and mmc single_irq workaround. It's set
- * enabled later by client driver call mtk_wcn_hif_sdio_enable_irq()
- */
- /* skip smp_rmb() here */
- if (MTK_WCN_BOOL_FALSE == g_hif_sdio_probed_func_list[probed_list_index].sdio_irq_enabled) {
- HIF_SDIO_WARN_FUNC("func(0x%p),probed_idx(%d) sdio irq not enabled yet\n",
- func, probed_list_index);
- return;
- }
- registed_list_index = g_hif_sdio_probed_func_list[probed_list_index].clt_idx;
- /* g_hif_sdio_probed_func_list[probed_list_index].interrupted = MTK_WCN_BOOL_TRUE; */
- if ((registed_list_index >= 0)
- && (registed_list_index < CFG_CLIENT_COUNT)) {
- HIF_SDIO_DBG_FUNC("[%d]SDIO IRQ (func:0x%p) v(0x%x) d(0x%x) n(0x%x)\n",
- probed_list_index, func, func->vendor, func->device, func->num);
- _hif_sdio_deep_sleep_ctrl(CLTCTX
- (func->device, func->num, func->cur_blksize,
- probed_list_index), 0);
- g_hif_sdio_clt_drv_list[registed_list_index].sdio_cltinfo->hif_clt_irq(CLTCTX
- (func->
- device,
- func->num,
- func->
- cur_blksize,
- probed_list_index));
- } else {
- /* 4 <3> if func has no VALID hif_sdio client's context, release irq for this */
- /* 4 func and mark it in g_hif_sdio_probed_func_list (remember: donnot claim host in irq contex). */
- HIF_SDIO_WARN_FUNC("release irq (func:0x%p) v(0x%x) d(0x%x) n(0x%x)\n",
- func, func->vendor, func->device, func->num);
- mtk_wcn_hif_sdio_irq_flag_set(0);
- sdio_release_irq(func);
- }
- }
- /*!
- * \brief hif_sdio init function
- *
- * detailed descriptions
- *
- * \retval
- */
- static INT32 hif_sdio_init(VOID)
- {
- INT32 ret = 0;
- INT32 i = 0;
- HIF_SDIO_INFO_FUNC("start!\n");
- /* 4 <1> init all private variables */
- /* init reference count to 0 */
- gRefCount = 0;
- atomic_set(&hif_sdio_irq_enable_flag, 0);
- /* init spin lock information */
- spin_lock_init(&g_hif_sdio_lock_info.probed_list_lock);
- spin_lock_init(&g_hif_sdio_lock_info.clt_list_lock);
- /* init probed function list and g_hif_sdio_clt_drv_list */
- for (i = 0; i < CFG_CLIENT_COUNT; i++) {
- hif_sdio_init_probed_list(i);
- hif_sdio_init_clt_list(i);
- }
- /* 4 <2> register to mmc driver */
- ret = sdio_register_driver(&mtk_sdio_client_drv);
- HIF_SDIO_INFO_FUNC("sdio_register_driver() ret=%d\n", ret);
- #if !(DELETE_HIF_SDIO_CHRDEV)
- /* 4 <3> create thread for query chip id and device node for launcher to access */
- if (0 == hifsdiod_start())
- hif_sdio_create_dev_node();
- #endif
- _hif_sdio_deep_sleep_info_init();
- HIF_SDIO_DBG_FUNC("end!\n");
- return ret;
- }
- /*!
- * \brief hif_sdio init function
- *
- * detailed descriptions
- *
- * \retval
- */
- static VOID hif_sdio_exit(VOID)
- {
- HIF_SDIO_INFO_FUNC("start!\n");
- #if !(DELETE_HIF_SDIO_CHRDEV)
- hif_sdio_remove_dev_node();
- hifsdiod_stop();
- #endif
- /* 4 <0> if client driver is not removed yet, we shall NOT be called... */
- /* 4 <1> check reference count */
- if (gRefCount != 0)
- HIF_SDIO_WARN_FUNC("gRefCount=%d !!!\n", gRefCount);
- /* 4 <2> check if there is any hif_sdio-registered clients. There should be */
- /* 4 no registered client... */
- /* 4 <3> Reregister with mmc driver. Our remove handler hif_sdio_remove() */
- /* 4 will be called later by mmc_core. Clean up driver resources there. */
- sdio_unregister_driver(&mtk_sdio_client_drv);
- atomic_set(&hif_sdio_irq_enable_flag, 0);
- HIF_SDIO_DBG_FUNC("end!\n");
- } /* end of exitWlan() */
- /*!
- * \brief stp on by wmt (probe client driver).
- *
- *
- * \param none.
- *
- * \retval 0:success, -11:not probed, -12:already on, -13:not registered, other errors.
- */
- INT32 hif_sdio_stp_on(VOID)
- {
- #if 0
- MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_probe_worker_info = 0;
- #endif
- INT32 clt_index = -1;
- INT32 probe_index = -1;
- INT32 ret = -1;
- INT32 ret2 = -1;
- struct sdio_func *func;
- UINT32 chip_id = 0;
- UINT16 func_num = 0;
- const MTK_WCN_HIF_SDIO_FUNCINFO *func_info = NULL;
- HIF_SDIO_INFO_FUNC("start!\n");
- /* 4 <1> If stp client drv has not been probed, return error code */
- /* MT6620 */
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020B, 1);
- if (probe_index >= 0)
- goto stp_on_exist;
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020C, 1);
- if (probe_index >= 0)
- goto stp_on_exist;
- /* MT6628 */
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6628, 2);
- if (probe_index >= 0)
- goto stp_on_exist;
- /* MT6630 */
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6630, 2);
- if (probe_index >= 0) {
- chip_id = 0x6630;
- func_num = 2;
- goto stp_on_exist;
- }
- /* MT6619 */
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6619, 1);
- if (probe_index >= 0)
- goto stp_on_exist;
- /* MT6618 */
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018B, 1);
- if (probe_index >= 0)
- goto stp_on_exist;
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018C, 1);
- if (probe_index >= 0)
- goto stp_on_exist;
- else {
- /* 4 <2> If stp client drv has not been probed, return error code */
- /* client func has not been probed */
- HIF_SDIO_INFO_FUNC("no supported func probed\n");
- return HIF_SDIO_ERR_NOT_PROBED;
- }
- stp_on_exist:
- /* 4 <3> If stp client drv has been on by wmt, return error code */
- if (MTK_WCN_BOOL_FALSE != g_hif_sdio_probed_func_list[probe_index].on_by_wmt) {
- HIF_SDIO_INFO_FUNC("already on...\n");
- return HIF_SDIO_ERR_ALRDY_ON;
- }
- g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_TRUE;
- clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx;
- if (clt_index >= 0) { /* the function has been registered */
- g_hif_sdio_probed_func_list[probe_index].sdio_irq_enabled = MTK_WCN_BOOL_FALSE;
- /* 4 <4> claim irq for this function */
- func = g_hif_sdio_probed_func_list[probe_index].func;
- if (unlikely(!(func) || !(func->card) || !(func->card->host)
- || mmc_card_removed(func->card))) {
- HIF_SDIO_ERR_FUNC("sdio host is missing\n");
- return HIF_SDIO_ERR_NOT_PROBED;
- }
- sdio_claim_host(func);
- ret = sdio_claim_irq(func, hif_sdio_irq);
- mtk_wcn_hif_sdio_irq_flag_set(1);
- sdio_release_host(func);
- if (ret) {
- HIF_SDIO_WARN_FUNC("sdio_claim_irq() for stp fail(%d)\n", ret);
- return ret;
- }
- HIF_SDIO_INFO_FUNC("sdio_claim_irq() for stp ok\n");
- /* 4 <5> If this struct sdio_func *func is supported by any driver in */
- /* 4 g_hif_sdio_clt_drv_list, schedule another task to call client's .hif_clt_probe() */
- /* TODO: [FixMe][George] WHY probe worker is removed??? */
- #if 1
- /* Call client's .hif_clt_probe() */
- ret = hif_sdio_clt_probe_func(&g_hif_sdio_clt_drv_list[clt_index], probe_index);
- if (ret) {
- HIF_SDIO_WARN_FUNC("clt_probe_func() for stp fail(%d) release irq\n", ret);
- sdio_claim_host(func);
- mtk_wcn_hif_sdio_irq_flag_set(0);
- ret2 = sdio_release_irq(func);
- sdio_release_host(func);
- if (ret2)
- HIF_SDIO_WARN_FUNC("sdio_release_irq() for stp fail(%d)\n", ret2);
- g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_FALSE;
- return ret;
- }
- g_hif_sdio_probed_func_list[probe_index].sdio_irq_enabled = MTK_WCN_BOOL_TRUE;
- /*set deep sleep information to global data struct */
- func_info = g_hif_sdio_clt_drv_list[clt_index].func_info;
- _hif_sdio_deep_sleep_info_set_act(chip_id, func_num,
- CLTCTX(func_info->card_id, func_info->func_num,
- func_info->blk_sz, probe_index), 1);
- HIF_SDIO_INFO_FUNC("ok!\n");
- return 0;
- #else
- /* use worker thread to perform the client's .hif_clt_probe() */
- clt_probe_worker_info = vmalloc(sizeof(MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO));
- INIT_WORK(&clt_probe_worker_info->probe_work, hif_sdio_clt_probe_worker);
- clt_probe_worker_info->registinfo_p = &g_hif_sdio_clt_drv_list[clt_index];
- clt_probe_worker_info->probe_idx = probe_index;
- schedule_work(&clt_probe_worker_info->probe_work);
- #endif
- } else {
- /* TODO: [FixMe][George] check if clt_index is cleared in client's unregister function */
- HIF_SDIO_WARN_FUNC("probed but not registered yet (%d)\n", ret);
- return HIF_SDIO_ERR_CLT_NOT_REG;
- }
- }
- /*!
- * \brief stp off by wmt (remove client driver).
- *
- *
- * \param none.
- *
- * \retval 0:success, -11:not probed, -12:already off, -13:not registered, other errors.
- */
- INT32 hif_sdio_stp_off(VOID)
- {
- INT32 clt_index = -1;
- INT32 probe_index = -1;
- INT32 ret = -1;
- INT32 ret2 = -1;
- struct sdio_func *func;
- UINT32 chip_id = 0;
- UINT16 func_num = 0;
- const MTK_WCN_HIF_SDIO_FUNCINFO *func_info = NULL;
- HIF_SDIO_INFO_FUNC("start!\n");
- /* 4 <1> If stp client drv has not been probed, return error code */
- /* MT6620 */
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020B, 1);
- if (probe_index >= 0)
- goto stp_off_exist;
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020C, 1);
- if (probe_index >= 0)
- goto stp_off_exist;
- /* MT6628 */
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6628, 2);
- if (probe_index >= 0)
- goto stp_off_exist;
- /* MT6630 */
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6630, 2);
- if (probe_index >= 0) {
- chip_id = 0x6630;
- func_num = 2;
- goto stp_off_exist;
- }
- /* MT6619 */
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6619, 1);
- if (probe_index >= 0)
- goto stp_off_exist;
- /* MT6618 */
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018B, 1);
- if (probe_index >= 0)
- goto stp_off_exist;
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018C, 1);
- if (probe_index >= 0)
- goto stp_off_exist;
- else {
- /* 4 <2> If stp client drv has not been probed, return error code */
- /* client func has not been probed */
- return HIF_SDIO_ERR_NOT_PROBED;
- }
- stp_off_exist:
- /* 4 <3> If stp client drv has been off by wmt, return error code */
- if (MTK_WCN_BOOL_FALSE == g_hif_sdio_probed_func_list[probe_index].on_by_wmt) {
- HIF_SDIO_WARN_FUNC("already off...\n");
- return HIF_SDIO_ERR_ALRDY_OFF;
- }
- g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_FALSE;
- #if 0 /* TODO: [FixMe][George] moved below as done in stp_on. */
- /* 4 <4> release irq for this function */
- func = g_hif_sdio_probed_func_list[probe_index].func;
- sdio_claim_host(func);
- ret = sdio_release_irq(func);
- sdio_release_host(func);
- if (ret)
- pr_warn(DRV_NAME "sdio_release_irq for stp fail(%d)\n", ret);
- else
- pr_warn(DRV_NAME "sdio_release_irq for stp ok\n");
- #endif
- clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx;
- if (clt_index >= 0) { /* the function has been registered */
- func = g_hif_sdio_probed_func_list[probe_index].func;
- if (unlikely(!(func) || !(func->card) || !(func->card->host)
- || mmc_card_removed(func->card))) {
- HIF_SDIO_ERR_FUNC("sdio host is missing\n");
- return HIF_SDIO_ERR_ALRDY_OFF;
- }
- /* 4 <4> release irq for this function */
- sdio_claim_host(func);
- mtk_wcn_hif_sdio_irq_flag_set(0);
- ret2 = sdio_release_irq(func);
- sdio_release_host(func);
- if (ret2)
- HIF_SDIO_WARN_FUNC("sdio_release_irq() for stp fail(%d)\n", ret2);
- else
- HIF_SDIO_INFO_FUNC("sdio_release_irq() for stp ok\n");
- /* 4 <5> Callback to client driver's remove() func */
- ret =
- g_hif_sdio_clt_drv_list[clt_index].
- sdio_cltinfo->hif_clt_remove(CLTCTX
- (func->device, func->num, func->cur_blksize,
- probe_index));
- if (ret)
- HIF_SDIO_WARN_FUNC("clt_remove for stp fail(%d)\n", ret);
- else
- HIF_SDIO_INFO_FUNC("ok!\n");
- /*set deep sleep information to global data struct */
- func_info = g_hif_sdio_clt_drv_list[clt_index].func_info;
- _hif_sdio_deep_sleep_info_set_act(chip_id, func_num,
- CLTCTX(func_info->card_id, func_info->func_num,
- func_info->blk_sz, probe_index), 0);
- return ret + ret2;
- }
- /* TODO: [FixMe][George] check if clt_index is cleared in client's unregister function */
- HIF_SDIO_WARN_FUNC("probed but not registered yet (%d)\n", ret);
- return HIF_SDIO_ERR_CLT_NOT_REG;
- }
- /*!
- * \brief wifi on by wmt (probe client driver).
- *
- *
- * \param none.
- *
- * \retval 0:success, -11:not probed, -12:already on, -13:not registered, other errors.
- */
- INT32 hif_sdio_wifi_on(VOID)
- {
- #if 0
- MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_probe_worker_info = 0;
- #endif
- INT32 clt_index = -1;
- INT32 probe_index = -1;
- INT32 ret = 0;
- INT32 ret2 = 0;
- INT32 sdio_autok_flag = 0;
- struct sdio_func *func;
- UINT32 chip_id = 0;
- UINT16 func_num = 0;
- const MTK_WCN_HIF_SDIO_FUNCINFO *func_info = NULL;
- HIF_SDIO_INFO_FUNC("start!\n");
- /* 4 <1> If wifi client drv has not been probed, return error code */
- /* MT6620 */
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020A, 1);
- if (probe_index >= 0)
- goto wifi_on_exist;
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020C, 2);
- if (probe_index >= 0)
- goto wifi_on_exist;
- /* MT6628 */
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6628, 1);
- if (probe_index == 0)
- goto wifi_on_exist;
- /* MT6630 */
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6630, 1);
- if (probe_index >= 0) {
- sdio_autok_flag = 1;
- chip_id = 0x6630;
- func_num = 1;
- goto wifi_on_exist;
- }
- /* MT6618 */
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018A, 1);
- if (probe_index == 0)
- goto wifi_on_exist;
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018C, 2);
- if (probe_index >= 0)
- goto wifi_on_exist;
- else {
- /* 4 <2> If wifi client drv has not been probed, return error code */
- /* client func has not been probed */
- return HIF_SDIO_ERR_NOT_PROBED;
- }
- wifi_on_exist:
- /* 4 <3> If wifi client drv has been on by wmt, return error code */
- if (g_hif_sdio_probed_func_list[probe_index].on_by_wmt) {
- HIF_SDIO_INFO_FUNC("probe_index (%d), already on...\n", probe_index);
- return HIF_SDIO_ERR_ALRDY_ON;
- }
- clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx;
- if (clt_index >= 0) { /* the function has been registered */
- if (sdio_autok_flag)
- _hif_sdio_do_autok(g_hif_sdio_probed_func_list[probe_index].func);
- else
- HIF_SDIO_INFO_FUNC("sdio_autok_flag is not set\n", ret);
- g_hif_sdio_probed_func_list[probe_index].sdio_irq_enabled = MTK_WCN_BOOL_FALSE;
- /* 4 <4> claim irq for this function */
- func = g_hif_sdio_probed_func_list[probe_index].func;
- if (unlikely(!(func) || !(func->card) || !(func->card->host)
- || mmc_card_removed(func->card))) {
- HIF_SDIO_ERR_FUNC("sdio host is missing\n");
- return HIF_SDIO_ERR_NOT_PROBED;
- }
- sdio_claim_host(func);
- ret = sdio_claim_irq(func, hif_sdio_irq);
- mtk_wcn_hif_sdio_irq_flag_set(1);
- sdio_release_host(func);
- if (ret) {
- HIF_SDIO_WARN_FUNC("sdio_claim_irq() for wifi fail(%d)\n", ret);
- return ret;
- }
- HIF_SDIO_INFO_FUNC("sdio_claim_irq() for wifi ok\n");
- /* 4 <5> If this struct sdio_func *func is supported by any driver in */
- /* 4 g_hif_sdio_clt_drv_list, schedule another task to call client's .hif_clt_probe() */
- /* TODO: [FixMe][George] WHY probe worker is removed??? */
- #if 1
- /*set deep sleep information to global data struct */
- func_info = g_hif_sdio_clt_drv_list[clt_index].func_info;
- _hif_sdio_deep_sleep_info_set_act(chip_id, func_num,
- CLTCTX(func_info->card_id, func_info->func_num,
- func_info->blk_sz, probe_index), 1);
- /* Call client's .hif_clt_probe() */
- ret = hif_sdio_clt_probe_func(&g_hif_sdio_clt_drv_list[clt_index], probe_index);
- if (ret) {
- HIF_SDIO_WARN_FUNC("clt_probe_func() for wifi fail(%d) release irq\n", ret);
- sdio_claim_host(func);
- mtk_wcn_hif_sdio_irq_flag_set(0);
- ret2 = sdio_release_irq(func);
- sdio_release_host(func);
- if (ret2)
- HIF_SDIO_WARN_FUNC("sdio_release_irq() for wifi fail(%d)\n", ret2);
- _hif_sdio_deep_sleep_info_set_act(chip_id, func_num,
- CLTCTX(func_info->card_id,
- func_info->func_num,
- func_info->blk_sz, probe_index),
- 0);
- g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_FALSE;
- return ret;
- }
- g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_TRUE;
- HIF_SDIO_INFO_FUNC("ok!\n");
- return 0;
- #else
- /* use worker thread to perform the client's .hif_clt_probe() */
- clt_probe_worker_info = vmalloc(sizeof(MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO));
- INIT_WORK(&clt_probe_worker_info->probe_work, hif_sdio_clt_probe_worker);
- clt_probe_worker_info->registinfo_p = &g_hif_sdio_clt_drv_list[clt_index];
- clt_probe_worker_info->probe_idx = probe_index;
- schedule_work(&clt_probe_worker_info->probe_work);
- #endif
- } else {
- /* TODO: [FixMe][George] check if clt_index is cleared in client's unregister function */
- HIF_SDIO_WARN_FUNC("probed but not registered yet (%d)\n", ret);
- return HIF_SDIO_ERR_CLT_NOT_REG;
- }
- }
- /*!
- * \brief wifi off by wmt (remove client driver).
- *
- *
- * \param none.
- *
- * \retval 0:success, -11:not probed, -12:already off, -13:not registered, other errors.
- */
- INT32 hif_sdio_wifi_off(VOID)
- {
- INT32 clt_index = -1;
- INT32 probe_index = -1;
- INT32 ret = -1;
- INT32 ret2 = -1;
- struct sdio_func *func;
- UINT32 chip_id = 0;
- UINT16 func_num = 0;
- const MTK_WCN_HIF_SDIO_FUNCINFO *func_info = NULL;
- HIF_SDIO_INFO_FUNC("start!\n");
- /* 4 <1> If wifi client drv has not been probed, return error code */
- /* MT6620 */
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020A, 1);
- if (probe_index >= 0)
- goto wifi_off_exist;
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020C, 2);
- if (probe_index >= 0)
- goto wifi_off_exist;
- /* MT6628 */
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6628, 1);
- if (probe_index >= 0)
- goto wifi_off_exist;
- /* MT6630 */
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6630, 1);
- if (probe_index >= 0) {
- chip_id = 0x6630;
- func_num = 1;
- goto wifi_off_exist;
- }
- /* MT6618 */
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018A, 1);
- if (probe_index >= 0)
- goto wifi_off_exist;
- probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018C, 2);
- if (probe_index >= 0)
- goto wifi_off_exist;
- else {
- /* 4 <2> If wifi client drv has not been probed, return error code */
- /* client func has not been probed */
- return HIF_SDIO_ERR_NOT_PROBED;
- }
- wifi_off_exist:
- /* 4 <3> If wifi client drv has been off by wmt, return error code */
- if (MTK_WCN_BOOL_FALSE == g_hif_sdio_probed_func_list[probe_index].on_by_wmt) {
- HIF_SDIO_WARN_FUNC("already off...\n");
- return HIF_SDIO_ERR_ALRDY_OFF;
- }
- g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_FALSE;
- #if 0 /* TODO: [FixMe][George] moved below as done in wifi_on. */
- /* 4 <4> release irq for this function */
- func = g_hif_sdio_probed_func_list[probe_index].func;
- sdio_claim_host(func);
- ret = sdio_release_irq(func);
- sdio_release_host(func);
- if (ret)
- pr_warn(DRV_NAME "sdio_release_irq for wifi fail(%d)\n", ret);
- else
- pr_warn(DRV_NAME "sdio_release_irq for wifi ok\n");
- #endif
- clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx;
- if (clt_index >= 0) { /* the function has been registered */
- func = g_hif_sdio_probed_func_list[probe_index].func;
- /* 4 <4> Callback to client driver's remove() func */
- ret =
- g_hif_sdio_clt_drv_list[clt_index].
- sdio_cltinfo->hif_clt_remove(CLTCTX
- (func->device, func->num, func->cur_blksize,
- probe_index));
- if (ret)
- HIF_SDIO_WARN_FUNC("clt_remove for wifi fail(%d)\n", ret);
- else
- HIF_SDIO_INFO_FUNC("ok!\n");
- if (unlikely(!(func) || !(func->card) || !(func->card->host)
- || mmc_card_removed(func->card))) {
- HIF_SDIO_ERR_FUNC("sdio host is missing\n");
- return HIF_SDIO_ERR_ALRDY_OFF;
- }
- /* 4 <5> release irq for this function */
- sdio_claim_host(func);
- mtk_wcn_hif_sdio_irq_flag_set(0);
- ret2 = sdio_release_irq(func);
- sdio_release_host(func);
- g_hif_sdio_probed_func_list[probe_index].sdio_irq_enabled = MTK_WCN_BOOL_FALSE;
- if (ret2)
- HIF_SDIO_WARN_FUNC("sdio_release_irq() for wifi fail(%d)\n", ret2);
- else
- HIF_SDIO_INFO_FUNC("sdio_release_irq() for wifi ok\n");
- /*set deep sleep information to global data struct */
- func_info = g_hif_sdio_clt_drv_list[clt_index].func_info;
- _hif_sdio_deep_sleep_info_set_act(chip_id, func_num,
- CLTCTX(func_info->card_id, func_info->func_num,
- func_info->blk_sz, probe_index), 0);
- return ret + ret2;
- }
- /* TODO: [FixMe][George] check if clt_index is cleared in client's unregister function */
- HIF_SDIO_WARN_FUNC("probed but not registered yet (%d)\n", ret);
- return HIF_SDIO_ERR_CLT_NOT_REG;
- }
- /*!
- * \brief set mmc power up/off
- *
- * detailed descriptions
- *
- * \param: 1. ctx client's context variable, 2.power state: 1:power up, other:power off
- *
- * \retval 0:success, -1:fail
- */
- INT32 mtk_wcn_hif_sdio_bus_set_power(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT32 pwrState)
- {
- int probe_index = -1;
- struct sdio_func *func = 0;
- HIF_SDIO_INFO_FUNC("turn Bus Power to: %d\n", pwrState);
- probe_index = CLTCTX_IDX(ctx);
- if (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */
- HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx);
- return -1;
- }
- func = g_hif_sdio_probed_func_list[probe_index].func;
- if (!func) {
- HIF_SDIO_WARN_FUNC("Cannot find sdio_func !!!\n");
- return -1;
- }
- if (1 == pwrState) {
- sdio_claim_host(func);
- mmc_power_up_ext(func->card->host);
- sdio_release_host(func);
- HIF_SDIO_WARN_FUNC("SDIO BUS Power UP\n");
- } else {
- sdio_claim_host(func);
- mmc_power_off_ext(func->card->host);
- sdio_release_host(func);
- HIF_SDIO_WARN_FUNC("SDIO BUS Power OFF\n");
- }
- return 0;
- }
- EXPORT_SYMBOL(mtk_wcn_hif_sdio_bus_set_power);
- VOID mtk_wcn_hif_sdio_enable_irq(MTK_WCN_HIF_SDIO_CLTCTX ctx, MTK_WCN_BOOL enable)
- {
- UINT8 probed_idx = CLTCTX_IDX(ctx);
- if (unlikely(!CLTCTX_IDX_VALID(probed_idx))) { /* invalid index in CLTCTX */
- HIF_SDIO_WARN_FUNC("invalid idx in ctx(0x%x), sdio_irq no change\n", ctx);
- return;
- }
- if (unlikely(!CLTCTX_IDX_VALID(probed_idx))) { /* invalid index in CLTCTX */
- HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx);
- return;
- }
- /* store client driver's private data to dev driver */
- g_hif_sdio_probed_func_list[probed_idx].sdio_irq_enabled = enable;
- smp_wmb();
- HIF_SDIO_INFO_FUNC("ctx(0x%x) sdio irq enable(%d)\n",
- ctx, (MTK_WCN_BOOL_FALSE == enable) ? 0 : 1);
- }
- EXPORT_SYMBOL(mtk_wcn_hif_sdio_enable_irq);
- #if 0
- static INT32 _hif_sdio_is_autok_support(struct sdio_func *func)
- {
- INT32 iRet = -1;
- if ((0x037A == func->vendor) && (0x6630 == func->device) && (1 == func->num))
- iRet = 0;
- return iRet;
- }
- #endif
- static INT32 _hif_sdio_do_autok(struct sdio_func *func)
- {
- INT32 i_ret = 0;
- #if MTK_HIF_SDIO_AUTOK_ENABLED
- #if 0
- BOOTMODE boot_mode;
- boot_mode = get_boot_mode();
- if (boot_mode == META_BOOT) {
- HIF_SDIO_INFO_FUNC("omit autok in meta mode\n");
- i_ret = 0;
- return i_ret;
- }
- #endif
- HIF_SDIO_INFO_FUNC("wait_sdio_autok_ready++\n");
- wait_sdio_autok_ready(func->card->host);
- HIF_SDIO_INFO_FUNC("wait_sdio_autok_ready--\n");
- i_ret = 0;
- #else
- HIF_SDIO_ERR_FUNC("autok feature is not enabled.\n");
- #endif
- return i_ret;
- }
- INT32 mtk_wcn_hif_sdio_do_autok(MTK_WCN_HIF_SDIO_CLTCTX ctx)
- {
- INT32 i_ret = 0;
- UINT8 probe_index = 0;
- struct sdio_func *func = NULL;
- probe_index = CLTCTX_IDX(ctx);
- if (CFG_CLIENT_COUNT > probe_index)
- func = g_hif_sdio_probed_func_list[probe_index].func;
- else {
- HIF_SDIO_WARN_FUNC("probe_index is %d, out of range!\n", probe_index);
- return -1;
- }
- i_ret = _hif_sdio_do_autok(func);
- return i_ret;
- }
- EXPORT_SYMBOL(mtk_wcn_hif_sdio_do_autok);
- /*!
- * \brief
- *
- * detailed descriptions
- *
- * \param ctx client's context variable
- *
- * \retval 0 register successfully
- * \retval < 0 list error code here
- */
- INT32 mtk_wcn_hif_sdio_f0_readb(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT32 offset, PUINT8 pvb)
- {
- #if HIF_SDIO_UPDATE
- INT32 ret;
- struct sdio_func *func;
- #else
- INT32 ret = -HIF_SDIO_ERR_FAIL;
- INT32 probe_index = -1;
- struct sdio_func *func = 0;
- #endif
- HIF_SDIO_DBG_FUNC("start!\n");
- HIF_SDIO_ASSERT(pvb);
- /*4 <1> check if ctx is valid, registered, and probed */
- #if HIF_SDIO_UPDATE
- ret = -HIF_SDIO_ERR_FAIL;
- func = hif_sdio_ctx_to_func(ctx);
- if (!func) {
- ret = -HIF_SDIO_ERR_FAIL;
- goto out;
- }
- #else
- probe_index = CLTCTX_IDX(ctx);
- if (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */
- HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx);
- return -1;
- }
- if (probe_index < 0 || probe_index >= CFG_CLIENT_COUNT) { /* the function has not been probed */
- HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
- ret = -HIF_SDIO_ERR_FAIL;
- goto out;
- } else {
- if (g_hif_sdio_probed_func_list[probe_index].clt_idx < 0) { /* the client has not been registered */
- HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
- ret = -HIF_SDIO_ERR_FAIL;
- goto out;
- }
- }
- func = g_hif_sdio_probed_func_list[probe_index].func;
- #endif
- /*4 <2>*/
- sdio_claim_host(func);
- *pvb = sdio_f0_readb(func, offset, &ret);
- sdio_release_host(func);
- /*4 <3> check result code and return proper error code*/
- out:
- HIF_SDIO_DBG_FUNC("end!\n");
- return ret;
- } /* end of mtk_wcn_hif_sdio_f0_readb() */
- /*!
- * \brief
- *
- * detailed descriptions
- *
- * \param ctx client's context variable
- *
- * \retval 0register successfully
- * \retval < 0 list error code here
- */
- INT32 mtk_wcn_hif_sdio_f0_writeb(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT32 offset, UINT8 vb)
- {
- #if HIF_SDIO_UPDATE
- INT32 ret;
- struct sdio_func *func;
- #else
- INT32 ret = -HIF_SDIO_ERR_FAIL;
- INT32 probe_index = -1;
- struct sdio_func *func = 0;
- #endif
- HIF_SDIO_DBG_FUNC("start!\n");
- /*4 <1> check if ctx is valid, registered, and probed*/
- #if HIF_SDIO_UPDATE
- ret = -HIF_SDIO_ERR_FAIL;
- func = hif_sdio_ctx_to_func(ctx);
- if (!func) {
- ret = -HIF_SDIO_ERR_FAIL;
- goto out;
- }
- #else
- probe_index = CLTCTX_IDX(ctx);
- if (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */
- HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx);
- goto out;
- }
- if (probe_index < 0) { /* the function has not been probed */
- HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
- ret = -HIF_SDIO_ERR_FAIL;
- goto out;
- } else {
- if (g_hif_sdio_probed_func_list[probe_index].clt_idx < 0) { /* the client has not been registered */
- HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
- ret = -HIF_SDIO_ERR_FAIL;
- goto out;
- }
- }
- func = g_hif_sdio_probed_func_list[probe_index].func;
- #endif
- /*4 <1.1> check if input parameters are valid*/
- /*4 <2>*/
- wmt_tra_sdio_update();
- sdio_claim_host(func);
- sdio_f0_writeb(func, vb, offset, &ret);
- sdio_release_host(func);
- /*4 <3> check result code and return proper error code*/
- out:
- HIF_SDIO_DBG_FUNC("end!\n");
- return ret;
- } /* end of mtk_wcn_hif_sdio_f0_writeb() */
- INT32 mtk_wcn_hif_sdio_en_deep_sleep(MTK_WCN_HIF_SDIO_CLTCTX ctx)
- {
- return _hif_sdio_deep_sleep_ctrl(ctx, 1);
- } /* end of mtk_wcn_hif_sdio_deep_sleep() */
- EXPORT_SYMBOL(mtk_wcn_hif_sdio_en_deep_sleep);
- INT32 mtk_wcn_hif_sdio_dis_deep_sleep(MTK_WCN_HIF_SDIO_CLTCTX ctx)
- {
- return _hif_sdio_deep_sleep_ctrl(ctx, 0);
- } /* end of mtk_wcn_hif_sdio_wake_up() */
- EXPORT_SYMBOL(mtk_wcn_hif_sdio_dis_deep_sleep);
- #ifdef MTK_WCN_REMOVE_KERNEL_MODULE
- INT32 mtk_wcn_hif_sdio_drv_init(VOID)
- {
- return hif_sdio_init();
- }
- EXPORT_SYMBOL(mtk_wcn_hif_sdio_drv_init);
- VOID mtk_wcn_hif_sdio_driver_exit(VOID)
- {
- return hif_sdio_exit();
- }
- EXPORT_SYMBOL(mtk_wcn_hif_sdio_driver_exit);
- #else
- module_init(hif_sdio_init);
- module_exit(hif_sdio_exit);
- #endif
|