hif_sdio.c 80 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785
  1. /*
  2. *
  3. * 07 25 2010 george.kuo
  4. *
  5. * Move hif_sdio driver to linux directory.
  6. *
  7. * 07 23 2010 george.kuo
  8. *
  9. * Add MT6620 driver source tree
  10. * , including char device driver (wmt, bt, gps), stp driver,
  11. * interface driver (tty ldisc and hif_sdio), and bt hci driver.
  12. **
  13. **
  14. */
  15. /*******************************************************************************
  16. * C O M P I L E R F L A G S
  17. ********************************************************************************
  18. */
  19. #define HIF_SDIO_UPDATE (1)
  20. #define HIF_SDIO_SUPPORT_SUSPEND (1)
  21. #define HIF_SDIO_SUPPORT_WAKEUP (0)
  22. /*******************************************************************************
  23. * E X T E R N A L R E F E R E N C E S
  24. ********************************************************************************
  25. */
  26. #include <linux/proc_fs.h>
  27. #include "hif_sdio.h"
  28. #include "hif_sdio_chrdev.h"
  29. #if MTK_HIF_SDIO_AUTOK_ENABLED
  30. #include <mt_boot.h>
  31. #endif
  32. #define mmc_power_up_ext(x)
  33. #define mmc_power_off_ext(x)
  34. /*******************************************************************************
  35. * C O N S T A N T S
  36. ********************************************************************************
  37. */
  38. /* #define DRV_NAME "[hif_sdio]" */
  39. /*******************************************************************************
  40. * D A T A T Y P E S
  41. ********************************************************************************
  42. */
  43. /*******************************************************************************
  44. * M A C R O S
  45. ********************************************************************************
  46. */
  47. /*******************************************************************************
  48. * F U N C T I O N D E C L A R A T I O N S
  49. ********************************************************************************
  50. */
  51. #if HIF_SDIO_SUPPORT_SUSPEND
  52. static INT32 hif_sdio_suspend(struct device *dev);
  53. static INT32 hif_sdio_resume(struct device *dev);
  54. #endif
  55. static INT32 hif_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id);
  56. static VOID hif_sdio_remove(struct sdio_func *func);
  57. static VOID hif_sdio_irq(struct sdio_func *func);
  58. static INT32 hif_sdio_clt_probe_func(MTK_WCN_HIF_SDIO_REGISTINFO *registinfo_p, INT8 probe_idx);
  59. static VOID hif_sdio_clt_probe_worker(struct work_struct *work);
  60. static INT32 hif_sdio_find_probed_list_index_by_func(struct sdio_func *func);
  61. #if 0 /* TODO:[ChangeFeature][George] remove obsolete function? */
  62. static INT32 hif_sdio_find_probed_list_index_by_clt_index(INT32 clt_index);
  63. #endif
  64. static INT32 hif_sdio_find_probed_list_index_by_id_func(UINT16 vendor,
  65. UINT16 device, UINT16 func_num);
  66. static VOID hif_sdio_init_clt_list(INT32 index);
  67. static INT32 hif_sdio_find_clt_list_index(UINT16 vendor, UINT16 device, UINT16 func_num);
  68. static INT32 hif_sdio_check_supported_sdio_id(UINT16 vendor, UINT16 device);
  69. static INT32 hif_sdio_check_duplicate_sdio_id(UINT16 vendor, UINT16 device, UINT16 func_num);
  70. static INT32 hif_sdio_add_clt_list(PINT32 clt_index_p,
  71. const MTK_WCN_HIF_SDIO_CLTINFO *pinfo, UINT32 tbl_index);
  72. static INT32 hif_sdio_stp_on(VOID);
  73. static INT32 hif_sdio_stp_off(VOID);
  74. static INT32 hif_sdio_wifi_on(VOID);
  75. static INT32 hif_sdio_wifi_off(VOID);
  76. static INT32 _hif_sdio_do_autok(struct sdio_func *func);
  77. #if 0
  78. static INT32 _hif_sdio_is_autok_support(struct sdio_func *func);
  79. #endif
  80. static INT32 _hif_sdio_deep_sleep_info_init(VOID);
  81. static INT32 _hif_sdio_deep_sleep_info_set_act(UINT32 chipid,
  82. UINT16 func_num,
  83. MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT8 act_flag);
  84. static INT32 _hif_sdio_deep_sleep_ctrl(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT8 en_flag);
  85. /*******************************************************************************
  86. * P R I V A T E D A T A
  87. ********************************************************************************
  88. */
  89. /* Supported SDIO device table */
  90. static const struct sdio_device_id mtk_sdio_id_tbl[] = {
  91. /* MT6618 *//* Not an SDIO standard class device */
  92. {SDIO_DEVICE(0x037A, 0x018A)}, /* SDIO1:WIFI */
  93. {SDIO_DEVICE(0x037A, 0x018B)}, /* SDIO2:FUNC1:BT+FM */
  94. {SDIO_DEVICE(0x037A, 0x018C)}, /* 2-function (SDIO2:FUNC1:BT+FM, FUNC2:WIFI) */
  95. /* MT6619 *//* Not an SDIO standard class device */
  96. {SDIO_DEVICE(0x037A, 0x6619)}, /* SDIO2:FUNC1:BT+FM+GPS */
  97. /* MT6620 *//* Not an SDIO standard class device */
  98. {SDIO_DEVICE(0x037A, 0x020A)}, /* SDIO1:FUNC1:WIFI */
  99. {SDIO_DEVICE(0x037A, 0x020B)}, /* SDIO2:FUNC1:BT+FM+GPS */
  100. {SDIO_DEVICE(0x037A, 0x020C)}, /* 2-function (SDIO2:FUNC1:BT+FM+GPS, FUNC2:WIFI) */
  101. /* MT5921 *//* Not an SDIO standard class device */
  102. {SDIO_DEVICE(0x037A, 0x5921)},
  103. /* MT6628 *//* SDIO1: Wi-Fi, SDIO2: BGF */
  104. {SDIO_DEVICE(0x037A, 0x6628)},
  105. /* MT6630 *//* SDIO1: Wi-Fi, SDIO2: BGF */
  106. {SDIO_DEVICE(0x037A, 0x6630)},
  107. { /* end: all zeroes */ },
  108. };
  109. #if HIF_SDIO_SUPPORT_SUSPEND
  110. static const struct dev_pm_ops mtk_sdio_pmops = {
  111. .suspend = hif_sdio_suspend,
  112. .resume = hif_sdio_resume,
  113. };
  114. #endif
  115. static struct sdio_driver mtk_sdio_client_drv = {
  116. .name = "mtk_sdio_client", /* MTK SDIO Client Driver */
  117. .id_table = mtk_sdio_id_tbl, /* all supported struct sdio_device_id table */
  118. .probe = hif_sdio_probe,
  119. .remove = hif_sdio_remove,
  120. #if HIF_SDIO_SUPPORT_SUSPEND
  121. .drv = {
  122. .pm = &mtk_sdio_pmops,
  123. },
  124. #endif
  125. };
  126. /* Registered client driver list */
  127. /* static list g_hif_sdio_clt_drv_list */
  128. static MTK_WCN_HIF_SDIO_REGISTINFO g_hif_sdio_clt_drv_list[CFG_CLIENT_COUNT];
  129. /* MMC probed function list */
  130. /* static list g_hif_sdio_probed_func_list */
  131. static MTK_WCN_HIF_SDIO_PROBEINFO g_hif_sdio_probed_func_list[CFG_CLIENT_COUNT];
  132. /* spin lock info for g_hif_sdio_clt_drv_list and g_hif_sdio_probed_func_list */
  133. static MTK_WCN_HIF_SDIO_LOCKINFO g_hif_sdio_lock_info;
  134. /* reference count, debug information? */
  135. static INT32 gRefCount;
  136. static INT32 (*fp_wmt_tra_sdio_update)(VOID);
  137. static atomic_t hif_sdio_irq_enable_flag = ATOMIC_INIT(0);
  138. /*deep sleep related information*/
  139. MTK_WCN_HIF_SDIO_DS_INFO g_hif_sdio_ds_info_list[] = {
  140. {
  141. .chip_id = 0x6630,
  142. .reg_offset = 0xF1,
  143. .value = 0x1,
  144. },
  145. { /* end: all zeroes */ }
  146. };
  147. /*******************************************************************************
  148. * P U B L I C D A T A
  149. ********************************************************************************
  150. */
  151. MODULE_LICENSE("GPL");
  152. MODULE_AUTHOR("MediaTek Inc WCN_SE_CS3");
  153. MODULE_DESCRIPTION("MediaTek MT6620 HIF SDIO Driver");
  154. MODULE_DEVICE_TABLE(sdio, mtk_sdio_id_tbl);
  155. UINT32 gHifSdioDbgLvl = HIF_SDIO_LOG_INFO;
  156. /*******************************************************************************
  157. * F U N C T I O N S
  158. ********************************************************************************
  159. */
  160. INT32 __weak mtk_wcn_sdio_irq_flag_set(INT32 falg)
  161. {
  162. return 0;
  163. }
  164. INT32 mtk_wcn_hif_sdio_irq_flag_set(INT32 flag)
  165. {
  166. if (0 == flag) {
  167. atomic_dec(&hif_sdio_irq_enable_flag);
  168. if (0 == atomic_read(&hif_sdio_irq_enable_flag))
  169. mtk_wcn_sdio_irq_flag_set(0);
  170. } else {
  171. atomic_inc(&hif_sdio_irq_enable_flag);
  172. if (1 == atomic_read(&hif_sdio_irq_enable_flag))
  173. mtk_wcn_sdio_irq_flag_set(1);
  174. }
  175. return 0;
  176. }
  177. /*!
  178. * \brief register the callback funciton for record the timestamp of sdio access
  179. *
  180. * \param callback function
  181. *
  182. * \retval -EINVAL, when registered callback is invalid
  183. * \retval 0, when registered callback is valid
  184. */
  185. extern INT32 mtk_wcn_hif_sdio_update_cb_reg(INT32(*ts_update) (VOID))
  186. {
  187. if (ts_update) {
  188. fp_wmt_tra_sdio_update = ts_update;
  189. return 0;
  190. } else {
  191. return -EINVAL;
  192. }
  193. }
  194. EXPORT_SYMBOL(mtk_wcn_hif_sdio_update_cb_reg);
  195. /*!
  196. * \brief update the accessing time of SDIO via callback function
  197. *
  198. * \param void
  199. *
  200. * \retval -EINVAL, when callback is not registered
  201. * \retval returned value of callback
  202. */
  203. static INT32 wmt_tra_sdio_update(VOID)
  204. {
  205. if (fp_wmt_tra_sdio_update)
  206. return (*fp_wmt_tra_sdio_update) ();
  207. /* HIF_SDIO_WARN_FUNC("wmt_tra_sdio_update == NULL\n"); */
  208. return -EINVAL;
  209. }
  210. /*!
  211. * \brief Translate CLTCTX into a pointer to struct sdio_func if it is valid
  212. *
  213. * Translate a CLTCTX into a pointer to struct sdio_func if it is
  214. * 1) probed by mmc_core, and
  215. * 2) client driver is registered, and
  216. * 3) clt_idx of client driver is valid
  217. *
  218. * \param ctx a context provided by client driver
  219. *
  220. * \retval null if any condition is not valie
  221. * \retval a pointer to a struct sdio_func mapped by provided ctx
  222. */
  223. static _osal_inline_ struct sdio_func *hif_sdio_ctx_to_func(MTK_WCN_HIF_SDIO_CLTCTX ctx)
  224. {
  225. UINT32 probe_index;
  226. /* 4 <1> check if ctx is valid, registered, and probed */
  227. probe_index = CLTCTX_IDX(ctx);
  228. if (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */
  229. HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx);
  230. return NULL;
  231. }
  232. /* the client has not been registered */
  233. if (unlikely(g_hif_sdio_probed_func_list[probe_index].clt_idx < 0)) {
  234. HIF_SDIO_WARN_FUNC
  235. ("can't find client idx in probed list!ctx(0x%x) prob_idx(%d) clt_idx(%d)\n",
  236. ctx, probe_index, g_hif_sdio_probed_func_list[probe_index].clt_idx);
  237. return NULL;
  238. }
  239. return g_hif_sdio_probed_func_list[probe_index].func;
  240. }
  241. static INT32 _hif_sdio_deep_sleep_info_dmp(MTK_WCN_HIF_SDIO_DS_INFO *p_ds_info)
  242. {
  243. UINT32 i = 0;
  244. MTK_WCN_HIF_SDIO_DS_CLT_INFO *ctl_info = NULL;
  245. UINT32 ctl_info_array_size = ARRAY_SIZE(p_ds_info->clt_info);
  246. mutex_lock(&p_ds_info->lock);
  247. HIF_SDIO_INFO_FUNC("p_ds_info: 0x%08x, chipid:0x%x, reg_offset:0x%x, value:0x%x\n",
  248. p_ds_info, p_ds_info->chip_id, p_ds_info->reg_offset, p_ds_info->value);
  249. for (i = 0; i < ctl_info_array_size; i++) {
  250. ctl_info = &p_ds_info->clt_info[i];
  251. HIF_SDIO_INFO_FUNC
  252. ("ctl_info[%d]--ctx:0x%08x, func_num:%d, act_flag:%d, en_flag:%d\n", i,
  253. ctl_info->ctx, ctl_info->func_num, ctl_info->act_flag, ctl_info->ds_en_flag);
  254. }
  255. mutex_unlock(&p_ds_info->lock);
  256. return 0;
  257. }
  258. static INT32 _hif_sdio_deep_sleep_info_init(VOID)
  259. {
  260. UINT32 array_size = 0;
  261. UINT32 clt_info_size = 0;
  262. UINT32 i = 0;
  263. UINT32 j = 0;
  264. array_size = ARRAY_SIZE(g_hif_sdio_ds_info_list);
  265. /*set clt_info segment to 0 by default, when do stp/wifi on, write real information back */
  266. for (i = 0; i < array_size; i++) {
  267. mutex_init(&g_hif_sdio_ds_info_list[i].lock);
  268. clt_info_size = ARRAY_SIZE(g_hif_sdio_ds_info_list[i].clt_info);
  269. mutex_lock(&g_hif_sdio_ds_info_list[i].lock);
  270. for (j = 0; j < clt_info_size; j++)
  271. memset(&g_hif_sdio_ds_info_list[i].clt_info[j],
  272. 0, sizeof(MTK_WCN_HIF_SDIO_DS_CLT_INFO));
  273. mutex_unlock(&g_hif_sdio_ds_info_list[i].lock);
  274. _hif_sdio_deep_sleep_info_dmp(&g_hif_sdio_ds_info_list[i]);
  275. }
  276. return 0;
  277. }
  278. static INT32 _hif_sdio_deep_sleep_info_set_act(UINT32 chipid, UINT16 func_num,
  279. MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT8 act_flag)
  280. {
  281. UINT32 i = 0;
  282. UINT32 array_size = 0;
  283. UINT32 clt_info_size = 0;
  284. UINT32 idx = 0;
  285. MTK_WCN_HIF_SDIO_DS_CLT_INFO *p_ds_clt_info = NULL;
  286. array_size = ARRAY_SIZE(g_hif_sdio_ds_info_list);
  287. /*search write index */
  288. for (i = 0; i < array_size; i++) {
  289. if (g_hif_sdio_ds_info_list[i].chip_id == chipid)
  290. break;
  291. }
  292. if (i >= array_size) {
  293. HIF_SDIO_WARN_FUNC("no valid ds info found for 0x%x\n", chipid);
  294. return -1;
  295. }
  296. HIF_SDIO_DBG_FUNC("valid ds info found for 0x%x\n", chipid);
  297. clt_info_size = ARRAY_SIZE(g_hif_sdio_ds_info_list[i].clt_info);
  298. if (func_num > clt_info_size) {
  299. HIF_SDIO_WARN_FUNC("func num <%d> exceed max clt info size <%d>\n", func_num,
  300. clt_info_size);
  301. return -2;
  302. }
  303. idx = func_num - 1;
  304. p_ds_clt_info = &g_hif_sdio_ds_info_list[i].clt_info[idx];
  305. mutex_lock(&g_hif_sdio_ds_info_list[i].lock);
  306. p_ds_clt_info->func_num = func_num;
  307. p_ds_clt_info->ctx = ctx;
  308. p_ds_clt_info->act_flag = act_flag;
  309. p_ds_clt_info->ds_en_flag = 0;
  310. mutex_unlock(&g_hif_sdio_ds_info_list[i].lock);
  311. HIF_SDIO_INFO_FUNC("set act_flag to %d for ctx:0x%x whose chipid:0x%x, func_num:%d done\n",
  312. act_flag, ctx, chipid, func_num);
  313. /* _hif_sdio_deep_sleep_info_dmp(&g_hif_sdio_ds_info_list[0]); */
  314. return 0;
  315. }
  316. static INT32 _hif_sdio_deep_sleep_ctrl(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT8 en_flag)
  317. {
  318. UINT32 i = 0;
  319. UINT32 j = 0;
  320. INT32 ret = 0;
  321. UINT32 array_size = 0;
  322. UINT32 clt_info_size = 0;
  323. MTK_WCN_HIF_SDIO_DS_CLT_INFO *p_ds_clt_info = NULL;
  324. MTK_WCN_HIF_SDIO_DS_INFO *p_ds_info = NULL;
  325. UINT8 do_ds_op_flag = 0;
  326. array_size = ARRAY_SIZE(g_hif_sdio_ds_info_list);
  327. /*search write index */
  328. for (i = 0; i < array_size; i++) {
  329. mutex_lock(&g_hif_sdio_ds_info_list[i].lock);
  330. /* _hif_sdio_deep_sleep_info_dmp(&g_hif_sdio_ds_info_list[i]); */
  331. clt_info_size = ARRAY_SIZE(g_hif_sdio_ds_info_list[i].clt_info);
  332. for (j = 0; j < clt_info_size; j++) {
  333. if (g_hif_sdio_ds_info_list[i].clt_info[j].ctx == ctx) {
  334. do_ds_op_flag = 1;
  335. break;
  336. }
  337. }
  338. if (0 != do_ds_op_flag)
  339. break;
  340. mutex_unlock(&g_hif_sdio_ds_info_list[i].lock);
  341. }
  342. if ((i >= array_size) || (j >= clt_info_size)) {
  343. HIF_SDIO_DBG_FUNC("no valid ds info found for ctx 0x%08x\n, en_flag:%d", ctx,
  344. en_flag);
  345. return -1;
  346. }
  347. HIF_SDIO_DBG_FUNC("valid ds info found for ctx 0x%08x, en_flag:%d\n", ctx, en_flag);
  348. p_ds_info = &g_hif_sdio_ds_info_list[i];
  349. p_ds_clt_info = &p_ds_info->clt_info[j];
  350. if (0 != p_ds_clt_info->act_flag)
  351. p_ds_clt_info->ds_en_flag = en_flag;
  352. else
  353. HIF_SDIO_DBG_FUNC("!!!!!----this case should never happen----!!!!!\n");
  354. /*check if deep sleep operation is needed or not */
  355. do_ds_op_flag = 1;
  356. for (j = 0; j < clt_info_size; j++) {
  357. if ((p_ds_info->clt_info[j].ds_en_flag == 0)
  358. && (p_ds_info->clt_info[j].act_flag == 1)) {
  359. do_ds_op_flag = 0;
  360. break;
  361. }
  362. }
  363. if (0 != do_ds_op_flag) {
  364. #if 0
  365. ret = mtk_wcn_hif_sdio_f0_writeb(ctx, p_ds_info->reg_offset, p_ds_info->value);
  366. if (0 == ret) {
  367. func = hif_sdio_ctx_to_func(ctx);
  368. HIF_SDIO_DBG_FUNC("msdc_sdio_deep_sleep++\n");
  369. msdc_sdio_deep_sleep(func->card->host, 0);
  370. HIF_SDIO_DBG_FUNC("msdc_sdio_deep_sleep--\n");
  371. HIF_SDIO_DBG_FUNC
  372. ("write deep sleep register:0x%x with value:0x%x succeed\n",
  373. p_ds_info->reg_offset, p_ds_info->value);
  374. } else {
  375. HIF_SDIO_ERR_FUNC("write deep sleep register:0x%x with value:0x%x failed\n",
  376. p_ds_info->reg_offset, p_ds_info->value);
  377. }
  378. #endif
  379. } else {
  380. HIF_SDIO_DBG_FUNC("no need to do deep sleep operation\n");
  381. }
  382. mutex_unlock(&g_hif_sdio_ds_info_list[i].lock);
  383. return ret;
  384. }
  385. /*!
  386. * \brief MTK hif sdio client registration function
  387. *
  388. * Client uses this function to register itself to hif_sdio driver
  389. *
  390. * \param pinfo a pointer of client's information
  391. *
  392. * \retval 0 register successfully
  393. * \retval < 0 list error code here
  394. */
  395. INT32 mtk_wcn_hif_sdio_client_reg(const MTK_WCN_HIF_SDIO_CLTINFO *pinfo)
  396. {
  397. INT32 ret = -HIF_SDIO_ERR_FAIL;
  398. INT32 clt_index = -1;
  399. UINT32 i = 0;
  400. UINT32 j = 0;
  401. MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_probe_worker_info = 0;
  402. HIF_SDIO_INFO_FUNC("start!\n");
  403. /* 4 <1> check input pointer is valid */
  404. HIF_SDIO_ASSERT(pinfo);
  405. /* 4 <2> check if input parameters are all supported and valid */
  406. for (i = 0; i < pinfo->func_tbl_size; i++) {
  407. ret =
  408. hif_sdio_check_supported_sdio_id(pinfo->func_tbl[i].manf_id,
  409. pinfo->func_tbl[i].card_id);
  410. if (ret) {
  411. HIF_SDIO_WARN_FUNC
  412. ("vendor id(0x%x) and device id(0x%x) of sdio_func are not supported!\n",
  413. pinfo->func_tbl[i].manf_id, pinfo->func_tbl[i].card_id);
  414. goto out;
  415. }
  416. }
  417. HIF_SDIO_DBG_FUNC("hif_sdio_check_supported_sdio_id() done!\n");
  418. /* 4 <3> check if the specific {manf id, card id, function number} tuple is */
  419. /* 4 already resigstered */
  420. for (i = 0; i < pinfo->func_tbl_size; i++) {
  421. ret =
  422. hif_sdio_check_duplicate_sdio_id(pinfo->func_tbl[i].manf_id,
  423. pinfo->func_tbl[i].card_id,
  424. pinfo->func_tbl[i].func_num);
  425. if (ret) {
  426. HIF_SDIO_WARN_FUNC("vendor id(0x%x), device id(0x%x), and fun_num(%d) of\n",
  427. pinfo->func_tbl[i].manf_id, pinfo->func_tbl[i].card_id,
  428. pinfo->func_tbl[i].func_num);
  429. HIF_SDIO_WARN_FUNC("sdio_func are duplicated in g_hif_sdio_clt_drv_list!\n");
  430. goto out;
  431. }
  432. }
  433. HIF_SDIO_DBG_FUNC("hif_sdio_check_duplicate_sdio_id() done!\n");
  434. /* 4 <4> add the specified {manf id, card id, function number}
  435. * tuple to registered client list */
  436. HIF_SDIO_DBG_FUNC("pinfo->func_tbl_size:%d\n", pinfo->func_tbl_size);
  437. for (i = 0; i < pinfo->func_tbl_size; i++) {
  438. ret = hif_sdio_add_clt_list(&clt_index, pinfo, i);
  439. if (ret) {
  440. HIF_SDIO_WARN_FUNC
  441. ("client's info are added in registed client list failed (buffer is full)!\n");
  442. goto out;
  443. }
  444. HIF_SDIO_DBG_FUNC("hif_sdio_add_clt_list() done (gRefCount=%d)!\n", gRefCount);
  445. /* 4 <5> if the specific {manf id, card id, function number} tuple has already */
  446. /* 4 been probed by mmc, schedule another task to call client's .hif_clt_probe() */
  447. for (j = 0; j < CFG_CLIENT_COUNT; j++) {
  448. /* probed spin lock */
  449. spin_lock_bh(&g_hif_sdio_lock_info.probed_list_lock);
  450. if (g_hif_sdio_probed_func_list[j].func == 0) {
  451. /* probed spin unlock */
  452. spin_unlock_bh(&g_hif_sdio_lock_info.probed_list_lock);
  453. continue;
  454. }
  455. /* the function has been probed */
  456. if ((g_hif_sdio_clt_drv_list[clt_index].func_info->manf_id ==
  457. g_hif_sdio_probed_func_list[j].func->vendor)
  458. && (g_hif_sdio_clt_drv_list[clt_index].func_info->card_id ==
  459. g_hif_sdio_probed_func_list[j].func->device)
  460. && (g_hif_sdio_clt_drv_list[clt_index].func_info->func_num ==
  461. g_hif_sdio_probed_func_list[j].func->num)) {
  462. g_hif_sdio_probed_func_list[j].clt_idx = clt_index;
  463. /* probed spin unlock */
  464. spin_unlock_bh(&g_hif_sdio_lock_info.probed_list_lock);
  465. /* use worker thread to perform the client's .hif_clt_probe() */
  466. clt_probe_worker_info =
  467. vmalloc(sizeof(MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO));
  468. if (clt_probe_worker_info) {
  469. INIT_WORK(&clt_probe_worker_info->probe_work,
  470. hif_sdio_clt_probe_worker);
  471. clt_probe_worker_info->registinfo_p =
  472. &g_hif_sdio_clt_drv_list[clt_index];
  473. clt_probe_worker_info->probe_idx = j;
  474. schedule_work(&clt_probe_worker_info->probe_work);
  475. }
  476. /* 4 <5.1> remember to do claim_irq for the func if it's irq had been released. */
  477. if (!(g_hif_sdio_probed_func_list[j].func->irq_handler)) {
  478. sdio_claim_host(g_hif_sdio_probed_func_list[j].func);
  479. ret =
  480. sdio_claim_irq(g_hif_sdio_probed_func_list[j].func,
  481. hif_sdio_irq);
  482. mtk_wcn_hif_sdio_irq_flag_set(1);
  483. sdio_release_host(g_hif_sdio_probed_func_list[j].func);
  484. HIF_SDIO_INFO_FUNC
  485. ("sdio_claim_irq for func(0x%p) j(%d) v(0x%x) d(0x%x) ok\n",
  486. g_hif_sdio_probed_func_list[j].func, j,
  487. g_hif_sdio_probed_func_list[j].func->vendor,
  488. g_hif_sdio_probed_func_list[j].func->device);
  489. }
  490. /* 4 <5.2> Reset the block size of the function provided by client */
  491. HIF_SDIO_INFO_FUNC("Reset sdio block size: %d!\n",
  492. g_hif_sdio_clt_drv_list[clt_index].
  493. func_info->blk_sz);
  494. sdio_claim_host(g_hif_sdio_probed_func_list[j].func);
  495. ret = sdio_set_block_size(g_hif_sdio_probed_func_list[j].func,
  496. g_hif_sdio_clt_drv_list
  497. [clt_index].func_info->blk_sz);
  498. sdio_release_host(g_hif_sdio_probed_func_list[j].func);
  499. } else {
  500. /* probed spin unlock */
  501. spin_unlock_bh(&g_hif_sdio_lock_info.probed_list_lock);
  502. }
  503. }
  504. HIF_SDIO_DBG_FUNC
  505. ("map g_hif_sdio_clt_drv_list to g_hif_sdio_probed_func_list done!\n");
  506. }
  507. ret = HIF_SDIO_ERR_SUCCESS;
  508. gRefCount++;
  509. out:
  510. /* 4 <last> error handling */
  511. HIF_SDIO_DBG_FUNC("end!\n");
  512. return ret;
  513. } /* end of mtk_wcn_hif_sdio_client_reg() */
  514. EXPORT_SYMBOL(mtk_wcn_hif_sdio_client_reg);
  515. /*!
  516. * \brief MTK hif sdio client un-registration function
  517. *
  518. * Client uses this function to un-register itself
  519. *
  520. * \param pinfo a pointer of client's information
  521. *
  522. * \retval 0 register successfully
  523. * \retval < 0 list error code here
  524. */
  525. INT32 mtk_wcn_hif_sdio_client_unreg(const MTK_WCN_HIF_SDIO_CLTINFO *pinfo)
  526. {
  527. INT32 ret = -HIF_SDIO_ERR_FAIL;
  528. INT32 clt_list_index = 0;
  529. UINT32 i = 0;
  530. UINT32 j = 0;
  531. HIF_SDIO_INFO_FUNC("start!\n");
  532. /* 4 <1> check if input pointer is valid */
  533. HIF_SDIO_ASSERT(pinfo);
  534. /* 4 <2> check if input parameters are all supported and valid */
  535. for (i = 0; i < pinfo->func_tbl_size; i++) {
  536. ret =
  537. hif_sdio_check_supported_sdio_id(pinfo->func_tbl[i].manf_id,
  538. pinfo->func_tbl[i].card_id);
  539. if (ret) {
  540. HIF_SDIO_WARN_FUNC
  541. ("vendor id(0x%x) and device id(0x%x) of sdio_func are not supported in mtk_sdio_id_tbl!\n",
  542. pinfo->func_tbl[i].manf_id, pinfo->func_tbl[i].card_id);
  543. goto out;
  544. }
  545. }
  546. /* 4 <3> check if the specific {manf id, card id, function number} tuple is already resigstered */
  547. /* 4 and find the corresponding client ctx and call client's .hif_clt_remove() in THIS context */
  548. for (i = 0; i < pinfo->func_tbl_size; i++) {
  549. clt_list_index =
  550. hif_sdio_find_clt_list_index(pinfo->func_tbl[i].manf_id,
  551. pinfo->func_tbl[i].card_id,
  552. pinfo->func_tbl[i].func_num);
  553. if (clt_list_index < 0) {
  554. HIF_SDIO_WARN_FUNC("vendor id(0x%x),", pinfo->func_tbl[i].manf_id);
  555. HIF_SDIO_WARN_FUNC(" device id(0x%x),", pinfo->func_tbl[i].card_id);
  556. HIF_SDIO_WARN_FUNC(" and fun_num(%d)", pinfo->func_tbl[i].func_num);
  557. HIF_SDIO_WARN_FUNC(" client info is not in the client's registed list!\n");
  558. ret = -HIF_SDIO_ERR_FAIL;
  559. goto out;
  560. }
  561. /* 4 <4> mark the specified {manf id, card id, function number} tuple as */
  562. /* 4 un-registered and invalidate client's context */
  563. hif_sdio_init_clt_list(clt_list_index);
  564. /* un-map g_hif_sdio_clt_drv_list index in g_hif_sdio_probed_func_list */
  565. for (j = 0; j < CFG_CLIENT_COUNT; j++) {
  566. if (g_hif_sdio_probed_func_list[j].clt_idx == clt_list_index)
  567. g_hif_sdio_probed_func_list[j].clt_idx = -1;
  568. }
  569. }
  570. gRefCount--;
  571. ret = HIF_SDIO_ERR_SUCCESS;
  572. out:
  573. HIF_SDIO_INFO_FUNC("end (gRefCount=%d) !\n", gRefCount);
  574. return ret;
  575. } /* end of mtk_wcn_hif_sdio_client_unreg() */
  576. EXPORT_SYMBOL(mtk_wcn_hif_sdio_client_unreg);
  577. /*!
  578. * \brief
  579. *
  580. * detailed descriptions
  581. *
  582. * \param ctx client's context variable
  583. *
  584. * \retval 0 register successfully
  585. * \retval < 0 list error code here
  586. */
  587. INT32 mtk_wcn_hif_sdio_readb(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT32 offset, PUINT8 pvb)
  588. {
  589. #if HIF_SDIO_UPDATE
  590. INT32 ret;
  591. struct sdio_func *func;
  592. #else
  593. INT32 ret = -HIF_SDIO_ERR_FAIL;
  594. int probe_index = -1;
  595. struct sdio_func *func = 0;
  596. #endif
  597. HIF_SDIO_DBG_FUNC("start!\n");
  598. HIF_SDIO_ASSERT(pvb);
  599. /* 4 <1> check if ctx is valid, registered, and probed */
  600. #if HIF_SDIO_UPDATE
  601. ret = -HIF_SDIO_ERR_FAIL;
  602. func = hif_sdio_ctx_to_func(ctx);
  603. if (!func) {
  604. ret = -HIF_SDIO_ERR_FAIL;
  605. goto out;
  606. }
  607. #else
  608. probe_index = CLTCTX_IDX(ctx);
  609. if (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */
  610. HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx);
  611. goto out;
  612. }
  613. if (probe_index < 0 || probe_index >= CFG_CLIENT_COUNT) { /* the function has not been probed */
  614. HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
  615. ret = -HIF_SDIO_ERR_FAIL;
  616. goto out;
  617. } else {
  618. if (g_hif_sdio_probed_func_list[probe_index].clt_idx < 0) { /* the client has not been registered */
  619. HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
  620. ret = -HIF_SDIO_ERR_FAIL;
  621. goto out;
  622. }
  623. }
  624. func = g_hif_sdio_probed_func_list[probe_index].func;
  625. #endif
  626. /* 4 <2> */
  627. sdio_claim_host(func);
  628. *pvb = sdio_readb(func, offset, &ret);
  629. sdio_release_host(func);
  630. /* 4 <3> check result code and return proper error code */
  631. out:
  632. HIF_SDIO_DBG_FUNC("end!\n");
  633. return ret;
  634. } /* end of mtk_wcn_hif_sdio_client_unreg() */
  635. EXPORT_SYMBOL(mtk_wcn_hif_sdio_readb);
  636. /*!
  637. * \brief
  638. *
  639. * detailed descriptions
  640. *
  641. * \param ctx client's context variable
  642. *
  643. * \retval 0 register successfully
  644. * \retval < 0 list error code here
  645. */
  646. INT32 mtk_wcn_hif_sdio_writeb(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT32 offset, UINT8 vb)
  647. {
  648. #if HIF_SDIO_UPDATE
  649. INT32 ret;
  650. struct sdio_func *func;
  651. #else
  652. INT32 ret = -HIF_SDIO_ERR_FAIL;
  653. INT32 probe_index = -1;
  654. struct sdio_func *func = 0;
  655. #endif
  656. HIF_SDIO_DBG_FUNC("start!\n");
  657. /* 4 <1> check if ctx is valid, registered, and probed */
  658. #if HIF_SDIO_UPDATE
  659. ret = -HIF_SDIO_ERR_FAIL;
  660. func = hif_sdio_ctx_to_func(ctx);
  661. if (!func) {
  662. ret = -HIF_SDIO_ERR_FAIL;
  663. goto out;
  664. }
  665. #else
  666. probe_index = CLTCTX_IDX(ctx);
  667. if (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */
  668. HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx);
  669. goto out;
  670. }
  671. if (probe_index < 0 || probe_index >= CFG_CLIENT_COUNT) { /* 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;
  674. goto out;
  675. } else {
  676. if (g_hif_sdio_probed_func_list[probe_index].clt_idx < 0) { /* the client has not been registered */
  677. HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
  678. ret = -HIF_SDIO_ERR_FAIL;
  679. goto out;
  680. }
  681. }
  682. func = g_hif_sdio_probed_func_list[probe_index].func;
  683. #endif
  684. /* 4 <1.1> check if input parameters are valid */
  685. /* 4 <2> */
  686. wmt_tra_sdio_update();
  687. sdio_claim_host(func);
  688. sdio_writeb(func, vb, offset, &ret);
  689. sdio_release_host(func);
  690. /* 4 <3> check result code and return proper error code */
  691. out:
  692. HIF_SDIO_DBG_FUNC("end!\n");
  693. return ret;
  694. } /* end of mtk_wcn_hif_sdio_client_unreg() */
  695. EXPORT_SYMBOL(mtk_wcn_hif_sdio_writeb);
  696. /*!
  697. * \brief
  698. *
  699. * detailed descriptions
  700. *
  701. * \param ctx client's context variable
  702. *
  703. * \retval 0 register successfully
  704. * \retval < 0 list error code here
  705. */
  706. INT32 mtk_wcn_hif_sdio_readl(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT32 offset, PUINT32 pvl)
  707. {
  708. #if HIF_SDIO_UPDATE
  709. INT32 ret;
  710. struct sdio_func *func;
  711. #else
  712. INT32 ret = -HIF_SDIO_ERR_FAIL;
  713. INT32 probe_index = -1;
  714. struct sdio_func *func = 0;
  715. #endif
  716. HIF_SDIO_DBG_FUNC("start!\n");
  717. HIF_SDIO_ASSERT(pvl);
  718. /* 4 <1> check if ctx is valid, registered, and probed */
  719. #if HIF_SDIO_UPDATE
  720. ret = -HIF_SDIO_ERR_FAIL;
  721. func = hif_sdio_ctx_to_func(ctx);
  722. if (!func) {
  723. ret = -HIF_SDIO_ERR_FAIL;
  724. goto out;
  725. }
  726. #else
  727. probe_index = CLTCTX_IDX(ctx);
  728. if (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */
  729. HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx);
  730. goto out;
  731. }
  732. if (probe_index < 0 || probe_index >= CFG_CLIENT_COUNT) { /* the function has not been probed */
  733. HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
  734. ret = -HIF_SDIO_ERR_FAIL;
  735. goto out;
  736. } else {
  737. if (g_hif_sdio_probed_func_list[probe_index].clt_idx < 0) { /* the client has not been registered */
  738. HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
  739. ret = -HIF_SDIO_ERR_FAIL;
  740. goto out;
  741. }
  742. }
  743. func = g_hif_sdio_probed_func_list[probe_index].func;
  744. #endif
  745. /* 4 <1.1> check if input parameters are valid */
  746. /* 4 <2> */
  747. sdio_claim_host(func);
  748. *pvl = sdio_readl(func, offset, &ret);
  749. sdio_release_host(func);
  750. /* 4 <3> check result code and return proper error code */
  751. out:
  752. HIF_SDIO_DBG_FUNC("end!\n");
  753. return ret;
  754. } /* end of mtk_wcn_hif_sdio_client_unreg() */
  755. EXPORT_SYMBOL(mtk_wcn_hif_sdio_readl);
  756. /*!
  757. * \brief
  758. *
  759. * detailed descriptions
  760. *
  761. * \param ctx client's context variable
  762. *
  763. * \retval 0 register successfully
  764. * \retval < 0 list error code here
  765. */
  766. INT32 mtk_wcn_hif_sdio_writel(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT32 offset, UINT32 vl)
  767. {
  768. #if HIF_SDIO_UPDATE
  769. INT32 ret;
  770. struct sdio_func *func;
  771. #else
  772. INT32 ret = -HIF_SDIO_ERR_FAIL;
  773. INT32 probe_index = -1;
  774. struct sdio_func *func = 0;
  775. #endif
  776. HIF_SDIO_DBG_FUNC("start!\n");
  777. /* 4 <1> check if ctx is valid, registered, and probed */
  778. #if HIF_SDIO_UPDATE
  779. ret = -HIF_SDIO_ERR_FAIL;
  780. func = hif_sdio_ctx_to_func(ctx);
  781. if (!func) {
  782. ret = -HIF_SDIO_ERR_FAIL;
  783. goto out;
  784. }
  785. #else
  786. probe_index = CLTCTX_IDX(ctx);
  787. if (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */
  788. HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx);
  789. goto out;
  790. }
  791. if (probe_index < 0 || probe_index >= CFG_CLIENT_COUNT) { /* the function has not been probed */
  792. HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
  793. ret = -HIF_SDIO_ERR_FAIL;
  794. goto out;
  795. } else {
  796. if (g_hif_sdio_probed_func_list[probe_index].clt_idx < 0) { /* the client has not been registered */
  797. HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
  798. ret = -HIF_SDIO_ERR_FAIL;
  799. goto out;
  800. }
  801. }
  802. func = g_hif_sdio_probed_func_list[probe_index].func;
  803. #endif
  804. /* 4 <1.1> check if input parameters are valid */
  805. /* 4 <2> */
  806. wmt_tra_sdio_update();
  807. sdio_claim_host(func);
  808. sdio_writel(func, vl, offset, &ret);
  809. sdio_release_host(func);
  810. /* 4 <3> check result code and return proper error code */
  811. out:
  812. HIF_SDIO_DBG_FUNC("end!\n");
  813. return ret;
  814. } /* end of mtk_wcn_hif_sdio_client_unreg() */
  815. EXPORT_SYMBOL(mtk_wcn_hif_sdio_writel);
  816. /*!
  817. * \brief
  818. *
  819. * detailed descriptions
  820. *
  821. * \param ctx client's context variable
  822. *
  823. * \retval 0 register successfully
  824. * \retval < 0 list error code here
  825. */
  826. INT32 mtk_wcn_hif_sdio_read_buf(MTK_WCN_HIF_SDIO_CLTCTX ctx,
  827. UINT32 offset, PUINT32 pbuf, UINT32 len)
  828. {
  829. #if HIF_SDIO_UPDATE
  830. INT32 ret;
  831. struct sdio_func *func;
  832. #else
  833. INT32 ret = -HIF_SDIO_ERR_FAIL;
  834. INT32 probe_index = -1;
  835. struct sdio_func *func = 0;
  836. #endif
  837. HIF_SDIO_DBG_FUNC("start!\n");
  838. HIF_SDIO_ASSERT(pbuf);
  839. /* 4 <1> check if ctx is valid, registered, and probed */
  840. #if HIF_SDIO_UPDATE
  841. ret = -HIF_SDIO_ERR_FAIL;
  842. func = hif_sdio_ctx_to_func(ctx);
  843. if (!func) {
  844. ret = -HIF_SDIO_ERR_FAIL;
  845. goto out;
  846. }
  847. #else
  848. probe_index = CLTCTX_IDX(ctx);
  849. if (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */
  850. HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx);
  851. goto out;
  852. }
  853. if (probe_index < 0 || probe_index >= CFG_CLIENT_COUNT) { /* the function has not been probed */
  854. HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
  855. ret = -HIF_SDIO_ERR_FAIL;
  856. goto out;
  857. } else {
  858. if (g_hif_sdio_probed_func_list[probe_index].clt_idx < 0) { /* the client has not been registered */
  859. HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
  860. ret = -HIF_SDIO_ERR_FAIL;
  861. goto out;
  862. }
  863. }
  864. func = g_hif_sdio_probed_func_list[probe_index].func;
  865. #endif
  866. /* 4 <1.1> check if input parameters are valid */
  867. /* 4 <2> */
  868. sdio_claim_host(func);
  869. ret = sdio_readsb(func, pbuf, offset, len);
  870. sdio_release_host(func);
  871. /* 4 <3> check result code and return proper error code */
  872. out:
  873. HIF_SDIO_DBG_FUNC("end!\n");
  874. return ret;
  875. } /* end of mtk_wcn_hif_sdio_read_buf() */
  876. EXPORT_SYMBOL(mtk_wcn_hif_sdio_read_buf);
  877. /*!
  878. * \brief
  879. *
  880. * detailed descriptions
  881. *
  882. * \param ctx client's context variable
  883. *
  884. * \retval 0 register successfully
  885. * \retval < 0 list error code here
  886. */
  887. INT32 mtk_wcn_hif_sdio_write_buf(MTK_WCN_HIF_SDIO_CLTCTX ctx,
  888. UINT32 offset, PUINT32 pbuf, UINT32 len)
  889. {
  890. #if HIF_SDIO_UPDATE
  891. INT32 ret;
  892. struct sdio_func *func;
  893. #else
  894. INT32 ret = -HIF_SDIO_ERR_FAIL;
  895. INT32 probe_index = -1;
  896. struct sdio_func *func = 0;
  897. #endif
  898. HIF_SDIO_DBG_FUNC("start!\n");
  899. HIF_SDIO_ASSERT(pbuf);
  900. /* 4 <1> check if ctx is valid, registered, and probed */
  901. #if HIF_SDIO_UPDATE
  902. ret = -HIF_SDIO_ERR_FAIL;
  903. func = hif_sdio_ctx_to_func(ctx);
  904. if (!func) {
  905. ret = -HIF_SDIO_ERR_FAIL;
  906. goto out;
  907. }
  908. #else
  909. probe_index = CLTCTX_IDX(ctx);
  910. if (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */
  911. HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx);
  912. goto out;
  913. }
  914. if (probe_index < 0 || probe_index >= CFG_CLIENT_COUNT) { /* the function has not been probed */
  915. HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
  916. ret = -HIF_SDIO_ERR_FAIL;
  917. goto out;
  918. } else {
  919. if (g_hif_sdio_probed_func_list[probe_index].clt_idx < 0) { /* the client has not been registered */
  920. HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
  921. ret = -HIF_SDIO_ERR_FAIL;
  922. goto out;
  923. }
  924. }
  925. func = g_hif_sdio_probed_func_list[probe_index].func;
  926. #endif
  927. /* 4 <1.1> check if input parameters are valid */
  928. /* 4 <2> */
  929. wmt_tra_sdio_update();
  930. sdio_claim_host(func);
  931. ret = sdio_writesb(func, offset, pbuf, len);
  932. sdio_release_host(func);
  933. /* 4 <3> check result code and return proper error code */
  934. out:
  935. HIF_SDIO_DBG_FUNC("ret(%d) end!\n", ret);
  936. return ret;
  937. } /* end of mtk_wcn_hif_sdio_write_buf() */
  938. EXPORT_SYMBOL(mtk_wcn_hif_sdio_write_buf);
  939. /*!
  940. * \brief store client driver's private data function.
  941. *
  942. *
  943. * \param clent's MTK_WCN_HIF_SDIO_CLTCTX.
  944. *
  945. * \retval none.
  946. */
  947. VOID mtk_wcn_hif_sdio_set_drvdata(MTK_WCN_HIF_SDIO_CLTCTX ctx, PVOID private_data_p)
  948. {
  949. UINT8 probed_idx = CLTCTX_IDX(ctx);
  950. if (unlikely(!CLTCTX_IDX_VALID(probed_idx))) { /* invalid index in CLTCTX */
  951. HIF_SDIO_WARN_FUNC("invalid idx in ctx(0x%x), private_data_p not stored!\n", ctx);
  952. } else {
  953. /* store client driver's private data to dev driver */
  954. g_hif_sdio_probed_func_list[probed_idx].private_data_p = private_data_p;
  955. HIF_SDIO_DBG_FUNC("private_data_p(0x%p) for ctx(0x%x) probed idx(%d) stored!\n",
  956. private_data_p, ctx, probed_idx);
  957. }
  958. }
  959. EXPORT_SYMBOL(mtk_wcn_hif_sdio_set_drvdata);
  960. /*!
  961. * \brief get client driver's private data function.
  962. *
  963. *
  964. * \param clent's MTK_WCN_HIF_SDIO_CLTCTX.
  965. *
  966. * \retval private data pointer.
  967. */
  968. PVOID mtk_wcn_hif_sdio_get_drvdata(MTK_WCN_HIF_SDIO_CLTCTX ctx)
  969. {
  970. UINT8 probed_idx = CLTCTX_IDX(ctx);
  971. /* get client driver's private data to dev driver */
  972. if (likely(CLTCTX_IDX_VALID(probed_idx)))
  973. return g_hif_sdio_probed_func_list[probed_idx].private_data_p;
  974. /* invalid index in CLTCTX */
  975. HIF_SDIO_WARN_FUNC("invalid idx in ctx(0x%x), return null!\n", ctx);
  976. return NULL;
  977. }
  978. EXPORT_SYMBOL(mtk_wcn_hif_sdio_get_drvdata);
  979. /*!
  980. * \brief control stp/wifi on/off from wmt.
  981. *
  982. *
  983. * \param (1)control function type, (2)on/off control.
  984. *
  985. * \retval (1)control results ,(2)unknown type: -5.
  986. * \retval 0:success, -11:not probed, -12:already on, -13:not registered, other errors.
  987. */
  988. INT32 mtk_wcn_hif_sdio_wmt_control(WMT_SDIO_FUNC_TYPE func_type, MTK_WCN_BOOL is_on)
  989. {
  990. /* TODO:[FixMe][George]: return value of this function shall distinguish */
  991. /* 1) not probed by mmc_core yet or */
  992. /* 2) probed by mmc_core but init fail... */
  993. switch (func_type) {
  994. case WMT_SDIO_FUNC_STP:
  995. if (is_on == MTK_WCN_BOOL_TRUE)
  996. return hif_sdio_stp_on();
  997. else
  998. return hif_sdio_stp_off();
  999. break;
  1000. case WMT_SDIO_FUNC_WIFI:
  1001. if (is_on == MTK_WCN_BOOL_TRUE)
  1002. return hif_sdio_wifi_on();
  1003. else
  1004. return hif_sdio_wifi_off();
  1005. break;
  1006. default:
  1007. HIF_SDIO_WARN_FUNC("unknown type(%d)\n", func_type);
  1008. return HIF_SDIO_ERR_INVALID_PARAM;
  1009. }
  1010. }
  1011. EXPORT_SYMBOL(mtk_wcn_hif_sdio_wmt_control);
  1012. /*!
  1013. * \brief ???
  1014. *
  1015. * \detail ???
  1016. *
  1017. * \param ctx a context provided by client driver
  1018. * \param struct device ** ???
  1019. *
  1020. * \retval none
  1021. */
  1022. VOID mtk_wcn_hif_sdio_get_dev(MTK_WCN_HIF_SDIO_CLTCTX ctx, struct device **dev)
  1023. {
  1024. #if HIF_SDIO_UPDATE
  1025. struct sdio_func *func;
  1026. #else
  1027. UINT8 probe_index = CLTCTX_IDX(ctx);
  1028. #endif
  1029. #if HIF_SDIO_UPDATE
  1030. *dev = NULL; /* ensure we does not return any invalid value back. */
  1031. func = hif_sdio_ctx_to_func(ctx);
  1032. if (unlikely(!func)) {
  1033. HIF_SDIO_WARN_FUNC("no valid *func with ctx(0x%x)\n", ctx);
  1034. return;
  1035. }
  1036. *dev = &(func->dev);
  1037. HIF_SDIO_DBG_FUNC("return *dev(0x%p) for ctx(0x%x)\n", *dev, ctx);
  1038. #else
  1039. if (probe_index < 0) {
  1040. HIF_SDIO_WARN_FUNC("func not probed, probe_index = %d", probe_index);
  1041. return;
  1042. }
  1043. *dev = &g_hif_sdio_probed_func_list[probe_index].func->dev;
  1044. #endif
  1045. }
  1046. EXPORT_SYMBOL(mtk_wcn_hif_sdio_get_dev);
  1047. /*!
  1048. * \brief client's probe() function.
  1049. *
  1050. *
  1051. * \param work queue structure.
  1052. *
  1053. * \retval none.
  1054. */
  1055. static INT32 hif_sdio_clt_probe_func(MTK_WCN_HIF_SDIO_REGISTINFO *registinfo_p, INT8 probe_idx)
  1056. {
  1057. UINT16 card_id = 0;
  1058. UINT16 func_num = 0;
  1059. UINT16 blk_sz = 0;
  1060. INT32 ret;
  1061. HIF_SDIO_DBG_FUNC("start!\n");
  1062. HIF_SDIO_ASSERT(registinfo_p);
  1063. if (!registinfo_p) {
  1064. HIF_SDIO_WARN_FUNC("registinfo_p NULL!!!\n");
  1065. return -1;
  1066. }
  1067. /* special case handling: if the clt's unregister is called during probe procedures */
  1068. if (!registinfo_p->func_info || !registinfo_p->sdio_cltinfo) {
  1069. HIF_SDIO_WARN_FUNC("client's registinfo_p is cleared !!!\n");
  1070. return -1;
  1071. }
  1072. card_id = registinfo_p->func_info->card_id;
  1073. func_num = registinfo_p->func_info->func_num;
  1074. blk_sz = registinfo_p->func_info->blk_sz;
  1075. ret =
  1076. registinfo_p->sdio_cltinfo->hif_clt_probe(CLTCTX(card_id, func_num, blk_sz, probe_idx),
  1077. registinfo_p->func_info);
  1078. HIF_SDIO_INFO_FUNC
  1079. ("clt_probe_func card_id(%x) func_num(%x) blk_sz(%d) prob_idx(%x) ret(%d) %s\n",
  1080. card_id, func_num, blk_sz, probe_idx, ret, (ret) ? "fail" : "ok");
  1081. return ret;
  1082. }
  1083. /*!
  1084. * \brief client's probe() worker.
  1085. *
  1086. *
  1087. * \param work queue structure.
  1088. *
  1089. * \retval none.
  1090. */
  1091. static VOID hif_sdio_clt_probe_worker(struct work_struct *work)
  1092. {
  1093. MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_worker_info_p = 0;
  1094. UINT16 card_id = 0;
  1095. UINT16 func_num = 0;
  1096. UINT16 blk_sz = 0;
  1097. INT8 prob_idx = 0;
  1098. HIF_SDIO_DBG_FUNC("start!\n");
  1099. HIF_SDIO_ASSERT(work);
  1100. /* get client's information */
  1101. clt_worker_info_p = container_of(work, MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO, probe_work);
  1102. HIF_SDIO_ASSERT(clt_worker_info_p);
  1103. HIF_SDIO_ASSERT(clt_worker_info_p->registinfo_p);
  1104. /* special case handling: if the clt's unregister is called during probe procedures */
  1105. if ((clt_worker_info_p->registinfo_p->func_info == 0)
  1106. || (clt_worker_info_p->registinfo_p->sdio_cltinfo == 0)) {
  1107. HIF_SDIO_WARN_FUNC("client's registinfo_p is cleared !!!\n");
  1108. vfree(clt_worker_info_p);
  1109. return;
  1110. }
  1111. card_id = clt_worker_info_p->registinfo_p->func_info->card_id;
  1112. func_num = clt_worker_info_p->registinfo_p->func_info->func_num;
  1113. blk_sz = clt_worker_info_p->registinfo_p->func_info->blk_sz;
  1114. prob_idx = clt_worker_info_p->probe_idx;
  1115. /* Execute client's probe() func */
  1116. clt_worker_info_p->registinfo_p->
  1117. sdio_cltinfo->hif_clt_probe(CLTCTX(card_id, func_num, blk_sz, prob_idx),
  1118. clt_worker_info_p->registinfo_p->func_info);
  1119. vfree(clt_worker_info_p);
  1120. HIF_SDIO_DBG_FUNC("card_id(0x%x) func_num(0x%x) blk_sz(0x%x) prob_idx(0x%x)\n", card_id,
  1121. func_num, blk_sz, prob_idx);
  1122. HIF_SDIO_DBG_FUNC("end!\n");
  1123. }
  1124. /*!
  1125. * \brief client's probe() worker.
  1126. *
  1127. *
  1128. * \param work queue structure.
  1129. *
  1130. * \retval none.
  1131. */
  1132. static VOID hif_sdio_dump_probe_list(VOID)
  1133. {
  1134. int i;
  1135. HIF_SDIO_DBG_FUNC("== DUMP probed list start ==\n");
  1136. for (i = 0; i < CFG_CLIENT_COUNT; i++) {
  1137. if (g_hif_sdio_probed_func_list[i].func) {
  1138. HIF_SDIO_DBG_FUNC("index(%d) func(0x%p) clt_idx(%d)\n",
  1139. i, g_hif_sdio_probed_func_list[i].func,
  1140. g_hif_sdio_probed_func_list[i].clt_idx);
  1141. HIF_SDIO_DBG_FUNC("vendor(0x%x) device(0x%x) num(0x%x) state(%d)\n",
  1142. g_hif_sdio_probed_func_list[i].func->vendor,
  1143. g_hif_sdio_probed_func_list[i].func->device,
  1144. g_hif_sdio_probed_func_list[i].func->num,
  1145. g_hif_sdio_probed_func_list[i].on_by_wmt);
  1146. }
  1147. }
  1148. HIF_SDIO_DBG_FUNC("== DUMP probed list end ==\n");
  1149. }
  1150. /*!
  1151. * \brief Initialize g_hif_sdio_probed_func_list
  1152. *
  1153. *
  1154. * \param index of g_hif_sdio_probed_func_list.
  1155. *
  1156. * \retval none.
  1157. */
  1158. static VOID hif_sdio_init_probed_list(INT32 index)
  1159. {
  1160. if ((index >= 0) && (index < CFG_CLIENT_COUNT)) {
  1161. /* probed spin lock */
  1162. spin_lock_bh(&g_hif_sdio_lock_info.probed_list_lock);
  1163. g_hif_sdio_probed_func_list[index].func = 0;
  1164. g_hif_sdio_probed_func_list[index].clt_idx = -1;
  1165. g_hif_sdio_probed_func_list[index].private_data_p = 0;
  1166. g_hif_sdio_probed_func_list[index].on_by_wmt = MTK_WCN_BOOL_FALSE;
  1167. /* probed spin unlock */
  1168. spin_unlock_bh(&g_hif_sdio_lock_info.probed_list_lock);
  1169. } else
  1170. HIF_SDIO_ERR_FUNC("index is out of g_hif_sdio_probed_func_list[] boundary!\n");
  1171. }
  1172. /*!
  1173. * \brief Initialize g_hif_sdio_clt_drv_list
  1174. *
  1175. *
  1176. * \param index of g_hif_sdio_clt_drv_list.
  1177. *
  1178. * \retval none.
  1179. */
  1180. static VOID hif_sdio_init_clt_list(INT32 index)
  1181. {
  1182. /* client list spin lock */
  1183. spin_lock_bh(&g_hif_sdio_lock_info.clt_list_lock);
  1184. if ((index >= 0) && (index < CFG_CLIENT_COUNT)) {
  1185. g_hif_sdio_clt_drv_list[index].sdio_cltinfo = 0;
  1186. g_hif_sdio_clt_drv_list[index].func_info = 0;
  1187. } else
  1188. HIF_SDIO_ERR_FUNC("index is out of g_hif_sdio_clt_drv_list[] boundary!\n");
  1189. /* client list spin unlock */
  1190. spin_unlock_bh(&g_hif_sdio_lock_info.clt_list_lock);
  1191. }
  1192. /*!
  1193. * \brief find matched g_hif_sdio_probed_func_list index from sdio function handler
  1194. *
  1195. *
  1196. * \param sdio function handler
  1197. *
  1198. * \retval -1 index not found
  1199. * \retval >= 0 return found index
  1200. */
  1201. static INT32 hif_sdio_find_probed_list_index_by_func(struct sdio_func *func)
  1202. {
  1203. INT32 i = 0;
  1204. HIF_SDIO_ASSERT(func);
  1205. for (i = 0; i < CFG_CLIENT_COUNT; i++) {
  1206. if (g_hif_sdio_probed_func_list[i].func == func)
  1207. return i;
  1208. }
  1209. return -1;
  1210. }
  1211. /*!
  1212. * \brief find matched g_hif_sdio_probed_func_list from vendor_id, device_id, and function number
  1213. *
  1214. *
  1215. * \param vendor id, device id, and function number of the sdio card.
  1216. *
  1217. * \retval -1 index not found
  1218. * \retval >= 0 return found index
  1219. */
  1220. static INT32 hif_sdio_find_probed_list_index_by_id_func(UINT16 vendor, UINT16 device,
  1221. UINT16 func_num)
  1222. {
  1223. INT32 i;
  1224. for (i = 0; i < CFG_CLIENT_COUNT; i++) {
  1225. if (g_hif_sdio_probed_func_list[i].func) {
  1226. HIF_SDIO_DBG_FUNC("probed entry: vendor(0x%x) device(0x%x) num(0x%x)\n",
  1227. g_hif_sdio_probed_func_list[i].func->vendor,
  1228. g_hif_sdio_probed_func_list[i].func->device,
  1229. g_hif_sdio_probed_func_list[i].func->num);
  1230. }
  1231. }
  1232. for (i = 0; i < CFG_CLIENT_COUNT; i++) {
  1233. if (!g_hif_sdio_probed_func_list[i].func) {
  1234. continue;
  1235. } else if ((g_hif_sdio_probed_func_list[i].func->vendor == vendor) &&
  1236. (g_hif_sdio_probed_func_list[i].func->device == device) &&
  1237. (g_hif_sdio_probed_func_list[i].func->num == func_num)) {
  1238. return i;
  1239. }
  1240. }
  1241. if (i == CFG_CLIENT_COUNT) {
  1242. /*
  1243. pr_warn(DRV_NAME "Cannot find vendor:0x%x, device:0x%x, func_num:0x%x, i=%d\n",
  1244. vendor, device, func_num, i);
  1245. */
  1246. /* client func has not been probed */
  1247. return -1;
  1248. }
  1249. return -1;
  1250. }
  1251. /*!
  1252. * \brief find matched g_hif_sdio_clt_drv_list index
  1253. *
  1254. * find the matched g_hif_sdio_clt_drv_list index from card_id and function number.
  1255. *
  1256. * \param vendor id, device id, and function number of the sdio card
  1257. *
  1258. * \retval -1 index not found
  1259. * \retval >= 0 return found index
  1260. */
  1261. static INT32 hif_sdio_find_clt_list_index(UINT16 vendor, UINT16 device, UINT16 func_num)
  1262. {
  1263. INT32 i = 0;
  1264. for (i = 0; i < CFG_CLIENT_COUNT; i++) {
  1265. if (g_hif_sdio_clt_drv_list[i].func_info != 0) {
  1266. if ((g_hif_sdio_clt_drv_list[i].func_info->manf_id == vendor) &&
  1267. (g_hif_sdio_clt_drv_list[i].func_info->card_id == device) &&
  1268. (g_hif_sdio_clt_drv_list[i].func_info->func_num == func_num)) {
  1269. return i;
  1270. }
  1271. }
  1272. }
  1273. return -1;
  1274. }
  1275. /*!
  1276. * \brief check if the vendor, device ids are supported in mtk_sdio_id_tbl.
  1277. *
  1278. *
  1279. * \param vendor id and device id of the sdio card
  1280. *
  1281. * \retval (-HIF_SDIO_ERR_FAIL) vendor, device ids are not supported
  1282. * \retval HIF_SDIO_ERR_SUCCESS vendor, device ids are supported
  1283. */
  1284. static INT32 hif_sdio_check_supported_sdio_id(UINT16 vendor, UINT16 device)
  1285. {
  1286. INT32 i = 0;
  1287. for (i = 0; i < CFG_CLIENT_COUNT; i++) {
  1288. if ((mtk_sdio_id_tbl[i].vendor == vendor) && (mtk_sdio_id_tbl[i].device == device))
  1289. return HIF_SDIO_ERR_SUCCESS; /* mtk_sdio_id is supported */
  1290. }
  1291. return -HIF_SDIO_ERR_FAIL; /* mtk_sdio_id is not supported */
  1292. }
  1293. /*!
  1294. * \brief check if the vendor, device ids are duplicated in g_hif_sdio_clt_drv_list.
  1295. *
  1296. *
  1297. * \param vendor id, device id, and function number of the sdio card
  1298. *
  1299. * \retval (-HIF_SDIO_ERR_DUPLICATED) vendor, device, func_num are duplicated
  1300. * \retval HIF_SDIO_ERR_SUCCESS vendor, device, func_num are not duplicated
  1301. */
  1302. static INT32 hif_sdio_check_duplicate_sdio_id(UINT16 vendor, UINT16 device, UINT16 func_num)
  1303. {
  1304. INT32 i = 0;
  1305. for (i = 0; i < CFG_CLIENT_COUNT; i++) {
  1306. if (g_hif_sdio_clt_drv_list[i].func_info != 0) {
  1307. if ((g_hif_sdio_clt_drv_list[i].func_info->manf_id == vendor) &&
  1308. (g_hif_sdio_clt_drv_list[i].func_info->card_id == device) &&
  1309. (g_hif_sdio_clt_drv_list[i].func_info->func_num == func_num)) {
  1310. return -HIF_SDIO_ERR_DUPLICATED; /* duplicated */
  1311. }
  1312. }
  1313. }
  1314. return HIF_SDIO_ERR_SUCCESS; /* Not duplicated */
  1315. }
  1316. /*!
  1317. * \brief Add the client info into g_hif_sdio_clt_drv_list.
  1318. *
  1319. *
  1320. * \param [output] client's index pointer.
  1321. * \param MTK_WCN_HIF_SDIO_CLTINFO of client's contex.
  1322. *
  1323. * \retval (-HIF_SDIO_ERR_FAIL) Add to clt_list successfully
  1324. * \retval HIF_SDIO_ERR_SUCCESS Add to clt_list failed (buffer is full)
  1325. */
  1326. static INT32 hif_sdio_add_clt_list(INT32 *clt_index_p,
  1327. const MTK_WCN_HIF_SDIO_CLTINFO *pinfo, UINT32 tbl_index)
  1328. {
  1329. INT32 i = 0;
  1330. HIF_SDIO_ASSERT(clt_index_p);
  1331. HIF_SDIO_ASSERT(pinfo);
  1332. for (i = 0; i < CFG_CLIENT_COUNT; i++) {
  1333. /* client list spin lock */
  1334. spin_lock_bh(&g_hif_sdio_lock_info.clt_list_lock);
  1335. if (g_hif_sdio_clt_drv_list[i].func_info == 0) {
  1336. g_hif_sdio_clt_drv_list[i].func_info = &(pinfo->func_tbl[tbl_index]);
  1337. g_hif_sdio_clt_drv_list[i].sdio_cltinfo = pinfo;
  1338. /* client list spin unlock */
  1339. spin_unlock_bh(&g_hif_sdio_lock_info.clt_list_lock);
  1340. *clt_index_p = i;
  1341. return HIF_SDIO_ERR_SUCCESS; /* Add to client list successfully */
  1342. }
  1343. /* client list spin unlock */
  1344. spin_unlock_bh(&g_hif_sdio_lock_info.clt_list_lock);
  1345. }
  1346. return -HIF_SDIO_ERR_FAIL; /* Add to client list failed (buffer is full) */
  1347. }
  1348. #if HIF_SDIO_SUPPORT_SUSPEND
  1349. static INT32 hif_sdio_suspend(struct device *dev)
  1350. {
  1351. struct sdio_func *func;
  1352. mmc_pm_flag_t flag;
  1353. INT32 ret;
  1354. if (!dev)
  1355. return -EINVAL;
  1356. func = dev_to_sdio_func(dev);
  1357. HIF_SDIO_DBG_FUNC("prepare for func(0x%p)\n", func);
  1358. flag = sdio_get_host_pm_caps(func);
  1359. #if HIF_SDIO_SUPPORT_WAKEUP
  1360. if (!(flag & MMC_PM_KEEP_POWER) || !(flag & MMC_PM_WAKE_SDIO_IRQ)) {
  1361. HIF_SDIO_WARN_FUNC
  1362. ("neither MMC_PM_KEEP_POWER or MMC_PM_WAKE_SDIO_IRQ is supported by host, return -ENOTSUPP\n");
  1363. return -ENOTSUPP;
  1364. }
  1365. /* set both */
  1366. flag |= MMC_PM_KEEP_POWER | MMC_PM_WAKE_SDIO_IRQ;
  1367. #else
  1368. if (!(flag & MMC_PM_KEEP_POWER)) {
  1369. HIF_SDIO_WARN_FUNC
  1370. ("neither MMC_PM_KEEP_POWER is supported by host, return -ENOTSUPP\n");
  1371. return -ENOTSUPP;
  1372. }
  1373. flag |= MMC_PM_KEEP_POWER;
  1374. #endif
  1375. ret = sdio_set_host_pm_flags(func, flag);
  1376. if (ret) {
  1377. HIF_SDIO_INFO_FUNC
  1378. ("set MMC_PM_KEEP_POWER to host fail(%d)\n", ret);
  1379. return -EFAULT;
  1380. }
  1381. #if HIF_SDIO_SUPPORT_WAKEUP
  1382. sdio_claim_host(func);
  1383. #endif
  1384. HIF_SDIO_INFO_FUNC("set MMC_PM_KEEP_POWER ok\n");
  1385. return 0;
  1386. }
  1387. static INT32 hif_sdio_resume(struct device *dev)
  1388. {
  1389. #if HIF_SDIO_SUPPORT_WAKEUP
  1390. struct sdio_func *func;
  1391. #endif
  1392. if (!dev) {
  1393. HIF_SDIO_WARN_FUNC("null dev!\n");
  1394. return -EINVAL;
  1395. }
  1396. #if HIF_SDIO_SUPPORT_WAKEUP
  1397. func = dev_to_sdio_func(dev);
  1398. sdio_release_host(func);
  1399. #endif
  1400. HIF_SDIO_INFO_FUNC("do nothing\n");
  1401. return 0;
  1402. }
  1403. #endif
  1404. /*!
  1405. * \brief hif_sdio probe function
  1406. *
  1407. * hif_sdio probe function called by mmc driver when any matched SDIO function
  1408. * is detected by it.
  1409. *
  1410. * \param func
  1411. * \param id
  1412. *
  1413. * \retval 0 register successfully
  1414. * \retval < 0 list error code here
  1415. */
  1416. static INT32 hif_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id)
  1417. {
  1418. INT32 ret = 0;
  1419. INT32 i = 0;
  1420. MTK_WCN_HIF_SDIO_PROBEINFO *hif_sdio_probed_funcp = 0;
  1421. INT32 probe_index = -1;
  1422. INT32 idx;
  1423. #if 0
  1424. INT32 clt_index = -1;
  1425. MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_probe_worker_info = 0;
  1426. #endif
  1427. HIF_SDIO_INFO_FUNC("start!\n");
  1428. HIF_SDIO_ASSERT(func);
  1429. #if !(DELETE_HIF_SDIO_CHRDEV)
  1430. hif_sdio_match_chipid_by_dev_id(id);
  1431. #endif
  1432. /* 4 <0> display debug information */
  1433. HIF_SDIO_INFO_FUNC("vendor(0x%x) device(0x%x) num(0x%x)\n", func->vendor, func->device,
  1434. func->num);
  1435. for (i = 0; i < func->card->num_info; i++)
  1436. HIF_SDIO_INFO_FUNC("card->info[%d]: %s\n", i, func->card->info[i]);
  1437. /* 4 <1> Check if this is supported by us (mtk_sdio_id_tbl) */
  1438. ret = hif_sdio_check_supported_sdio_id(func->vendor, func->device);
  1439. if (ret) {
  1440. HIF_SDIO_WARN_FUNC
  1441. ("vendor id and device id of sdio_func are not supported in mtk_sdio_id_tbl!\n");
  1442. goto out;
  1443. }
  1444. /* 4 <2> Add this struct sdio_func *func to g_hif_sdio_probed_func_list */
  1445. for (i = 0; i < CFG_CLIENT_COUNT; i++) {
  1446. /* probed spin lock */
  1447. spin_lock_bh(&g_hif_sdio_lock_info.probed_list_lock);
  1448. if (g_hif_sdio_probed_func_list[i].func == 0) {
  1449. hif_sdio_probed_funcp = &g_hif_sdio_probed_func_list[i];
  1450. hif_sdio_probed_funcp->func = func;
  1451. hif_sdio_probed_funcp->clt_idx =
  1452. hif_sdio_find_clt_list_index(func->vendor, func->device, func->num);
  1453. hif_sdio_probed_funcp->on_by_wmt = MTK_WCN_BOOL_FALSE;
  1454. hif_sdio_probed_funcp->sdio_irq_enabled = MTK_WCN_BOOL_FALSE;
  1455. /* probed spin unlock */
  1456. spin_unlock_bh(&g_hif_sdio_lock_info.probed_list_lock);
  1457. probe_index = i;
  1458. break;
  1459. }
  1460. /* probed spin unlock */
  1461. spin_unlock_bh(&g_hif_sdio_lock_info.probed_list_lock);
  1462. }
  1463. if ((probe_index < 0) || (probe_index >= CFG_CLIENT_COUNT)) {
  1464. HIF_SDIO_ERR_FUNC("probe function list if full!\n");
  1465. goto out;
  1466. }
  1467. /* 4 <3> Initialize this function */
  1468. if (g_hif_sdio_probed_func_list[probe_index].clt_idx < 0) {
  1469. for (i = 0; i < CFG_CLIENT_COUNT; i++) {
  1470. /* client list spin lock */
  1471. spin_lock_bh(&g_hif_sdio_lock_info.clt_list_lock);
  1472. if (g_hif_sdio_clt_drv_list[i].func_info == 0) {
  1473. /* client list spin unlock */
  1474. spin_unlock_bh(&g_hif_sdio_lock_info.clt_list_lock);
  1475. continue;
  1476. }
  1477. HIF_SDIO_INFO_FUNC("manf_id:%x, card_id:%x, func_num:%d\n",
  1478. g_hif_sdio_clt_drv_list[i].func_info->manf_id,
  1479. g_hif_sdio_clt_drv_list[i].func_info->card_id,
  1480. g_hif_sdio_clt_drv_list[i].func_info->func_num);
  1481. if ((g_hif_sdio_clt_drv_list[i].func_info->manf_id ==
  1482. g_hif_sdio_probed_func_list[probe_index].func->vendor)
  1483. && (g_hif_sdio_clt_drv_list[i].func_info->card_id ==
  1484. g_hif_sdio_probed_func_list[probe_index].func->device)
  1485. && (g_hif_sdio_clt_drv_list[i].func_info->func_num ==
  1486. g_hif_sdio_probed_func_list[probe_index].func->num)) {
  1487. g_hif_sdio_probed_func_list[probe_index].clt_idx = i;
  1488. /* client list spin unlock */
  1489. spin_unlock_bh(&g_hif_sdio_lock_info.clt_list_lock);
  1490. break;
  1491. }
  1492. /* client list spin unlock */
  1493. spin_unlock_bh(&g_hif_sdio_lock_info.clt_list_lock);
  1494. }
  1495. HIF_SDIO_INFO_FUNC("map to g_hif_sdio_clt_drv_list[] done: %d\n",
  1496. g_hif_sdio_probed_func_list[probe_index].clt_idx);
  1497. }
  1498. /* 4 <3.1> enable this function */
  1499. sdio_claim_host(func);
  1500. ret = sdio_enable_func(func);
  1501. sdio_release_host(func);
  1502. if (ret) {
  1503. HIF_SDIO_ERR_FUNC("sdio_enable_func failed!\n");
  1504. goto out;
  1505. }
  1506. #if 0
  1507. if (0 == _hif_sdio_is_autok_support(func))
  1508. /* _hif_sdio_do_autok(func); */
  1509. #endif
  1510. /* 4 <3.2> set block size according to the table storing function characteristics */
  1511. if (hif_sdio_probed_funcp == 0) {
  1512. HIF_SDIO_ERR_FUNC("hif_sdio_probed_funcp is null!\n");
  1513. goto out;
  1514. }
  1515. if (hif_sdio_probed_funcp->clt_idx >= 0 &&
  1516. hif_sdio_probed_funcp->clt_idx < CFG_CLIENT_COUNT) {
  1517. /* The clt contex has been registed */
  1518. sdio_claim_host(func);
  1519. idx = hif_sdio_probed_funcp->clt_idx;
  1520. ret = sdio_set_block_size(func, g_hif_sdio_clt_drv_list[idx].func_info->blk_sz);
  1521. sdio_release_host(func);
  1522. } else { /* The clt contex has not been registed */
  1523. sdio_claim_host(func);
  1524. ret = sdio_set_block_size(func, HIF_DEFAULT_BLK_SIZE);
  1525. sdio_release_host(func);
  1526. }
  1527. if (ret) {
  1528. HIF_SDIO_ERR_FUNC("set sdio block size failed!\n");
  1529. goto out;
  1530. }
  1531. HIF_SDIO_INFO_FUNC("cur_blksize(%d) max(%d), host max blk_size(%d) blk_count(%d)\n",
  1532. func->cur_blksize, func->max_blksize,
  1533. func->card->host->max_blk_size, func->card->host->max_blk_count);
  1534. hif_sdio_dump_probe_list();
  1535. out:
  1536. /* 4 <last> error handling */
  1537. return ret;
  1538. }
  1539. /*!
  1540. * \brief hif_sdio remove function
  1541. *
  1542. * hif_sdio probe function called by mmc driver when the probed func should be
  1543. * removed.
  1544. *
  1545. * \param func
  1546. *
  1547. */
  1548. static VOID hif_sdio_remove(struct sdio_func *func)
  1549. {
  1550. INT32 probed_list_index = 0;
  1551. #if 0
  1552. INT32 registed_list_index = 0;
  1553. #endif
  1554. HIF_SDIO_INFO_FUNC("start!\n");
  1555. HIF_SDIO_ASSERT(func);
  1556. /* 4 <1> check input parameter is valid and has been probed previously */
  1557. if (func == NULL) {
  1558. HIF_SDIO_ERR_FUNC("func null(%p)\n", func);
  1559. return;
  1560. }
  1561. /* 4 <2> if this function has been initialized by any client driver, */
  1562. /* 4 call client's .hif_clt_remove() call back in THIS context. */
  1563. probed_list_index = hif_sdio_find_probed_list_index_by_func(func);
  1564. if (probed_list_index < 0) {
  1565. HIF_SDIO_WARN_FUNC
  1566. ("sdio function pointer is not in g_hif_sdio_probed_func_list!\n");
  1567. return;
  1568. }
  1569. #if 0
  1570. registed_list_index = g_hif_sdio_probed_func_list[probed_list_index].clt_idx;
  1571. if (registed_list_index >= 0) {
  1572. g_hif_sdio_clt_drv_list[registed_list_index].sdio_cltinfo->hif_clt_remove(CLTCTX
  1573. (func->
  1574. device,
  1575. func->
  1576. num,
  1577. func->
  1578. cur_blksize,
  1579. probed_list_index));
  1580. }
  1581. #endif
  1582. /* 4 <3> mark this function as de-initialized and invalidate client's context */
  1583. hif_sdio_init_probed_list(probed_list_index);
  1584. #if 0
  1585. /* 4 <4> release irq for this function */
  1586. sdio_claim_host(func);
  1587. sdio_release_irq(func);
  1588. sdio_release_host(func);
  1589. #endif
  1590. /* 4 <5> disable this function */
  1591. sdio_claim_host(func);
  1592. sdio_disable_func(func);
  1593. sdio_release_host(func);
  1594. /* 4 <6> mark this function as removed */
  1595. HIF_SDIO_INFO_FUNC("sdio func(0x%p) is removed successfully!\n", func);
  1596. }
  1597. /*!
  1598. * \brief hif_sdio interrupt handler
  1599. *
  1600. * detailed descriptions
  1601. *
  1602. * \param ctx client's context variable
  1603. *
  1604. */
  1605. static VOID hif_sdio_irq(struct sdio_func *func)
  1606. {
  1607. INT32 probed_list_index = -1;
  1608. INT32 registed_list_index = -1;
  1609. HIF_SDIO_DBG_FUNC("start!\n");
  1610. /* 4 <1> check if func is valid */
  1611. HIF_SDIO_ASSERT(func);
  1612. /* 4 <2> if func has valid corresponding hif_sdio client's context, mark it */
  1613. /* 4 host-locked, use it to call client's .hif_clt_irq() callback function in */
  1614. /* 4 THIS context. */
  1615. probed_list_index = hif_sdio_find_probed_list_index_by_func(func);
  1616. if ((probed_list_index < 0) || (probed_list_index >= CFG_CLIENT_COUNT)) {
  1617. HIF_SDIO_ERR_FUNC("probed_list_index not found!\n");
  1618. return;
  1619. }
  1620. /* [George] added for sdio irq sync and mmc single_irq workaround. It's set
  1621. * enabled later by client driver call mtk_wcn_hif_sdio_enable_irq()
  1622. */
  1623. /* skip smp_rmb() here */
  1624. if (MTK_WCN_BOOL_FALSE == g_hif_sdio_probed_func_list[probed_list_index].sdio_irq_enabled) {
  1625. HIF_SDIO_WARN_FUNC("func(0x%p),probed_idx(%d) sdio irq not enabled yet\n",
  1626. func, probed_list_index);
  1627. return;
  1628. }
  1629. registed_list_index = g_hif_sdio_probed_func_list[probed_list_index].clt_idx;
  1630. /* g_hif_sdio_probed_func_list[probed_list_index].interrupted = MTK_WCN_BOOL_TRUE; */
  1631. if ((registed_list_index >= 0)
  1632. && (registed_list_index < CFG_CLIENT_COUNT)) {
  1633. HIF_SDIO_DBG_FUNC("[%d]SDIO IRQ (func:0x%p) v(0x%x) d(0x%x) n(0x%x)\n",
  1634. probed_list_index, func, func->vendor, func->device, func->num);
  1635. _hif_sdio_deep_sleep_ctrl(CLTCTX
  1636. (func->device, func->num, func->cur_blksize,
  1637. probed_list_index), 0);
  1638. g_hif_sdio_clt_drv_list[registed_list_index].sdio_cltinfo->hif_clt_irq(CLTCTX
  1639. (func->
  1640. device,
  1641. func->num,
  1642. func->
  1643. cur_blksize,
  1644. probed_list_index));
  1645. } else {
  1646. /* 4 <3> if func has no VALID hif_sdio client's context, release irq for this */
  1647. /* 4 func and mark it in g_hif_sdio_probed_func_list (remember: donnot claim host in irq contex). */
  1648. HIF_SDIO_WARN_FUNC("release irq (func:0x%p) v(0x%x) d(0x%x) n(0x%x)\n",
  1649. func, func->vendor, func->device, func->num);
  1650. mtk_wcn_hif_sdio_irq_flag_set(0);
  1651. sdio_release_irq(func);
  1652. }
  1653. }
  1654. /*!
  1655. * \brief hif_sdio init function
  1656. *
  1657. * detailed descriptions
  1658. *
  1659. * \retval
  1660. */
  1661. static INT32 hif_sdio_init(VOID)
  1662. {
  1663. INT32 ret = 0;
  1664. INT32 i = 0;
  1665. HIF_SDIO_INFO_FUNC("start!\n");
  1666. /* 4 <1> init all private variables */
  1667. /* init reference count to 0 */
  1668. gRefCount = 0;
  1669. atomic_set(&hif_sdio_irq_enable_flag, 0);
  1670. /* init spin lock information */
  1671. spin_lock_init(&g_hif_sdio_lock_info.probed_list_lock);
  1672. spin_lock_init(&g_hif_sdio_lock_info.clt_list_lock);
  1673. /* init probed function list and g_hif_sdio_clt_drv_list */
  1674. for (i = 0; i < CFG_CLIENT_COUNT; i++) {
  1675. hif_sdio_init_probed_list(i);
  1676. hif_sdio_init_clt_list(i);
  1677. }
  1678. /* 4 <2> register to mmc driver */
  1679. ret = sdio_register_driver(&mtk_sdio_client_drv);
  1680. HIF_SDIO_INFO_FUNC("sdio_register_driver() ret=%d\n", ret);
  1681. #if !(DELETE_HIF_SDIO_CHRDEV)
  1682. /* 4 <3> create thread for query chip id and device node for launcher to access */
  1683. if (0 == hifsdiod_start())
  1684. hif_sdio_create_dev_node();
  1685. #endif
  1686. _hif_sdio_deep_sleep_info_init();
  1687. HIF_SDIO_DBG_FUNC("end!\n");
  1688. return ret;
  1689. }
  1690. /*!
  1691. * \brief hif_sdio init function
  1692. *
  1693. * detailed descriptions
  1694. *
  1695. * \retval
  1696. */
  1697. static VOID hif_sdio_exit(VOID)
  1698. {
  1699. HIF_SDIO_INFO_FUNC("start!\n");
  1700. #if !(DELETE_HIF_SDIO_CHRDEV)
  1701. hif_sdio_remove_dev_node();
  1702. hifsdiod_stop();
  1703. #endif
  1704. /* 4 <0> if client driver is not removed yet, we shall NOT be called... */
  1705. /* 4 <1> check reference count */
  1706. if (gRefCount != 0)
  1707. HIF_SDIO_WARN_FUNC("gRefCount=%d !!!\n", gRefCount);
  1708. /* 4 <2> check if there is any hif_sdio-registered clients. There should be */
  1709. /* 4 no registered client... */
  1710. /* 4 <3> Reregister with mmc driver. Our remove handler hif_sdio_remove() */
  1711. /* 4 will be called later by mmc_core. Clean up driver resources there. */
  1712. sdio_unregister_driver(&mtk_sdio_client_drv);
  1713. atomic_set(&hif_sdio_irq_enable_flag, 0);
  1714. HIF_SDIO_DBG_FUNC("end!\n");
  1715. } /* end of exitWlan() */
  1716. /*!
  1717. * \brief stp on by wmt (probe client driver).
  1718. *
  1719. *
  1720. * \param none.
  1721. *
  1722. * \retval 0:success, -11:not probed, -12:already on, -13:not registered, other errors.
  1723. */
  1724. INT32 hif_sdio_stp_on(VOID)
  1725. {
  1726. #if 0
  1727. MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_probe_worker_info = 0;
  1728. #endif
  1729. INT32 clt_index = -1;
  1730. INT32 probe_index = -1;
  1731. INT32 ret = -1;
  1732. INT32 ret2 = -1;
  1733. struct sdio_func *func;
  1734. UINT32 chip_id = 0;
  1735. UINT16 func_num = 0;
  1736. const MTK_WCN_HIF_SDIO_FUNCINFO *func_info = NULL;
  1737. HIF_SDIO_INFO_FUNC("start!\n");
  1738. /* 4 <1> If stp client drv has not been probed, return error code */
  1739. /* MT6620 */
  1740. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020B, 1);
  1741. if (probe_index >= 0)
  1742. goto stp_on_exist;
  1743. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020C, 1);
  1744. if (probe_index >= 0)
  1745. goto stp_on_exist;
  1746. /* MT6628 */
  1747. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6628, 2);
  1748. if (probe_index >= 0)
  1749. goto stp_on_exist;
  1750. /* MT6630 */
  1751. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6630, 2);
  1752. if (probe_index >= 0) {
  1753. chip_id = 0x6630;
  1754. func_num = 2;
  1755. goto stp_on_exist;
  1756. }
  1757. /* MT6619 */
  1758. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6619, 1);
  1759. if (probe_index >= 0)
  1760. goto stp_on_exist;
  1761. /* MT6618 */
  1762. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018B, 1);
  1763. if (probe_index >= 0)
  1764. goto stp_on_exist;
  1765. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018C, 1);
  1766. if (probe_index >= 0)
  1767. goto stp_on_exist;
  1768. else {
  1769. /* 4 <2> If stp client drv has not been probed, return error code */
  1770. /* client func has not been probed */
  1771. HIF_SDIO_INFO_FUNC("no supported func probed\n");
  1772. return HIF_SDIO_ERR_NOT_PROBED;
  1773. }
  1774. stp_on_exist:
  1775. /* 4 <3> If stp client drv has been on by wmt, return error code */
  1776. if (MTK_WCN_BOOL_FALSE != g_hif_sdio_probed_func_list[probe_index].on_by_wmt) {
  1777. HIF_SDIO_INFO_FUNC("already on...\n");
  1778. return HIF_SDIO_ERR_ALRDY_ON;
  1779. }
  1780. g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_TRUE;
  1781. clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx;
  1782. if (clt_index >= 0) { /* the function has been registered */
  1783. g_hif_sdio_probed_func_list[probe_index].sdio_irq_enabled = MTK_WCN_BOOL_FALSE;
  1784. /* 4 <4> claim irq for this function */
  1785. func = g_hif_sdio_probed_func_list[probe_index].func;
  1786. if (unlikely(!(func) || !(func->card) || !(func->card->host)
  1787. || mmc_card_removed(func->card))) {
  1788. HIF_SDIO_ERR_FUNC("sdio host is missing\n");
  1789. return HIF_SDIO_ERR_NOT_PROBED;
  1790. }
  1791. sdio_claim_host(func);
  1792. ret = sdio_claim_irq(func, hif_sdio_irq);
  1793. mtk_wcn_hif_sdio_irq_flag_set(1);
  1794. sdio_release_host(func);
  1795. if (ret) {
  1796. HIF_SDIO_WARN_FUNC("sdio_claim_irq() for stp fail(%d)\n", ret);
  1797. return ret;
  1798. }
  1799. HIF_SDIO_INFO_FUNC("sdio_claim_irq() for stp ok\n");
  1800. /* 4 <5> If this struct sdio_func *func is supported by any driver in */
  1801. /* 4 g_hif_sdio_clt_drv_list, schedule another task to call client's .hif_clt_probe() */
  1802. /* TODO: [FixMe][George] WHY probe worker is removed??? */
  1803. #if 1
  1804. /* Call client's .hif_clt_probe() */
  1805. ret = hif_sdio_clt_probe_func(&g_hif_sdio_clt_drv_list[clt_index], probe_index);
  1806. if (ret) {
  1807. HIF_SDIO_WARN_FUNC("clt_probe_func() for stp fail(%d) release irq\n", ret);
  1808. sdio_claim_host(func);
  1809. mtk_wcn_hif_sdio_irq_flag_set(0);
  1810. ret2 = sdio_release_irq(func);
  1811. sdio_release_host(func);
  1812. if (ret2)
  1813. HIF_SDIO_WARN_FUNC("sdio_release_irq() for stp fail(%d)\n", ret2);
  1814. g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_FALSE;
  1815. return ret;
  1816. }
  1817. g_hif_sdio_probed_func_list[probe_index].sdio_irq_enabled = MTK_WCN_BOOL_TRUE;
  1818. /*set deep sleep information to global data struct */
  1819. func_info = g_hif_sdio_clt_drv_list[clt_index].func_info;
  1820. _hif_sdio_deep_sleep_info_set_act(chip_id, func_num,
  1821. CLTCTX(func_info->card_id, func_info->func_num,
  1822. func_info->blk_sz, probe_index), 1);
  1823. HIF_SDIO_INFO_FUNC("ok!\n");
  1824. return 0;
  1825. #else
  1826. /* use worker thread to perform the client's .hif_clt_probe() */
  1827. clt_probe_worker_info = vmalloc(sizeof(MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO));
  1828. INIT_WORK(&clt_probe_worker_info->probe_work, hif_sdio_clt_probe_worker);
  1829. clt_probe_worker_info->registinfo_p = &g_hif_sdio_clt_drv_list[clt_index];
  1830. clt_probe_worker_info->probe_idx = probe_index;
  1831. schedule_work(&clt_probe_worker_info->probe_work);
  1832. #endif
  1833. } else {
  1834. /* TODO: [FixMe][George] check if clt_index is cleared in client's unregister function */
  1835. HIF_SDIO_WARN_FUNC("probed but not registered yet (%d)\n", ret);
  1836. return HIF_SDIO_ERR_CLT_NOT_REG;
  1837. }
  1838. }
  1839. /*!
  1840. * \brief stp off by wmt (remove client driver).
  1841. *
  1842. *
  1843. * \param none.
  1844. *
  1845. * \retval 0:success, -11:not probed, -12:already off, -13:not registered, other errors.
  1846. */
  1847. INT32 hif_sdio_stp_off(VOID)
  1848. {
  1849. INT32 clt_index = -1;
  1850. INT32 probe_index = -1;
  1851. INT32 ret = -1;
  1852. INT32 ret2 = -1;
  1853. struct sdio_func *func;
  1854. UINT32 chip_id = 0;
  1855. UINT16 func_num = 0;
  1856. const MTK_WCN_HIF_SDIO_FUNCINFO *func_info = NULL;
  1857. HIF_SDIO_INFO_FUNC("start!\n");
  1858. /* 4 <1> If stp client drv has not been probed, return error code */
  1859. /* MT6620 */
  1860. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020B, 1);
  1861. if (probe_index >= 0)
  1862. goto stp_off_exist;
  1863. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020C, 1);
  1864. if (probe_index >= 0)
  1865. goto stp_off_exist;
  1866. /* MT6628 */
  1867. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6628, 2);
  1868. if (probe_index >= 0)
  1869. goto stp_off_exist;
  1870. /* MT6630 */
  1871. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6630, 2);
  1872. if (probe_index >= 0) {
  1873. chip_id = 0x6630;
  1874. func_num = 2;
  1875. goto stp_off_exist;
  1876. }
  1877. /* MT6619 */
  1878. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6619, 1);
  1879. if (probe_index >= 0)
  1880. goto stp_off_exist;
  1881. /* MT6618 */
  1882. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018B, 1);
  1883. if (probe_index >= 0)
  1884. goto stp_off_exist;
  1885. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018C, 1);
  1886. if (probe_index >= 0)
  1887. goto stp_off_exist;
  1888. else {
  1889. /* 4 <2> If stp client drv has not been probed, return error code */
  1890. /* client func has not been probed */
  1891. return HIF_SDIO_ERR_NOT_PROBED;
  1892. }
  1893. stp_off_exist:
  1894. /* 4 <3> If stp client drv has been off by wmt, return error code */
  1895. if (MTK_WCN_BOOL_FALSE == g_hif_sdio_probed_func_list[probe_index].on_by_wmt) {
  1896. HIF_SDIO_WARN_FUNC("already off...\n");
  1897. return HIF_SDIO_ERR_ALRDY_OFF;
  1898. }
  1899. g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_FALSE;
  1900. #if 0 /* TODO: [FixMe][George] moved below as done in stp_on. */
  1901. /* 4 <4> release irq for this function */
  1902. func = g_hif_sdio_probed_func_list[probe_index].func;
  1903. sdio_claim_host(func);
  1904. ret = sdio_release_irq(func);
  1905. sdio_release_host(func);
  1906. if (ret)
  1907. pr_warn(DRV_NAME "sdio_release_irq for stp fail(%d)\n", ret);
  1908. else
  1909. pr_warn(DRV_NAME "sdio_release_irq for stp ok\n");
  1910. #endif
  1911. clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx;
  1912. if (clt_index >= 0) { /* the function has been registered */
  1913. func = g_hif_sdio_probed_func_list[probe_index].func;
  1914. if (unlikely(!(func) || !(func->card) || !(func->card->host)
  1915. || mmc_card_removed(func->card))) {
  1916. HIF_SDIO_ERR_FUNC("sdio host is missing\n");
  1917. return HIF_SDIO_ERR_ALRDY_OFF;
  1918. }
  1919. /* 4 <4> release irq for this function */
  1920. sdio_claim_host(func);
  1921. mtk_wcn_hif_sdio_irq_flag_set(0);
  1922. ret2 = sdio_release_irq(func);
  1923. sdio_release_host(func);
  1924. if (ret2)
  1925. HIF_SDIO_WARN_FUNC("sdio_release_irq() for stp fail(%d)\n", ret2);
  1926. else
  1927. HIF_SDIO_INFO_FUNC("sdio_release_irq() for stp ok\n");
  1928. /* 4 <5> Callback to client driver's remove() func */
  1929. ret =
  1930. g_hif_sdio_clt_drv_list[clt_index].
  1931. sdio_cltinfo->hif_clt_remove(CLTCTX
  1932. (func->device, func->num, func->cur_blksize,
  1933. probe_index));
  1934. if (ret)
  1935. HIF_SDIO_WARN_FUNC("clt_remove for stp fail(%d)\n", ret);
  1936. else
  1937. HIF_SDIO_INFO_FUNC("ok!\n");
  1938. /*set deep sleep information to global data struct */
  1939. func_info = g_hif_sdio_clt_drv_list[clt_index].func_info;
  1940. _hif_sdio_deep_sleep_info_set_act(chip_id, func_num,
  1941. CLTCTX(func_info->card_id, func_info->func_num,
  1942. func_info->blk_sz, probe_index), 0);
  1943. return ret + ret2;
  1944. }
  1945. /* TODO: [FixMe][George] check if clt_index is cleared in client's unregister function */
  1946. HIF_SDIO_WARN_FUNC("probed but not registered yet (%d)\n", ret);
  1947. return HIF_SDIO_ERR_CLT_NOT_REG;
  1948. }
  1949. /*!
  1950. * \brief wifi on by wmt (probe client driver).
  1951. *
  1952. *
  1953. * \param none.
  1954. *
  1955. * \retval 0:success, -11:not probed, -12:already on, -13:not registered, other errors.
  1956. */
  1957. INT32 hif_sdio_wifi_on(VOID)
  1958. {
  1959. #if 0
  1960. MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO *clt_probe_worker_info = 0;
  1961. #endif
  1962. INT32 clt_index = -1;
  1963. INT32 probe_index = -1;
  1964. INT32 ret = 0;
  1965. INT32 ret2 = 0;
  1966. INT32 sdio_autok_flag = 0;
  1967. struct sdio_func *func;
  1968. UINT32 chip_id = 0;
  1969. UINT16 func_num = 0;
  1970. const MTK_WCN_HIF_SDIO_FUNCINFO *func_info = NULL;
  1971. HIF_SDIO_INFO_FUNC("start!\n");
  1972. /* 4 <1> If wifi client drv has not been probed, return error code */
  1973. /* MT6620 */
  1974. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020A, 1);
  1975. if (probe_index >= 0)
  1976. goto wifi_on_exist;
  1977. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020C, 2);
  1978. if (probe_index >= 0)
  1979. goto wifi_on_exist;
  1980. /* MT6628 */
  1981. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6628, 1);
  1982. if (probe_index == 0)
  1983. goto wifi_on_exist;
  1984. /* MT6630 */
  1985. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6630, 1);
  1986. if (probe_index >= 0) {
  1987. sdio_autok_flag = 1;
  1988. chip_id = 0x6630;
  1989. func_num = 1;
  1990. goto wifi_on_exist;
  1991. }
  1992. /* MT6618 */
  1993. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018A, 1);
  1994. if (probe_index == 0)
  1995. goto wifi_on_exist;
  1996. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018C, 2);
  1997. if (probe_index >= 0)
  1998. goto wifi_on_exist;
  1999. else {
  2000. /* 4 <2> If wifi client drv has not been probed, return error code */
  2001. /* client func has not been probed */
  2002. return HIF_SDIO_ERR_NOT_PROBED;
  2003. }
  2004. wifi_on_exist:
  2005. /* 4 <3> If wifi client drv has been on by wmt, return error code */
  2006. if (g_hif_sdio_probed_func_list[probe_index].on_by_wmt) {
  2007. HIF_SDIO_INFO_FUNC("probe_index (%d), already on...\n", probe_index);
  2008. return HIF_SDIO_ERR_ALRDY_ON;
  2009. }
  2010. clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx;
  2011. if (clt_index >= 0) { /* the function has been registered */
  2012. if (sdio_autok_flag)
  2013. _hif_sdio_do_autok(g_hif_sdio_probed_func_list[probe_index].func);
  2014. else
  2015. HIF_SDIO_INFO_FUNC("sdio_autok_flag is not set\n", ret);
  2016. g_hif_sdio_probed_func_list[probe_index].sdio_irq_enabled = MTK_WCN_BOOL_FALSE;
  2017. /* 4 <4> claim irq for this function */
  2018. func = g_hif_sdio_probed_func_list[probe_index].func;
  2019. if (unlikely(!(func) || !(func->card) || !(func->card->host)
  2020. || mmc_card_removed(func->card))) {
  2021. HIF_SDIO_ERR_FUNC("sdio host is missing\n");
  2022. return HIF_SDIO_ERR_NOT_PROBED;
  2023. }
  2024. sdio_claim_host(func);
  2025. ret = sdio_claim_irq(func, hif_sdio_irq);
  2026. mtk_wcn_hif_sdio_irq_flag_set(1);
  2027. sdio_release_host(func);
  2028. if (ret) {
  2029. HIF_SDIO_WARN_FUNC("sdio_claim_irq() for wifi fail(%d)\n", ret);
  2030. return ret;
  2031. }
  2032. HIF_SDIO_INFO_FUNC("sdio_claim_irq() for wifi ok\n");
  2033. /* 4 <5> If this struct sdio_func *func is supported by any driver in */
  2034. /* 4 g_hif_sdio_clt_drv_list, schedule another task to call client's .hif_clt_probe() */
  2035. /* TODO: [FixMe][George] WHY probe worker is removed??? */
  2036. #if 1
  2037. /*set deep sleep information to global data struct */
  2038. func_info = g_hif_sdio_clt_drv_list[clt_index].func_info;
  2039. _hif_sdio_deep_sleep_info_set_act(chip_id, func_num,
  2040. CLTCTX(func_info->card_id, func_info->func_num,
  2041. func_info->blk_sz, probe_index), 1);
  2042. /* Call client's .hif_clt_probe() */
  2043. ret = hif_sdio_clt_probe_func(&g_hif_sdio_clt_drv_list[clt_index], probe_index);
  2044. if (ret) {
  2045. HIF_SDIO_WARN_FUNC("clt_probe_func() for wifi fail(%d) release irq\n", ret);
  2046. sdio_claim_host(func);
  2047. mtk_wcn_hif_sdio_irq_flag_set(0);
  2048. ret2 = sdio_release_irq(func);
  2049. sdio_release_host(func);
  2050. if (ret2)
  2051. HIF_SDIO_WARN_FUNC("sdio_release_irq() for wifi fail(%d)\n", ret2);
  2052. _hif_sdio_deep_sleep_info_set_act(chip_id, func_num,
  2053. CLTCTX(func_info->card_id,
  2054. func_info->func_num,
  2055. func_info->blk_sz, probe_index),
  2056. 0);
  2057. g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_FALSE;
  2058. return ret;
  2059. }
  2060. g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_TRUE;
  2061. HIF_SDIO_INFO_FUNC("ok!\n");
  2062. return 0;
  2063. #else
  2064. /* use worker thread to perform the client's .hif_clt_probe() */
  2065. clt_probe_worker_info = vmalloc(sizeof(MTK_WCN_HIF_SDIO_CLT_PROBE_WORKERINFO));
  2066. INIT_WORK(&clt_probe_worker_info->probe_work, hif_sdio_clt_probe_worker);
  2067. clt_probe_worker_info->registinfo_p = &g_hif_sdio_clt_drv_list[clt_index];
  2068. clt_probe_worker_info->probe_idx = probe_index;
  2069. schedule_work(&clt_probe_worker_info->probe_work);
  2070. #endif
  2071. } else {
  2072. /* TODO: [FixMe][George] check if clt_index is cleared in client's unregister function */
  2073. HIF_SDIO_WARN_FUNC("probed but not registered yet (%d)\n", ret);
  2074. return HIF_SDIO_ERR_CLT_NOT_REG;
  2075. }
  2076. }
  2077. /*!
  2078. * \brief wifi off by wmt (remove client driver).
  2079. *
  2080. *
  2081. * \param none.
  2082. *
  2083. * \retval 0:success, -11:not probed, -12:already off, -13:not registered, other errors.
  2084. */
  2085. INT32 hif_sdio_wifi_off(VOID)
  2086. {
  2087. INT32 clt_index = -1;
  2088. INT32 probe_index = -1;
  2089. INT32 ret = -1;
  2090. INT32 ret2 = -1;
  2091. struct sdio_func *func;
  2092. UINT32 chip_id = 0;
  2093. UINT16 func_num = 0;
  2094. const MTK_WCN_HIF_SDIO_FUNCINFO *func_info = NULL;
  2095. HIF_SDIO_INFO_FUNC("start!\n");
  2096. /* 4 <1> If wifi client drv has not been probed, return error code */
  2097. /* MT6620 */
  2098. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020A, 1);
  2099. if (probe_index >= 0)
  2100. goto wifi_off_exist;
  2101. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x020C, 2);
  2102. if (probe_index >= 0)
  2103. goto wifi_off_exist;
  2104. /* MT6628 */
  2105. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6628, 1);
  2106. if (probe_index >= 0)
  2107. goto wifi_off_exist;
  2108. /* MT6630 */
  2109. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x6630, 1);
  2110. if (probe_index >= 0) {
  2111. chip_id = 0x6630;
  2112. func_num = 1;
  2113. goto wifi_off_exist;
  2114. }
  2115. /* MT6618 */
  2116. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018A, 1);
  2117. if (probe_index >= 0)
  2118. goto wifi_off_exist;
  2119. probe_index = hif_sdio_find_probed_list_index_by_id_func(0x037A, 0x018C, 2);
  2120. if (probe_index >= 0)
  2121. goto wifi_off_exist;
  2122. else {
  2123. /* 4 <2> If wifi client drv has not been probed, return error code */
  2124. /* client func has not been probed */
  2125. return HIF_SDIO_ERR_NOT_PROBED;
  2126. }
  2127. wifi_off_exist:
  2128. /* 4 <3> If wifi client drv has been off by wmt, return error code */
  2129. if (MTK_WCN_BOOL_FALSE == g_hif_sdio_probed_func_list[probe_index].on_by_wmt) {
  2130. HIF_SDIO_WARN_FUNC("already off...\n");
  2131. return HIF_SDIO_ERR_ALRDY_OFF;
  2132. }
  2133. g_hif_sdio_probed_func_list[probe_index].on_by_wmt = MTK_WCN_BOOL_FALSE;
  2134. #if 0 /* TODO: [FixMe][George] moved below as done in wifi_on. */
  2135. /* 4 <4> release irq for this function */
  2136. func = g_hif_sdio_probed_func_list[probe_index].func;
  2137. sdio_claim_host(func);
  2138. ret = sdio_release_irq(func);
  2139. sdio_release_host(func);
  2140. if (ret)
  2141. pr_warn(DRV_NAME "sdio_release_irq for wifi fail(%d)\n", ret);
  2142. else
  2143. pr_warn(DRV_NAME "sdio_release_irq for wifi ok\n");
  2144. #endif
  2145. clt_index = g_hif_sdio_probed_func_list[probe_index].clt_idx;
  2146. if (clt_index >= 0) { /* the function has been registered */
  2147. func = g_hif_sdio_probed_func_list[probe_index].func;
  2148. /* 4 <4> Callback to client driver's remove() func */
  2149. ret =
  2150. g_hif_sdio_clt_drv_list[clt_index].
  2151. sdio_cltinfo->hif_clt_remove(CLTCTX
  2152. (func->device, func->num, func->cur_blksize,
  2153. probe_index));
  2154. if (ret)
  2155. HIF_SDIO_WARN_FUNC("clt_remove for wifi fail(%d)\n", ret);
  2156. else
  2157. HIF_SDIO_INFO_FUNC("ok!\n");
  2158. if (unlikely(!(func) || !(func->card) || !(func->card->host)
  2159. || mmc_card_removed(func->card))) {
  2160. HIF_SDIO_ERR_FUNC("sdio host is missing\n");
  2161. return HIF_SDIO_ERR_ALRDY_OFF;
  2162. }
  2163. /* 4 <5> release irq for this function */
  2164. sdio_claim_host(func);
  2165. mtk_wcn_hif_sdio_irq_flag_set(0);
  2166. ret2 = sdio_release_irq(func);
  2167. sdio_release_host(func);
  2168. g_hif_sdio_probed_func_list[probe_index].sdio_irq_enabled = MTK_WCN_BOOL_FALSE;
  2169. if (ret2)
  2170. HIF_SDIO_WARN_FUNC("sdio_release_irq() for wifi fail(%d)\n", ret2);
  2171. else
  2172. HIF_SDIO_INFO_FUNC("sdio_release_irq() for wifi ok\n");
  2173. /*set deep sleep information to global data struct */
  2174. func_info = g_hif_sdio_clt_drv_list[clt_index].func_info;
  2175. _hif_sdio_deep_sleep_info_set_act(chip_id, func_num,
  2176. CLTCTX(func_info->card_id, func_info->func_num,
  2177. func_info->blk_sz, probe_index), 0);
  2178. return ret + ret2;
  2179. }
  2180. /* TODO: [FixMe][George] check if clt_index is cleared in client's unregister function */
  2181. HIF_SDIO_WARN_FUNC("probed but not registered yet (%d)\n", ret);
  2182. return HIF_SDIO_ERR_CLT_NOT_REG;
  2183. }
  2184. /*!
  2185. * \brief set mmc power up/off
  2186. *
  2187. * detailed descriptions
  2188. *
  2189. * \param: 1. ctx client's context variable, 2.power state: 1:power up, other:power off
  2190. *
  2191. * \retval 0:success, -1:fail
  2192. */
  2193. INT32 mtk_wcn_hif_sdio_bus_set_power(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT32 pwrState)
  2194. {
  2195. int probe_index = -1;
  2196. struct sdio_func *func = 0;
  2197. HIF_SDIO_INFO_FUNC("turn Bus Power to: %d\n", pwrState);
  2198. probe_index = CLTCTX_IDX(ctx);
  2199. if (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */
  2200. HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx);
  2201. return -1;
  2202. }
  2203. func = g_hif_sdio_probed_func_list[probe_index].func;
  2204. if (!func) {
  2205. HIF_SDIO_WARN_FUNC("Cannot find sdio_func !!!\n");
  2206. return -1;
  2207. }
  2208. if (1 == pwrState) {
  2209. sdio_claim_host(func);
  2210. mmc_power_up_ext(func->card->host);
  2211. sdio_release_host(func);
  2212. HIF_SDIO_WARN_FUNC("SDIO BUS Power UP\n");
  2213. } else {
  2214. sdio_claim_host(func);
  2215. mmc_power_off_ext(func->card->host);
  2216. sdio_release_host(func);
  2217. HIF_SDIO_WARN_FUNC("SDIO BUS Power OFF\n");
  2218. }
  2219. return 0;
  2220. }
  2221. EXPORT_SYMBOL(mtk_wcn_hif_sdio_bus_set_power);
  2222. VOID mtk_wcn_hif_sdio_enable_irq(MTK_WCN_HIF_SDIO_CLTCTX ctx, MTK_WCN_BOOL enable)
  2223. {
  2224. UINT8 probed_idx = CLTCTX_IDX(ctx);
  2225. if (unlikely(!CLTCTX_IDX_VALID(probed_idx))) { /* invalid index in CLTCTX */
  2226. HIF_SDIO_WARN_FUNC("invalid idx in ctx(0x%x), sdio_irq no change\n", ctx);
  2227. return;
  2228. }
  2229. if (unlikely(!CLTCTX_IDX_VALID(probed_idx))) { /* invalid index in CLTCTX */
  2230. HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx);
  2231. return;
  2232. }
  2233. /* store client driver's private data to dev driver */
  2234. g_hif_sdio_probed_func_list[probed_idx].sdio_irq_enabled = enable;
  2235. smp_wmb();
  2236. HIF_SDIO_INFO_FUNC("ctx(0x%x) sdio irq enable(%d)\n",
  2237. ctx, (MTK_WCN_BOOL_FALSE == enable) ? 0 : 1);
  2238. }
  2239. EXPORT_SYMBOL(mtk_wcn_hif_sdio_enable_irq);
  2240. #if 0
  2241. static INT32 _hif_sdio_is_autok_support(struct sdio_func *func)
  2242. {
  2243. INT32 iRet = -1;
  2244. if ((0x037A == func->vendor) && (0x6630 == func->device) && (1 == func->num))
  2245. iRet = 0;
  2246. return iRet;
  2247. }
  2248. #endif
  2249. static INT32 _hif_sdio_do_autok(struct sdio_func *func)
  2250. {
  2251. INT32 i_ret = 0;
  2252. #if MTK_HIF_SDIO_AUTOK_ENABLED
  2253. #if 0
  2254. BOOTMODE boot_mode;
  2255. boot_mode = get_boot_mode();
  2256. if (boot_mode == META_BOOT) {
  2257. HIF_SDIO_INFO_FUNC("omit autok in meta mode\n");
  2258. i_ret = 0;
  2259. return i_ret;
  2260. }
  2261. #endif
  2262. HIF_SDIO_INFO_FUNC("wait_sdio_autok_ready++\n");
  2263. wait_sdio_autok_ready(func->card->host);
  2264. HIF_SDIO_INFO_FUNC("wait_sdio_autok_ready--\n");
  2265. i_ret = 0;
  2266. #else
  2267. HIF_SDIO_ERR_FUNC("autok feature is not enabled.\n");
  2268. #endif
  2269. return i_ret;
  2270. }
  2271. INT32 mtk_wcn_hif_sdio_do_autok(MTK_WCN_HIF_SDIO_CLTCTX ctx)
  2272. {
  2273. INT32 i_ret = 0;
  2274. UINT8 probe_index = 0;
  2275. struct sdio_func *func = NULL;
  2276. probe_index = CLTCTX_IDX(ctx);
  2277. if (CFG_CLIENT_COUNT > probe_index)
  2278. func = g_hif_sdio_probed_func_list[probe_index].func;
  2279. else {
  2280. HIF_SDIO_WARN_FUNC("probe_index is %d, out of range!\n", probe_index);
  2281. return -1;
  2282. }
  2283. i_ret = _hif_sdio_do_autok(func);
  2284. return i_ret;
  2285. }
  2286. EXPORT_SYMBOL(mtk_wcn_hif_sdio_do_autok);
  2287. /*!
  2288. * \brief
  2289. *
  2290. * detailed descriptions
  2291. *
  2292. * \param ctx client's context variable
  2293. *
  2294. * \retval 0 register successfully
  2295. * \retval < 0 list error code here
  2296. */
  2297. INT32 mtk_wcn_hif_sdio_f0_readb(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT32 offset, PUINT8 pvb)
  2298. {
  2299. #if HIF_SDIO_UPDATE
  2300. INT32 ret;
  2301. struct sdio_func *func;
  2302. #else
  2303. INT32 ret = -HIF_SDIO_ERR_FAIL;
  2304. INT32 probe_index = -1;
  2305. struct sdio_func *func = 0;
  2306. #endif
  2307. HIF_SDIO_DBG_FUNC("start!\n");
  2308. HIF_SDIO_ASSERT(pvb);
  2309. /*4 <1> check if ctx is valid, registered, and probed */
  2310. #if HIF_SDIO_UPDATE
  2311. ret = -HIF_SDIO_ERR_FAIL;
  2312. func = hif_sdio_ctx_to_func(ctx);
  2313. if (!func) {
  2314. ret = -HIF_SDIO_ERR_FAIL;
  2315. goto out;
  2316. }
  2317. #else
  2318. probe_index = CLTCTX_IDX(ctx);
  2319. if (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */
  2320. HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx);
  2321. return -1;
  2322. }
  2323. if (probe_index < 0 || probe_index >= CFG_CLIENT_COUNT) { /* the function has not been probed */
  2324. HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
  2325. ret = -HIF_SDIO_ERR_FAIL;
  2326. goto out;
  2327. } else {
  2328. if (g_hif_sdio_probed_func_list[probe_index].clt_idx < 0) { /* the client has not been registered */
  2329. HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
  2330. ret = -HIF_SDIO_ERR_FAIL;
  2331. goto out;
  2332. }
  2333. }
  2334. func = g_hif_sdio_probed_func_list[probe_index].func;
  2335. #endif
  2336. /*4 <2>*/
  2337. sdio_claim_host(func);
  2338. *pvb = sdio_f0_readb(func, offset, &ret);
  2339. sdio_release_host(func);
  2340. /*4 <3> check result code and return proper error code*/
  2341. out:
  2342. HIF_SDIO_DBG_FUNC("end!\n");
  2343. return ret;
  2344. } /* end of mtk_wcn_hif_sdio_f0_readb() */
  2345. /*!
  2346. * \brief
  2347. *
  2348. * detailed descriptions
  2349. *
  2350. * \param ctx client's context variable
  2351. *
  2352. * \retval 0register successfully
  2353. * \retval < 0 list error code here
  2354. */
  2355. INT32 mtk_wcn_hif_sdio_f0_writeb(MTK_WCN_HIF_SDIO_CLTCTX ctx, UINT32 offset, UINT8 vb)
  2356. {
  2357. #if HIF_SDIO_UPDATE
  2358. INT32 ret;
  2359. struct sdio_func *func;
  2360. #else
  2361. INT32 ret = -HIF_SDIO_ERR_FAIL;
  2362. INT32 probe_index = -1;
  2363. struct sdio_func *func = 0;
  2364. #endif
  2365. HIF_SDIO_DBG_FUNC("start!\n");
  2366. /*4 <1> check if ctx is valid, registered, and probed*/
  2367. #if HIF_SDIO_UPDATE
  2368. ret = -HIF_SDIO_ERR_FAIL;
  2369. func = hif_sdio_ctx_to_func(ctx);
  2370. if (!func) {
  2371. ret = -HIF_SDIO_ERR_FAIL;
  2372. goto out;
  2373. }
  2374. #else
  2375. probe_index = CLTCTX_IDX(ctx);
  2376. if (unlikely(!CLTCTX_IDX_VALID(probe_index))) { /* invalid index in CLTCTX */
  2377. HIF_SDIO_WARN_FUNC("invalid ctx(0x%x)\n", ctx);
  2378. goto out;
  2379. }
  2380. if (probe_index < 0) { /* the function has not been probed */
  2381. HIF_SDIO_WARN_FUNC("can't find client in probed list!\n");
  2382. ret = -HIF_SDIO_ERR_FAIL;
  2383. goto out;
  2384. } else {
  2385. if (g_hif_sdio_probed_func_list[probe_index].clt_idx < 0) { /* the client has not been registered */
  2386. HIF_SDIO_WARN_FUNC("can't find client in registered list!\n");
  2387. ret = -HIF_SDIO_ERR_FAIL;
  2388. goto out;
  2389. }
  2390. }
  2391. func = g_hif_sdio_probed_func_list[probe_index].func;
  2392. #endif
  2393. /*4 <1.1> check if input parameters are valid*/
  2394. /*4 <2>*/
  2395. wmt_tra_sdio_update();
  2396. sdio_claim_host(func);
  2397. sdio_f0_writeb(func, vb, offset, &ret);
  2398. sdio_release_host(func);
  2399. /*4 <3> check result code and return proper error code*/
  2400. out:
  2401. HIF_SDIO_DBG_FUNC("end!\n");
  2402. return ret;
  2403. } /* end of mtk_wcn_hif_sdio_f0_writeb() */
  2404. INT32 mtk_wcn_hif_sdio_en_deep_sleep(MTK_WCN_HIF_SDIO_CLTCTX ctx)
  2405. {
  2406. return _hif_sdio_deep_sleep_ctrl(ctx, 1);
  2407. } /* end of mtk_wcn_hif_sdio_deep_sleep() */
  2408. EXPORT_SYMBOL(mtk_wcn_hif_sdio_en_deep_sleep);
  2409. INT32 mtk_wcn_hif_sdio_dis_deep_sleep(MTK_WCN_HIF_SDIO_CLTCTX ctx)
  2410. {
  2411. return _hif_sdio_deep_sleep_ctrl(ctx, 0);
  2412. } /* end of mtk_wcn_hif_sdio_wake_up() */
  2413. EXPORT_SYMBOL(mtk_wcn_hif_sdio_dis_deep_sleep);
  2414. #ifdef MTK_WCN_REMOVE_KERNEL_MODULE
  2415. INT32 mtk_wcn_hif_sdio_drv_init(VOID)
  2416. {
  2417. return hif_sdio_init();
  2418. }
  2419. EXPORT_SYMBOL(mtk_wcn_hif_sdio_drv_init);
  2420. VOID mtk_wcn_hif_sdio_driver_exit(VOID)
  2421. {
  2422. return hif_sdio_exit();
  2423. }
  2424. EXPORT_SYMBOL(mtk_wcn_hif_sdio_driver_exit);
  2425. #else
  2426. module_init(hif_sdio_init);
  2427. module_exit(hif_sdio_exit);
  2428. #endif