| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420 |
- /*-----------linux system header files----------------*/
- #include <linux/module.h>
- #include <linux/kernel.h>
- #include <linux/device.h>
- #include <linux/errno.h>
- #include <linux/platform_device.h>
- #include <linux/fs.h>
- #include <linux/cdev.h>
- #include <linux/poll.h>
- /*#include <mach/eint.h>*/
- /*-----------driver own header files----------------*/
- #ifdef CONFIG_COMPAT
- #include <linux/compat.h>
- #endif
- #ifdef DFT_TAG
- #undef DFT_TAG
- #endif
- #define DFT_TAG "MTK-BTIF"
- #define BTIF_CDEV_SUPPORT 1
- #include "btif_pub.h"
- #include "btif_dma_pub.h"
- #include "mtk_btif_exp.h"
- #include "mtk_btif.h"
- /*-----------static function declearation----------------*/
- static int mtk_btif_probe(struct platform_device *pdev);
- static int mtk_btif_remove(struct platform_device *pdev);
- static int mtk_btif_suspend(struct platform_device *pdev, pm_message_t state);
- static int mtk_btif_resume(struct platform_device *pdev);
- static int mtk_btif_drv_resume(struct device *dev);
- static int mtk_btif_drv_suspend(struct device *pdev);
- static int mtk_btif_restore_noirq(struct device *device);
- static int btif_file_open(struct inode *pinode, struct file *pfile);
- static int btif_file_release(struct inode *pinode, struct file *pfile);
- static ssize_t btif_file_read(struct file *pfile,
- char __user *buf, size_t count, loff_t *f_ops);
- static unsigned int btif_poll(struct file *filp, poll_table *wait);
- static int _btif_irq_reg(P_MTK_BTIF_IRQ_STR p_irq,
- mtk_btif_irq_handler irq_handler, void *data);
- static int _btif_irq_free(P_MTK_BTIF_IRQ_STR p_irq, void *data);
- static int _btif_irq_ctrl(P_MTK_BTIF_IRQ_STR p_irq, bool en);
- static int _btif_irq_ctrl_sync(P_MTK_BTIF_IRQ_STR p_irq, bool en);
- static irqreturn_t btif_irq_handler(int irq, void *data);
- static unsigned int btif_pio_rx_data_receiver(P_MTK_BTIF_INFO_STR p_btif_info,
- unsigned char *p_buf,
- unsigned int buf_len);
- static irqreturn_t btif_tx_dma_irq_handler(int irq, void *data);
- static irqreturn_t btif_rx_dma_irq_handler(int irq, void *data);
- static unsigned int btif_dma_rx_data_receiver(P_MTK_DMA_INFO_STR p_dma_info,
- unsigned char *p_buf,
- unsigned int buf_len);
- static int _btif_controller_tx_setup(p_mtk_btif p_btif);
- static int _btif_controller_tx_free(p_mtk_btif p_btif);
- static int _btif_controller_rx_setup(p_mtk_btif p_btif);
- static int _btif_controller_rx_free(p_mtk_btif p_btif);
- static int _btif_tx_pio_setup(p_mtk_btif p_btif);
- static int _btif_rx_pio_setup(p_mtk_btif p_btif);
- static int _btif_rx_dma_setup(p_mtk_btif p_btif);
- static int _btif_rx_dma_free(p_mtk_btif p_btif);
- static int _btif_tx_dma_setup(p_mtk_btif p_btif);
- static int _btif_tx_dma_free(p_mtk_btif p_btif);
- static int _btif_controller_setup(p_mtk_btif p_btif);
- static int _btif_controller_free(p_mtk_btif p_btif);
- static int _btif_pio_write(p_mtk_btif p_btif,
- const unsigned char *p_buf, unsigned int buf_len);
- static int _btif_dma_write(p_mtk_btif p_btif,
- const unsigned char *p_buf, unsigned int buf_len);
- static unsigned int btif_bbs_wr_direct(p_btif_buf_str p_bbs,
- unsigned char *p_buf, unsigned int buf_len);
- static unsigned int btif_bbs_read(p_btif_buf_str p_bbs,
- unsigned char *p_buf, unsigned int buf_len);
- static unsigned int btif_bbs_write(p_btif_buf_str p_bbs,
- unsigned char *p_buf, unsigned int buf_len);
- static void btif_dump_bbs_str(unsigned char *p_str, p_btif_buf_str p_bbs);
- static int _btif_dump_memory(char *str, unsigned char *p_buf, unsigned int buf_len);
- static int _btif_rx_btm_deinit(p_mtk_btif p_btif);
- static int _btif_rx_btm_sched(p_mtk_btif p_btif);
- static int _btif_rx_btm_init(p_mtk_btif p_btif);
- static void btif_rx_tasklet(unsigned long func_data);
- static void btif_rx_worker(struct work_struct *p_work);
- static int btif_rx_thread(void *p_data);
- static int btif_rx_data_consummer(p_mtk_btif p_btif);
- static int _btif_tx_ctx_init(p_mtk_btif p_btif);
- static int _btif_tx_ctx_deinit(p_mtk_btif p_btif);
- static void btif_tx_worker(struct work_struct *p_work);
- static int _btif_state_deinit(p_mtk_btif p_btif);
- static int _btif_state_release(p_mtk_btif p_btif);
- static ENUM_BTIF_STATE _btif_state_get(p_mtk_btif p_btif);
- static int _btif_state_set(p_mtk_btif p_btif, ENUM_BTIF_STATE state);
- static int _btif_state_hold(p_mtk_btif p_btif);
- static int _btif_state_init(p_mtk_btif p_btif);
- static int _btif_dpidle_notify_ctrl(p_mtk_btif p_btif,
- ENUM_BTIF_DPIDLE_CTRL en_flag);
- static int _btif_enter_dpidle(p_mtk_btif p_btif);
- static int _btif_exit_dpidle(p_mtk_btif p_btif);
- static int _btif_exit_dpidle_from_sus(p_mtk_btif p_btif);
- static int _btif_exit_dpidle_from_dpidle(p_mtk_btif p_btif);
- static int _btif_enter_dpidle_from_on(p_mtk_btif p_btif);
- static int _btif_enter_dpidle_from_sus(p_mtk_btif p_btif);
- static int _btif_vfifo_deinit(p_mtk_btif_dma p_dma);
- static int _btif_vfifo_init(p_mtk_btif_dma p_dma);
- static bool _btif_is_tx_complete(p_mtk_btif p_btif);
- static int _btif_init(p_mtk_btif p_btif);
- static int _btif_lpbk_ctrl(p_mtk_btif p_btif, bool flag);
- static int btif_rx_dma_mode_set(int en);
- static int btif_tx_dma_mode_set(int en);
- static int _btif_send_data(p_mtk_btif p_btif,
- const unsigned char *p_buf, unsigned int buf_len);
- /*-----------end of static function declearation----------------*/
- static const char *g_state[B_S_MAX] = {
- "OFF",
- "SUSPEND",
- "DPIDLE",
- "ON",
- };
- /*-----------BTIF setting--------------*/
- mtk_btif_setting g_btif_setting[BTIF_PORT_NR] = {
- {
- .tx_mode = BTIF_TX_MODE,
- .rx_mode = BTIF_RX_MODE,
- .rx_type = BTIF_RX_BTM_CTX,
- .tx_type = BTIF_TX_CTX,
- },
- };
- mtk_btif g_btif[BTIF_PORT_NR] = {
- {
- .open_counter = 0,
- .state = B_S_OFF,
- .setting = &g_btif_setting[0],
- .p_tx_dma = NULL,
- .p_rx_dma = NULL,
- .rx_cb = NULL,
- .p_btif_info = NULL,
- },
- };
- mtk_btif_dma g_dma[BTIF_PORT_NR][BTIF_DIR_MAX] = {
- {
- {
- .p_btif = NULL,
- .dir = BTIF_TX,
- .p_dma_info = NULL,
- .entry = ATOMIC_INIT(0),
- },
- {
- .p_btif = NULL,
- .dir = BTIF_RX,
- .p_dma_info = NULL,
- .entry = ATOMIC_INIT(0),
- },
- },
- };
- #define G_MAX_PKG_LEN (7 * 1024)
- static int g_max_pkg_len = G_MAX_PKG_LEN; /*DMA vFIFO is set to 8 * 1024, we set this to 7/8 * vFIFO size*/
- static int g_max_pding_data_size = BTIF_RX_BUFFER_SIZE * 3 / 4;
- static int mtk_btif_dbg_lvl = BTIF_LOG_INFO;
- #if BTIF_RXD_BE_BLOCKED_DETECT
- static struct timeval btif_rxd_time_stamp[MAX_BTIF_RXD_TIME_REC];
- #endif
- /*-----------Platform bus related structures----------------*/
- #define DRV_NAME "mtk_btif"
- #ifdef CONFIG_OF
- const struct of_device_id apbtif_of_ids[] = {
- { .compatible = "mediatek,btif", },
- {}
- };
- #endif
- const struct dev_pm_ops mtk_btif_drv_pm_ops = {
- .restore_noirq = mtk_btif_restore_noirq,
- .suspend = mtk_btif_drv_suspend,
- .resume = mtk_btif_drv_resume,
- };
- struct platform_driver mtk_btif_dev_drv = {
- .probe = mtk_btif_probe,
- .remove = mtk_btif_remove,
- #ifdef CONFIG_PM
- .suspend = mtk_btif_suspend,
- .resume = mtk_btif_resume,
- #endif
- .driver = {
- .name = DRV_NAME,
- .owner = THIS_MODULE,
- #ifdef CONFIG_PM
- .pm = &mtk_btif_drv_pm_ops,
- #endif
- #ifdef CONFIG_OF
- .of_match_table = apbtif_of_ids,
- #endif
- }
- };
- #define BTIF_STATE_RELEASE(x) _btif_state_release(x)
- /*-----------End of Platform bus related structures----------------*/
- /*-----------platform bus related operation APIs----------------*/
- static int mtk_btif_probe(struct platform_device *pdev)
- {
- /*Chaozhong: ToDo: to be implement*/
- /*register IRQ for BTIF and Tx Rx DMA and disable them by default*/
- BTIF_INFO_FUNC("DO BTIF PROBE\n");
- platform_set_drvdata(pdev, &g_btif[0]);
- g_btif[0].private_data = (struct device *)&pdev->dev;
- #if !defined(CONFIG_MTK_CLKMGR)
- hal_btif_clk_get_and_prepare(pdev);
- #endif
- return 0;
- }
- static int mtk_btif_remove(struct platform_device *pdev)
- {
- /*Chaozhong: ToDo: to be implement*/
- BTIF_INFO_FUNC("DO BTIF REMOVE\n");
- platform_set_drvdata(pdev, NULL);
- g_btif[0].private_data = NULL;
- return 0;
- }
- int _btif_suspend(p_mtk_btif p_btif)
- {
- int i_ret;
- if (_btif_state_hold(p_btif))
- return E_BTIF_INTR;
- if (NULL != p_btif) {
- if (!(p_btif->enable))
- i_ret = 0;
- else {
- if (B_S_ON == _btif_state_get(p_btif)) {
- BTIF_ERR_FUNC("BTIF in ON state,",
- "there are data need to be send or recev,suspend fail\n");
- i_ret = -1;
- } else {
- /*before disable BTIF controller and DMA controller
- we need to set BTIF to ON state*/
- i_ret = _btif_exit_dpidle(p_btif);
- if (0 == i_ret) {
- i_ret += _btif_controller_free(p_btif);
- i_ret = _btif_controller_tx_free(p_btif);
- i_ret += _btif_controller_rx_free(p_btif);
- }
- if (0 != i_ret) {
- BTIF_INFO_FUNC("failed\n");
- /*Chaozhong: what if failed*/
- } else {
- BTIF_INFO_FUNC("succeed\n");
- i_ret = _btif_state_set(p_btif, B_S_SUSPEND);
- if (i_ret && _btif_init(p_btif)) {
- /*Chaozhong:BTIF re-init failed? what to do*/
- i_ret = _btif_state_set(p_btif, B_S_OFF);
- }
- }
- }
- }
- } else
- i_ret = -1;
- BTIF_STATE_RELEASE(p_btif);
- return i_ret;
- }
- static int mtk_btif_drv_suspend(struct device *dev)
- {
- struct platform_device *pdev = to_platform_device(dev);
- pm_message_t state = PMSG_SUSPEND;
- return mtk_btif_suspend(pdev, state);
- }
- static int mtk_btif_drv_resume(struct device *dev)
- {
- struct platform_device *pdev = to_platform_device(dev);
- return mtk_btif_resume(pdev);
- }
- static int mtk_btif_suspend(struct platform_device *pdev, pm_message_t state)
- {
- int i_ret = 0;
- p_mtk_btif p_btif = NULL;
- /*Chaozhong: ToDo: to be implement*/
- BTIF_DBG_FUNC("++\n");
- p_btif = platform_get_drvdata(pdev);
- i_ret = _btif_suspend(p_btif);
- BTIF_DBG_FUNC("--, i_ret:%d\n", i_ret);
- return i_ret;
- }
- int _btif_restore_noirq(p_mtk_btif p_btif)
- {
- int i_ret = 0;
- /*BTIF IRQ restore no irq*/
- i_ret = hal_btif_pm_ops(p_btif->p_btif_info, BTIF_PM_RESTORE_NOIRQ);
- if (0 == i_ret) {
- BTIF_INFO_FUNC("BTIF HW IRQ restore succeed\n");
- } else {
- BTIF_INFO_FUNC("BTIF HW IRQ restore failed, i_ret:%d\n", i_ret);
- return i_ret;
- }
- /*BTIF DMA restore no irq*/
- if (p_btif->tx_mode & BTIF_MODE_DMA) {
- i_ret = hal_dma_pm_ops(p_btif->p_tx_dma->p_dma_info,
- BTIF_PM_RESTORE_NOIRQ);
- if (0 == i_ret) {
- BTIF_INFO_FUNC("BTIF Tx DMA IRQ restore succeed\n");
- } else {
- BTIF_INFO_FUNC
- ("BTIF Tx DMA IRQ restore failed, i_ret:%d\n",
- i_ret);
- return i_ret;
- }
- }
- if (p_btif->rx_mode & BTIF_MODE_DMA) {
- i_ret = hal_dma_pm_ops(p_btif->p_rx_dma->p_dma_info,
- BTIF_PM_RESTORE_NOIRQ);
- if (0 == i_ret) {
- BTIF_INFO_FUNC("BTIF Rx DMA IRQ restore succeed\n");
- } else {
- BTIF_INFO_FUNC
- ("BTIF Rx DMA IRQ restore failed, i_ret:%d\n",
- i_ret);
- return i_ret;
- }
- }
- return i_ret;
- }
- static int mtk_btif_restore_noirq(struct device *dev)
- {
- int i_ret = 0;
- struct platform_device *pdev = to_platform_device(dev);
- p_mtk_btif p_btif = platform_get_drvdata(pdev);
- BTIF_INFO_FUNC("++\n");
- if (_btif_state_hold(p_btif))
- return E_BTIF_INTR;
- if (p_btif->enable)
- BTIF_ERR_FUNC("!!!-----------------!BTIF is not closed before IPOH shutdown!!!---------------!\n");
- BUG_ON(p_btif->enable);
- i_ret = _btif_restore_noirq(p_btif);
- BTIF_STATE_RELEASE(p_btif);
- BTIF_INFO_FUNC("--\n");
- return 0;
- }
- int _btif_resume(p_mtk_btif p_btif)
- {
- int i_ret = 0;
- ENUM_BTIF_STATE state = B_S_MAX;
- if (_btif_state_hold(p_btif))
- return E_BTIF_INTR;
- if (NULL != p_btif) {
- state = _btif_state_get(p_btif);
- if (!(p_btif->enable))
- i_ret = 0;
- else if (state == B_S_SUSPEND)
- i_ret = _btif_enter_dpidle(p_btif);
- else
- BTIF_INFO_FUNC
- ("BTIF state: %s before resume, do nothing\n", g_state[state]);
- } else
- i_ret = -1;
- BTIF_STATE_RELEASE(p_btif);
- return i_ret;
- }
- static int mtk_btif_resume(struct platform_device *pdev)
- {
- int i_ret = 0;
- p_mtk_btif p_btif = NULL;
- /*Chaozhong: ToDo: to be implement*/
- BTIF_DBG_FUNC("++\n");
- p_btif = platform_get_drvdata(pdev);
- i_ret = _btif_resume(p_btif);
- BTIF_DBG_FUNC("--, i_ret:%d\n", i_ret);
- return 0;
- }
- /*-----------device node----------------*/
- #if BTIF_CDEV_SUPPORT
- dev_t btif_dev;
- struct class *p_btif_class;
- struct device *p_btif_dev;
- const char *p_btif_dev_name = "btif";
- static struct semaphore wr_mtx;
- static struct semaphore rd_mtx;
- unsigned char wr_buf[2048];
- unsigned char rd_buf[2048];
- static int rx_notify_flag;
- static DECLARE_WAIT_QUEUE_HEAD(btif_wq);
- static int btif_file_open(struct inode *pinode, struct file *pfile);
- static int btif_file_release(struct inode *pinode, struct file *pfile);
- static ssize_t btif_file_read(struct file *pfile,
- char __user *buf, size_t count, loff_t *f_ops);
- static ssize_t btif_file_write(struct file *filp,
- const char __user *buf, size_t count, loff_t *f_pos);
- static long btif_unlocked_ioctl(struct file *filp, unsigned int cmd,
- unsigned long arg);
- #ifdef CONFIG_COMPAT
- static long btif_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
- #endif
- static struct cdev btif_dev_c;
- static wait_queue_head_t btif_read_inq; /* read queues */
- const struct file_operations mtk_btif_fops = {
- .owner = THIS_MODULE,
- .open = btif_file_open,
- .release = btif_file_release,
- .read = btif_file_read,
- .write = btif_file_write,
- .unlocked_ioctl = btif_unlocked_ioctl,
- #ifdef CONFIG_COMPAT
- .compat_ioctl = btif_compat_ioctl,
- #endif
- .poll = btif_poll,
- };
- static int btif_chrdev_init(void)
- {
- int i_ret;
- int i_err;
- /* alloc device number dynamically */
- i_ret = alloc_chrdev_region(&btif_dev, 0, 1, p_btif_dev_name);
- if (i_ret) {
- BTIF_ERR_FUNC("devuce number allocation failed, i_ret:%d\n",
- i_ret);
- } else {
- BTIF_INFO_FUNC("devuce number allocation succeed\n");
- }
- cdev_init(&btif_dev_c, &mtk_btif_fops);
- btif_dev_c.owner = THIS_MODULE;
- i_err = cdev_add(&btif_dev_c, btif_dev, 1);
- if (i_err) {
- BTIF_ERR_FUNC("error add btif dev to kernel, error code:%d\n",
- i_err);
- unregister_chrdev_region(btif_dev, 1);
- btif_dev = 0;
- return -1;
- }
- BTIF_INFO_FUNC("add btif dev to kernel succeed\n");
- p_btif_class = class_create(THIS_MODULE, p_btif_dev_name);
- if (IS_ERR(p_btif_class)) {
- BTIF_ERR_FUNC("error happened when doing class_create\n");
- unregister_chrdev_region(btif_dev, 1);
- btif_dev = 0;
- return -2;
- }
- BTIF_INFO_FUNC("create class for btif succeed\n");
- p_btif_dev = device_create(p_btif_class,
- NULL, btif_dev, 0, p_btif_dev_name);
- if (IS_ERR(p_btif_dev)) {
- BTIF_ERR_FUNC("error happened when doing device_create\n");
- class_destroy(p_btif_class);
- p_btif_class = NULL;
- unregister_chrdev_region(btif_dev, 1);
- btif_dev = 0;
- return -3;
- }
- BTIF_INFO_FUNC("create device for btif succeed\n");
- return 0;
- }
- void btif_rx_notify_cb(void)
- {
- BTIF_DBG_FUNC("++\n");
- rx_notify_flag = 1;
- wake_up(&btif_wq);
- wake_up_interruptible(&btif_read_inq);
- BTIF_DBG_FUNC("--\n");
- }
- unsigned int btif_poll(struct file *filp, poll_table *wait)
- {
- unsigned int mask = 0;
- unsigned int ava_len = 0;
- /* btif_bbs_read(&(g_btif[0].btif_buf), rd_buf, sizeof(rd_buf)); */
- unsigned int wr_idx = g_btif[0].btif_buf.wr_idx;
- /* BTIF_Rx_IRQ_Disable(); */
- ava_len = BBS_COUNT_CUR(&(g_btif[0].btif_buf), wr_idx);
- BTIF_INFO_FUNC("++\n");
- if (0 == ava_len) {
- poll_wait(filp, &btif_read_inq, wait);
- wr_idx = g_btif[0].btif_buf.wr_idx;
- ava_len = BBS_COUNT_CUR(&(g_btif[0].btif_buf), wr_idx);
- /* btif_bbs_read(&(g_btif[0].btif_buf), rd_buf, sizeof(rd_buf)); */
- if (ava_len)
- mask |= POLLIN | POLLRDNORM; /* readable */
- } else {
- mask |= POLLIN | POLLRDNORM; /* readable */
- }
- /*make for writable*/
- mask |= POLLOUT | POLLWRNORM; /* writable */
- BTIF_INFO_FUNC("--, mask:%d\n", mask);
- return mask;
- }
- static int _btif_file_open(void)
- {
- int i_ret = -1;
- p_mtk_btif p_btif = &g_btif[0];
- BTIF_INFO_FUNC("++\n");
- /*Chaozhong: ToDo: to be implement*/
- i_ret = btif_open(p_btif);
- if ((0 != i_ret) && (E_BTIF_ALREADY_OPEN != i_ret)) {
- BTIF_ERR_FUNC("btif_open failed, error code:%d\n", i_ret);
- } else {
- BTIF_INFO_FUNC("btif_open succeed\n");
- i_ret = 0;
- }
- /*semaphore for read and write operation init*/
- sema_init(&wr_mtx, 1);
- sema_init(&rd_mtx, 1);
- /*buffer for read and write init*/
- memset(wr_buf, 0, sizeof(wr_buf));
- memset(rd_buf, 0, sizeof(rd_buf));
- init_waitqueue_head(&(btif_read_inq));
- btif_rx_notify_reg(p_btif, btif_rx_notify_cb);
- BTIF_INFO_FUNC("--\n");
- return i_ret;
- }
- static int _btif_file_close(void)
- {
- int i_ret = -1;
- BTIF_INFO_FUNC("++\n");
- /*Chaozhong: ToDo: to be implement*/
- i_ret = btif_close(&g_btif[0]);
- if (0 != i_ret)
- BTIF_ERR_FUNC("btif_close failed, error code:%d\n", i_ret);
- else
- BTIF_INFO_FUNC("btif_close succeed\n");
- BTIF_INFO_FUNC("--\n");
- return i_ret;
- }
- static int btif_file_open(struct inode *pinode, struct file *pfile)
- {
- int i_ret = -1;
- BTIF_INFO_FUNC("pid:%d\n", current->pid);
- i_ret = 0;
- return i_ret;
- }
- static int btif_file_release(struct inode *pinode, struct file *pfile)
- {
- int i_ret = -1;
- BTIF_INFO_FUNC("pid:%d\n", current->pid);
- i_ret = 0;
- return i_ret;
- }
- static ssize_t btif_file_read(struct file *pfile,
- char __user *buf, size_t count, loff_t *f_ops)
- {
- int i_ret = 0;
- int rd_len = 0;
- BTIF_INFO_FUNC("++\n");
- down(&rd_mtx);
- rd_len = btif_bbs_read(&(g_btif[0].btif_buf), rd_buf, sizeof(rd_buf));
- while (0 == rd_len) {
- if (pfile->f_flags & O_NONBLOCK)
- break;
- wait_event(btif_wq, rx_notify_flag != 0);
- rx_notify_flag = 0;
- rd_len =
- btif_bbs_read(&(g_btif[0].btif_buf), rd_buf,
- sizeof(rd_buf));
- }
- if (0 == rd_len)
- i_ret = 0;
- else if ((0 < rd_len) && (0 == copy_to_user(buf, rd_buf, rd_len)))
- i_ret = rd_len;
- else
- i_ret = -EFAULT;
- up(&rd_mtx);
- BTIF_INFO_FUNC("--, i_ret:%d\n", i_ret);
- return i_ret;
- }
- ssize_t btif_file_write(struct file *filp,
- const char __user *buf, size_t count, loff_t *f_pos)
- {
- int i_ret = 0;
- int copy_size = 0;
- copy_size = count > sizeof(wr_buf) ? sizeof(wr_buf) : count;
- BTIF_INFO_FUNC("++\n");
- down(&wr_mtx);
- if (copy_from_user(&wr_buf[0], &buf[0], copy_size))
- i_ret = -EFAULT;
- else
- i_ret = btif_send_data(&g_btif[0], wr_buf, copy_size);
- up(&wr_mtx);
- BTIF_INFO_FUNC("--, i_ret:%d\n", i_ret);
- return i_ret;
- }
- #ifdef CONFIG_COMPAT
- long btif_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
- {
- long ret;
- BTIF_INFO_FUNC("cmd[0x%x]\n", cmd);
- ret = btif_unlocked_ioctl(filp, cmd, arg);
- return ret;
- }
- #endif
- long btif_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
- {
- #define BTIF_IOC_MAGIC 0xb0
- #define BTIF_IOCTL_OPEN _IOW(BTIF_IOC_MAGIC, 1, int)
- #define BTIF_IOCTL_CLOSE _IOW(BTIF_IOC_MAGIC, 2, int)
- #define BTIF_IOCTL_LPBK_CTRL _IOWR(BTIF_IOC_MAGIC, 3, int)
- #define BTIF_IOCTL_LOG_FUNC_CTRL _IOWR(BTIF_IOC_MAGIC, 4, int)
- #define BTIF_IOCTL_RT_LOG_CTRL _IOWR(BTIF_IOC_MAGIC, 5, int)
- #define BTIF_IOCTL_LOG_DUMP _IOWR(BTIF_IOC_MAGIC, 6, int)
- #define BTIF_IOCTL_REG_DUMP _IOWR(BTIF_IOC_MAGIC, 7, int)
- #define BTIF_IOCTL_DMA_CTRL _IOWR(BTIF_IOC_MAGIC, 8, int)
- long ret = 0;
- /* unsigned char p_buf[NAME_MAX + 1]; */
- p_mtk_btif p_btif = &g_btif[0];
- BTIF_INFO_FUNC("++\n");
- BTIF_DBG_FUNC("cmd (%u), arg (0x%lx)\n", cmd, arg);
- switch (cmd) {
- case BTIF_IOCTL_OPEN:
- ret = _btif_file_open();
- break;
- case BTIF_IOCTL_CLOSE:
- ret = _btif_file_close();
- break;
- case BTIF_IOCTL_LPBK_CTRL:
- ret = btif_lpbk_ctrl(p_btif, 0 == arg ? 0 : 1);
- break;
- case BTIF_IOCTL_LOG_FUNC_CTRL:
- if (0 == arg) {
- ret += btif_log_buf_disable(&p_btif->tx_log);
- ret += btif_log_buf_disable(&p_btif->rx_log);
- } else {
- ret += btif_log_buf_enable(&p_btif->tx_log);
- ret += btif_log_buf_enable(&p_btif->rx_log);
- }
- break;
- case BTIF_IOCTL_RT_LOG_CTRL:
- if (0 == arg) {
- ret += btif_log_output_disable(&p_btif->tx_log);
- ret += btif_log_output_disable(&p_btif->rx_log);
- } else {
- ret += btif_log_output_enable(&p_btif->tx_log);
- ret += btif_log_output_enable(&p_btif->rx_log);
- }
- break;
- case BTIF_IOCTL_LOG_DUMP:
- ret += btif_log_buf_dmp_out(&p_btif->tx_log);
- ret += btif_log_buf_dmp_out(&p_btif->rx_log);
- break;
- case BTIF_IOCTL_REG_DUMP:
- ret += btif_dump_reg(p_btif);
- break;
- case BTIF_IOCTL_DMA_CTRL:
- if (0 == arg) {
- ret += btif_tx_dma_mode_set(0);
- ret += btif_rx_dma_mode_set(0);
- } else {
- ret += btif_tx_dma_mode_set(1);
- ret += btif_rx_dma_mode_set(1);
- }
- break;
- default:
- BTIF_INFO_FUNC("unknown cmd(%d)\n", cmd);
- ret = -2;
- break;
- }
- BTIF_INFO_FUNC("--\n");
- return ret;
- }
- #endif
- /*-----------device property----------------*/
- static ssize_t driver_flag_read(struct device_driver *drv, char *buf)
- {
- return sprintf(buf, "btif driver debug level:%d\n", mtk_btif_dbg_lvl);
- }
- static ssize_t driver_flag_set(struct device_driver *drv,
- const char *buffer, size_t count)
- {
- char buf[256];
- char *p_buf;
- unsigned long len = count;
- long x = 0;
- long y = 0;
- long z = 0;
- int result = 0;
- char *p_token = NULL;
- char *p_delimiter = " \t";
- BTIF_INFO_FUNC("buffer = %s, count = %zd\n", buffer, count);
- if (len >= sizeof(buf)) {
- BTIF_ERR_FUNC("input handling fail!\n");
- len = sizeof(buf) - 1;
- return -1;
- }
- memcpy(buf, buffer, sizeof(buf));
- p_buf = buf;
- p_token = strsep(&p_buf, p_delimiter);
- if (p_token != NULL) {
- result = kstrtol(p_token, 16, &x);
- BTIF_INFO_FUNC("x = 0x%08x\n\r", x);
- } else
- x = 0;
- /* x = (NULL != p_token) ? kstrtol(p_token, 16, NULL) : 0;*/
- p_token = strsep(&p_buf, "\t\n ");
- if (p_token != NULL) {
- result = kstrtol(p_token, 16, &y);
- BTIF_INFO_FUNC("y = 0x%08x\n\r", y);
- } else
- y = 0;
- p_token = strsep(&p_buf, "\t\n ");
- if (p_token != NULL)
- result = kstrtol(p_token, 16, &z);
- else
- z = 0;
- BTIF_INFO_FUNC("x(0x%08x), y(0x%08x), z(0x%08x)\n\r", x, y, z);
- switch (x) {
- case 1:
- mtk_btif_exp_open_test();
- break;
- case 2:
- mtk_btif_exp_close_test();
- break;
- case 3:
- mtk_btif_exp_write_test();
- break;
- case 4:
- mtk_btif_exp_enter_dpidle_test();
- break;
- case 5:
- mtk_btif_exp_exit_dpidle_test();
- break;
- case 6:
- mtk_btif_exp_suspend_test();
- break;
- case 7:
- mtk_btif_exp_resume_test();
- break;
- case 8:
- if (y > BTIF_LOG_LOUD)
- mtk_btif_dbg_lvl = BTIF_LOG_LOUD;
- else if (y < BTIF_LOG_ERR)
- mtk_btif_dbg_lvl = BTIF_LOG_WARN;
- else
- mtk_btif_dbg_lvl = y;
- BTIF_ERR_FUNC("mtk_btif_dbg_lvl set to %d\n", mtk_btif_dbg_lvl);
- break;
- case 9:
- mtk_btif_exp_open_test();
- mtk_btif_exp_write_test();
- mtk_btif_exp_close_test();
- break;
- case 0xa:
- mtk_btif_exp_log_debug_test(y);
- break;
- case 0xb:
- btif_tx_dma_mode_set(1);
- btif_rx_dma_mode_set(1);
- break;
- case 0xc:
- btif_tx_dma_mode_set(0);
- btif_rx_dma_mode_set(0);
- break;
- case 0xd:
- mtk_btif_exp_restore_noirq_test();
- break;
- case 0xe:
- btif_wakeup_consys_no_id();
- break;
- case 0xf:
- mtk_btif_exp_clock_ctrl(y);
- break;
- case 0x10:
- y = y > G_MAX_PKG_LEN ? G_MAX_PKG_LEN : y;
- y = y < 1024 ? 1024 : y;
- BTIF_INFO_FUNC("g_max_pkg_len is set to %d\n", y);
- g_max_pkg_len = y;
- break;
- case 0x11:
- y = y > BTIF_RX_BUFFER_SIZE ? BTIF_RX_BUFFER_SIZE : y;
- y = y < 1024 ? 1024 : y;
- BTIF_INFO_FUNC("g_max_pding_data_size is set to %d\n", y);
- g_max_pding_data_size = y;
- break;
- default:
- mtk_btif_exp_open_test();
- mtk_btif_exp_write_stress_test(3030, 1);
- mtk_btif_exp_close_test();
- BTIF_WARN_FUNC("not supported.\n");
- break;
- }
- return count;
- }
- static DRIVER_ATTR(flag, S_IRUGO | S_IWUSR, driver_flag_read, driver_flag_set);
- /*-----------End of platform bus related operation APIs------------*/
- /*-----------------------platform driver ----------------*/
- int _btif_irq_reg(P_MTK_BTIF_IRQ_STR p_irq,
- mtk_btif_irq_handler irq_handler, void *data)
- {
- int i_ret = -1;
- unsigned int irq_id;
- unsigned int flag;
- if ((NULL == p_irq) || (NULL == irq_handler))
- return E_BTIF_INVAL_PARAM;
- if (!(p_irq->is_irq_sup)) {
- BTIF_WARN_FUNC("%s is not supported\n", p_irq->name);
- return 0;
- }
- irq_id = p_irq->irq_id;
- #ifdef CONFIG_OF
- flag = p_irq->irq_flags;
- #else
- switch (p_irq->sens_type) {
- case IRQ_SENS_EDGE:
- if (IRQ_EDGE_FALL == p_irq->edge_type)
- flag = IRQF_TRIGGER_FALLING;
- else if (IRQ_EDGE_RAISE == p_irq->edge_type)
- flag = IRQF_TRIGGER_RISING;
- else if (IRQ_EDGE_BOTH == p_irq->edge_type)
- flag = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING;
- else
- /*make this as default type */
- flag = IRQF_TRIGGER_FALLING;
- break;
- case IRQ_SENS_LVL:
- if (IRQ_LVL_LOW == p_irq->lvl_type)
- flag = IRQF_TRIGGER_LOW;
- else if (IRQ_LVL_HIGH == p_irq->lvl_type)
- flag = IRQF_TRIGGER_HIGH;
- else
- /*make this as default type */
- flag = IRQF_TRIGGER_LOW;
- break;
- default:
- /*make this as default type */
- flag = IRQF_TRIGGER_LOW;
- break;
- }
- #endif
- p_irq->p_irq_handler = irq_handler;
- i_ret = request_irq(irq_id,
- (irq_handler_t) irq_handler,
- flag, p_irq->name, data);
- if (i_ret)
- return i_ret;
- p_irq->reg_flag = true;
- return 0;
- }
- int _btif_irq_free(P_MTK_BTIF_IRQ_STR p_irq, void *data)
- {
- int i_ret = 0;
- unsigned int eint_num = p_irq->irq_id;
- if ((p_irq->is_irq_sup) && (p_irq->reg_flag)) {
- _btif_irq_ctrl(p_irq, false);
- free_irq(eint_num, data);
- p_irq->reg_flag = false;
- }
- /*do nothing for this operation*/
- return i_ret;
- }
- int _btif_irq_ctrl(P_MTK_BTIF_IRQ_STR p_irq, bool en)
- {
- unsigned int eint_num = p_irq->irq_id;
- if (en)
- enable_irq(eint_num);
- else
- disable_irq_nosync(eint_num);
- return 0;
- }
- int _btif_irq_ctrl_sync(P_MTK_BTIF_IRQ_STR p_irq, bool en)
- {
- unsigned int eint_num = p_irq->irq_id;
- if (en)
- enable_irq(eint_num);
- else
- disable_irq(eint_num);
- return 0;
- }
- irqreturn_t btif_irq_handler(int irq, void *data)
- {
- /*search BTIF? just use index 0*/
- /*Chaozhong: do we need lock here?*/
- p_mtk_btif p_btif = (p_mtk_btif) data; /*&(g_btif[index]); */
- BTIF_DBG_FUNC("++, p_btif(0x%p)\n", data);
- _btif_irq_ctrl(p_btif->p_btif_info->p_irq, false);
- #if MTK_BTIF_ENABLE_CLK_REF_COUNTER
- hal_btif_clk_ctrl(p_btif->p_btif_info, CLK_OUT_ENABLE);
- #endif
- hal_btif_irq_handler(p_btif->p_btif_info, NULL, 0);
- #if MTK_BTIF_ENABLE_CLK_REF_COUNTER
- hal_btif_clk_ctrl(p_btif->p_btif_info, CLK_OUT_DISABLE);
- #endif
- _btif_irq_ctrl(p_btif->p_btif_info->p_irq, true);
- _btif_rx_btm_sched(p_btif);
- BTIF_DBG_FUNC("--\n");
- return IRQ_HANDLED;
- }
- irqreturn_t btif_tx_dma_irq_handler(int irq, void *data)
- {
- /*search BTIF? just use index 0*/
- p_mtk_btif p_btif = (p_mtk_btif) data; /*&(g_btif[index]); */
- p_mtk_btif_dma p_tx_dma = p_btif->p_tx_dma;
- P_MTK_DMA_INFO_STR p_dma_info = p_tx_dma->p_dma_info;
- BTIF_DBG_FUNC("++, p_btif(0x%p)\n", data);
- _btif_irq_ctrl(p_dma_info->p_irq, false);
- #if MTK_BTIF_ENABLE_CLK_REF_COUNTER
- hal_btif_dma_clk_ctrl(p_dma_info, CLK_OUT_ENABLE);
- #endif
- hal_tx_dma_irq_handler(p_dma_info);
- #if MTK_BTIF_ENABLE_CLK_REF_COUNTER
- hal_btif_dma_clk_ctrl(p_dma_info, CLK_OUT_DISABLE);
- #endif
- _btif_irq_ctrl(p_dma_info->p_irq, true);
- BTIF_DBG_FUNC("--\n");
- return IRQ_HANDLED;
- }
- irqreturn_t btif_rx_dma_irq_handler(int irq, void *data)
- {
- /*search BTIF? just use index 0*/
- p_mtk_btif p_btif = (p_mtk_btif) data; /*&(g_btif[index]); */
- p_mtk_btif_dma p_rx_dma = p_btif->p_rx_dma;
- P_MTK_DMA_INFO_STR p_rx_dma_info = p_rx_dma->p_dma_info;
- BTIF_DBG_FUNC("++, p_btif(0x%p)\n", data);
- _btif_irq_ctrl(p_rx_dma_info->p_irq, false);
- #if MTK_BTIF_ENABLE_CLK_REF_COUNTER
- hal_btif_clk_ctrl(p_btif->p_btif_info, CLK_OUT_ENABLE);
- hal_btif_dma_clk_ctrl(p_rx_dma_info, CLK_OUT_ENABLE);
- #endif
- hal_rx_dma_irq_handler(p_rx_dma_info, NULL, 0);
- #if MTK_BTIF_ENABLE_CLK_REF_COUNTER
- hal_btif_dma_clk_ctrl(p_rx_dma_info, CLK_OUT_DISABLE);
- hal_btif_clk_ctrl(p_btif->p_btif_info, CLK_OUT_DISABLE);
- #endif
- _btif_irq_ctrl(p_rx_dma_info->p_irq, true);
- _btif_rx_btm_sched(p_btif);
- BTIF_DBG_FUNC("--\n");
- return IRQ_HANDLED;
- }
- unsigned int btif_dma_rx_data_receiver(P_MTK_DMA_INFO_STR p_dma_info,
- unsigned char *p_buf,
- unsigned int buf_len)
- {
- unsigned int index = 0;
- p_mtk_btif p_btif = &(g_btif[index]);
- #if 0
- _btif_dump_memory("<DMA Rx>", p_buf, buf_len);
- #endif
- btif_bbs_write(&(p_btif->btif_buf), p_buf, buf_len);
- /*save DMA Rx packet here*/
- if (0 < buf_len)
- btif_log_buf_dmp_in(&p_btif->rx_log, p_buf, buf_len);
- return 0;
- }
- unsigned int btif_pio_rx_data_receiver(P_MTK_BTIF_INFO_STR p_btif_info,
- unsigned char *p_buf,
- unsigned int buf_len)
- {
- unsigned int index = 0;
- p_mtk_btif p_btif = &(g_btif[index]);
- #if 0
- _btif_dump_memory("<PIO Rx>", p_buf, buf_len);
- #endif
- btif_bbs_write(&(p_btif->btif_buf), p_buf, buf_len);
- /*save PIO Rx packet here*/
- if (0 < buf_len)
- btif_log_buf_dmp_in(&p_btif->rx_log, p_buf, buf_len);
- return 0;
- }
- bool btif_parser_wmt_evt(p_mtk_btif p_btif,
- const char *sub_str,
- unsigned int str_len)
- {
- unsigned int data_cnt = 0;
- unsigned int copy_cnt = 0;
- char *local_buf = NULL;
- bool b_ret = false;
- p_btif_buf_str p_bbs = &(p_btif->btif_buf);
- unsigned int wr_idx = p_bbs->wr_idx;
- unsigned int rd_idx = p_bbs->rd_idx;
- data_cnt = copy_cnt = BBS_COUNT(p_bbs);
- if (data_cnt < str_len) {
- BTIF_WARN_FUNC("there is not enough data for parser,need(%d),have(%d)\n", str_len, data_cnt);
- return false;
- }
- BTIF_INFO_FUNC("data count in bbs buffer:%d,wr_idx(%d),rd_idx(%d)\n", data_cnt, wr_idx, rd_idx);
- local_buf = vmalloc((data_cnt + 3) & ~0x3UL);
- if (!local_buf) {
- BTIF_WARN_FUNC("vmalloc memory fail\n");
- return false;
- }
- if (wr_idx >= rd_idx) {
- memcpy(local_buf, BBS_PTR(p_bbs, rd_idx), copy_cnt);
- } else {
- unsigned int tail_len = BBS_SIZE(p_bbs) - rd_idx;
- BTIF_INFO_FUNC("tail_Len(%d)\n", tail_len);
- memcpy(local_buf, BBS_PTR(p_bbs, rd_idx), tail_len);
- memcpy(local_buf + tail_len, BBS_PTR(p_bbs, 0), copy_cnt - tail_len);
- }
- do {
- int i = 0;
- int j = 0;
- int k = 0;
- int d = 0;
- BTIF_INFO_FUNC("sub_str_len:%d\n", str_len);
- for (i = 0; i < copy_cnt; i++) {
- BTIF_DBG_FUNC("i:%d\n", i);
- k = i;
- while (1) {
- if ((j >= str_len) || (k >= copy_cnt) || (sub_str[j++] != local_buf[k++]))
- break;
- }
- if (j == str_len) {
- for (d = i; d < (str_len + i); d++)
- BTIF_INFO_FUNC("0x%2x", local_buf[d]);
- BTIF_INFO_FUNC("find sub str index:%d\n", i);
- b_ret = true;
- break;
- }
- if (j < str_len)
- j = 0;
- }
- } while (0);
- vfree(local_buf);
- return b_ret;
- }
- int _btif_controller_tx_setup(p_mtk_btif p_btif)
- {
- int i_ret = -1;
- if (BTIF_MODE_DMA == p_btif->tx_mode) {
- i_ret = _btif_tx_dma_setup(p_btif);
- if (i_ret) {
- BTIF_ERR_FUNC("_btif_tx_dma_setup failed,i_ret(%d),",
- "set tx to PIO mode\n", i_ret);
- i_ret = _btif_tx_pio_setup(p_btif);
- }
- } else
- /*enable Tx PIO mode*/
- i_ret = _btif_tx_pio_setup(p_btif);
- return i_ret;
- }
- int _btif_controller_tx_free(p_mtk_btif p_btif)
- {
- int i_ret = -1;
- if (BTIF_MODE_DMA == p_btif->tx_mode) {
- i_ret = _btif_tx_dma_free(p_btif);
- if (i_ret) {
- BTIF_ERR_FUNC("_btif_tx_dma_free failed, i_ret(%d)\n",
- i_ret);
- }
- } else {
- /*do nothing for Tx PIO mode*/
- }
- return i_ret;
- }
- int _btif_controller_rx_setup(p_mtk_btif p_btif)
- {
- int i_ret = -1;
- if (BTIF_MODE_DMA == p_btif->rx_mode) {
- i_ret = _btif_rx_dma_setup(p_btif);
- if (i_ret) {
- BTIF_ERR_FUNC("_btif_tx_dma_setup failed, i_ret(%d),",
- "set tx to PIO mode\n", i_ret);
- i_ret = _btif_rx_pio_setup(p_btif);
- }
- } else {
- /*enable Tx PIO mode*/
- i_ret = _btif_rx_pio_setup(p_btif);
- }
- return i_ret;
- }
- int _btif_controller_rx_free(p_mtk_btif p_btif)
- {
- int i_ret = -1;
- if (BTIF_MODE_DMA == p_btif->rx_mode) {
- i_ret = _btif_rx_dma_free(p_btif);
- if (i_ret) {
- BTIF_ERR_FUNC("_btif_rx_dma_free failed, i_ret(%d)\n",
- i_ret);
- }
- } else {
- /*do nothing for Rx PIO mode*/
- }
- return i_ret;
- }
- int _btif_tx_pio_setup(p_mtk_btif p_btif)
- {
- int i_ret = -1;
- P_MTK_BTIF_INFO_STR p_btif_info = p_btif->p_btif_info;
- /*set Tx to PIO mode*/
- p_btif->tx_mode = BTIF_MODE_PIO;
- /*enable Tx PIO mode*/
- i_ret = hal_btif_tx_mode_ctrl(p_btif_info, BTIF_MODE_PIO);
- return i_ret;
- }
- int _btif_rx_pio_setup(p_mtk_btif p_btif)
- {
- int i_ret = -1;
- P_MTK_BTIF_INFO_STR p_btif_info = p_btif->p_btif_info;
- P_MTK_BTIF_IRQ_STR p_btif_irq = p_btif_info->p_irq;
- p_btif->rx_mode = BTIF_MODE_PIO;
- /*Enable Rx IRQ*/
- _btif_irq_ctrl(p_btif_irq, true);
- /*enable Rx PIO mode*/
- i_ret = hal_btif_rx_mode_ctrl(p_btif_info, BTIF_MODE_PIO);
- return i_ret;
- }
- int _btif_rx_dma_setup(p_mtk_btif p_btif)
- {
- int i_ret = -1;
- P_MTK_BTIF_INFO_STR p_btif_info = NULL;
- P_MTK_BTIF_IRQ_STR p_btif_irq = NULL;
- P_MTK_DMA_INFO_STR p_dma_info = p_btif->p_rx_dma->p_dma_info;
- p_btif_info = p_btif->p_btif_info;
- p_btif_irq = p_dma_info->p_irq;
- /*vFIFO reset*/
- hal_btif_vfifo_reset(p_dma_info);
- i_ret = hal_btif_dma_clk_ctrl(p_dma_info, CLK_OUT_ENABLE);
- if (i_ret) {
- BTIF_ERR_FUNC("hal_btif_dma_clk_ctrl failed, i_ret(%d),",
- "set rx to pio mode\n", i_ret);
- /*DMA control failed set Rx to PIO mode*/
- return _btif_rx_pio_setup(p_btif);
- }
- /*hardware init*/
- hal_btif_dma_hw_init(p_dma_info);
- hal_btif_dma_rx_cb_reg(p_dma_info,
- (dma_rx_buf_write) btif_dma_rx_data_receiver);
- /*DMA controller enable*/
- i_ret = hal_btif_dma_ctrl(p_dma_info, DMA_CTRL_ENABLE);
- if (i_ret) {
- BTIF_ERR_FUNC("hal_btif_dma_ctrl failed, i_ret(%d),",
- "set rx to pio mode\n", i_ret);
- hal_btif_dma_clk_ctrl(p_dma_info, CLK_OUT_DISABLE);
- /*DMA control failed set Rx to PIO mode*/
- i_ret = _btif_rx_pio_setup(p_btif);
- } else {
- /*enable Rx DMA mode*/
- hal_btif_rx_mode_ctrl(p_btif_info, BTIF_MODE_DMA);
- /*DMA Rx IRQ register*/
- _btif_irq_reg(p_btif_irq, btif_rx_dma_irq_handler, p_btif);
- #if 0
- /*Enable DMA Rx IRQ*/
- _btif_irq_ctrl(p_btif_irq, true);
- #endif
- BTIF_DBG_FUNC("succeed\n");
- }
- return i_ret;
- }
- int _btif_rx_dma_free(p_mtk_btif p_btif)
- {
- P_MTK_DMA_INFO_STR p_dma_info = p_btif->p_rx_dma->p_dma_info;
- P_MTK_BTIF_IRQ_STR p_irq = p_btif->p_rx_dma->p_dma_info->p_irq;
- hal_btif_dma_rx_cb_reg(p_dma_info, (dma_rx_buf_write) NULL);
- _btif_irq_free(p_irq, p_btif);
- /*disable BTIF Rx DMA channel*/
- hal_btif_dma_ctrl(p_dma_info, DMA_CTRL_DISABLE);
- /*disable clock output*/
- return hal_btif_dma_clk_ctrl(p_dma_info, CLK_OUT_DISABLE);
- }
- int _btif_tx_dma_setup(p_mtk_btif p_btif)
- {
- int i_ret = -1;
- P_MTK_BTIF_INFO_STR p_btif_info = p_btif->p_btif_info;
- P_MTK_DMA_INFO_STR p_dma_info = p_btif->p_tx_dma->p_dma_info;
- P_MTK_BTIF_IRQ_STR p_btif_irq = p_dma_info->p_irq;
- /*vFIFO reset*/
- hal_btif_vfifo_reset(p_dma_info);
- i_ret = hal_btif_dma_clk_ctrl(p_dma_info, CLK_OUT_ENABLE);
- if (i_ret) {
- BTIF_ERR_FUNC("hal_btif_dma_clk_ctrl failed, i_ret(%d)\n",
- i_ret);
- return i_ret;
- }
- /*DMA controller setup*/
- hal_btif_dma_hw_init(p_dma_info);
- /*DMA HW Enable*/
- i_ret = hal_btif_dma_ctrl(p_dma_info, DMA_CTRL_ENABLE);
- if (i_ret) {
- BTIF_ERR_FUNC("hal_btif_dma_ctrl failed, i_ret(%d),",
- "set tx to pio mode\n", i_ret);
- #if !(MTK_BTIF_ENABLE_CLK_REF_COUNTER)
- hal_btif_dma_clk_ctrl(p_dma_info, CLK_OUT_DISABLE);
- #endif
- _btif_tx_pio_setup(p_btif);
- } else {
- hal_btif_tx_mode_ctrl(p_btif_info, BTIF_MODE_DMA);
- /*DMA Tx IRQ register*/
- _btif_irq_reg(p_btif_irq, btif_tx_dma_irq_handler, p_btif);
- #if 0
- /*disable DMA Tx IRQ*/
- _btif_irq_ctrl(p_btif_irq, false);
- #endif
- BTIF_DBG_FUNC("succeed\n");
- }
- return i_ret;
- }
- int _btif_tx_dma_free(p_mtk_btif p_btif)
- {
- P_MTK_DMA_INFO_STR p_dma_info = p_btif->p_tx_dma->p_dma_info;
- P_MTK_BTIF_IRQ_STR p_irq = p_btif->p_tx_dma->p_dma_info->p_irq;
- _btif_irq_free(p_irq, p_btif);
- /*disable BTIF Tx DMA channel*/
- hal_btif_dma_ctrl(p_dma_info, DMA_CTRL_DISABLE);
- /*disable clock output*/
- return hal_btif_dma_clk_ctrl(p_dma_info, CLK_OUT_DISABLE);
- }
- int btif_lpbk_ctrl(p_mtk_btif p_btif, bool flag)
- {
- int i_ret = -1;
- /*hold state mechine lock*/
- if (_btif_state_hold(p_btif))
- return E_BTIF_INTR;
- #if 0
- state = _btif_state_get(p_btif);
- if (p_btif->enable && B_S_ON == state)
- i_ret = _btif_lpbk_ctrl(p_btif, flag);
- else
- i_ret = E_BTIF_INVAL_STATE;
- #endif
- i_ret = _btif_exit_dpidle(p_btif);
- if (0 == i_ret)
- i_ret = _btif_lpbk_ctrl(p_btif, flag);
- else
- i_ret = E_BTIF_INVAL_STATE;
- BTIF_STATE_RELEASE(p_btif);
- return i_ret;
- }
- int _btif_lpbk_ctrl(p_mtk_btif p_btif, bool flag)
- {
- int i_ret = -1;
- if (flag) {
- i_ret = hal_btif_loopback_ctrl(p_btif->p_btif_info, true);
- BTIF_DBG_FUNC("loopback function enabled\n");
- } else {
- i_ret = hal_btif_loopback_ctrl(p_btif->p_btif_info, false);
- BTIF_DBG_FUNC("loopback function disabled\n");
- }
- if (0 == i_ret)
- p_btif->lpbk_flag = flag;
- return i_ret;
- }
- int btif_clock_ctrl(p_mtk_btif p_btif, int en)
- {
- int i_ret = 0;
- P_MTK_BTIF_INFO_STR p_btif_info = p_btif->p_btif_info;
- ENUM_CLOCK_CTRL ctrl_flag = en == 0 ? CLK_OUT_DISABLE : CLK_OUT_ENABLE;
- i_ret = hal_btif_clk_ctrl(p_btif_info, ctrl_flag);
- if (BTIF_MODE_DMA == p_btif->rx_mode)
- i_ret += hal_btif_dma_clk_ctrl(p_btif->p_rx_dma->p_dma_info, ctrl_flag);
- if (BTIF_MODE_DMA == p_btif->tx_mode)
- i_ret += hal_btif_dma_clk_ctrl(p_btif->p_tx_dma->p_dma_info, ctrl_flag);
- return i_ret;
- }
- int _btif_controller_setup(p_mtk_btif p_btif)
- {
- int i_ret = -1;
- P_MTK_BTIF_INFO_STR p_btif_info = p_btif->p_btif_info;
- P_MTK_BTIF_IRQ_STR p_btif_irq = p_btif_info->p_irq;
- /*BTIF rx buffer init*/
- /* memset(p_btif->rx_buf, 0, BTIF_RX_BUFFER_SIZE); */
- BBS_INIT(&(p_btif->btif_buf));
- /************************************************/
- hal_btif_rx_cb_reg(p_btif_info,
- (btif_rx_buf_write) btif_pio_rx_data_receiver);
- i_ret = hal_btif_clk_ctrl(p_btif_info, CLK_OUT_ENABLE);
- if (i_ret) {
- BTIF_ERR_FUNC("hal_btif_clk_ctrl failed, i_ret(%d)\n", i_ret);
- return i_ret;
- }
- /*BTIF controller init*/
- i_ret = hal_btif_hw_init(p_btif_info);
- if (i_ret) {
- hal_btif_clk_ctrl(p_btif_info, CLK_OUT_DISABLE);
- BTIF_ERR_FUNC("hal_btif_hw_init failed, i_ret(%d)\n", i_ret);
- return i_ret;
- }
- _btif_lpbk_ctrl(p_btif, p_btif->lpbk_flag);
- /*BTIF IRQ register*/
- i_ret = _btif_irq_reg(p_btif_irq, btif_irq_handler, p_btif);
- if (i_ret) {
- hal_btif_clk_ctrl(p_btif_info, CLK_OUT_DISABLE);
- BTIF_ERR_FUNC("_btif_irq_reg failed, i_ret(%d)\n", i_ret);
- return i_ret;
- }
- /*disable IRQ*/
- _btif_irq_ctrl(p_btif_irq, false);
- i_ret = 0;
- BTIF_DBG_FUNC("succeed\n");
- return i_ret;
- }
- int _btif_controller_free(p_mtk_btif p_btif)
- {
- /*No need to set BTIF to PIO mode, only enable BTIF CG*/
- hal_btif_rx_cb_reg(p_btif->p_btif_info, (btif_rx_buf_write) NULL);
- _btif_irq_free(p_btif->p_btif_info->p_irq, p_btif);
- return hal_btif_clk_ctrl(p_btif->p_btif_info, CLK_OUT_DISABLE);
- }
- int _btif_init(p_mtk_btif p_btif)
- {
- int i_ret = 0;
- i_ret = _btif_controller_setup(p_btif);
- if (i_ret) {
- BTIF_ERR_FUNC("_btif_controller_init failed, i_ret(%d)\n",
- i_ret);
- _btif_dpidle_notify_ctrl(p_btif, BTIF_DPIDLE_ENABLE);
- BTIF_STATE_RELEASE(p_btif);
- return i_ret;
- }
- i_ret = _btif_controller_tx_setup(p_btif);
- if (i_ret) {
- BTIF_ERR_FUNC("_btif_controller_tx_setup failed, i_ret(%d)\n",
- i_ret);
- _btif_controller_free(p_btif);
- _btif_dpidle_notify_ctrl(p_btif, BTIF_DPIDLE_ENABLE);
- BTIF_STATE_RELEASE(p_btif);
- return i_ret;
- }
- i_ret = _btif_controller_rx_setup(p_btif);
- if (i_ret) {
- BTIF_ERR_FUNC("_btif_controller_tx_setup failed, i_ret(%d)\n",
- i_ret);
- _btif_controller_tx_free(p_btif);
- _btif_controller_free(p_btif);
- _btif_dpidle_notify_ctrl(p_btif, BTIF_DPIDLE_ENABLE);
- BTIF_STATE_RELEASE(p_btif);
- return i_ret;
- }
- return i_ret;
- }
- int btif_open(p_mtk_btif p_btif)
- {
- int i_ret = -1;
- if (p_btif->enable)
- return E_BTIF_ALREADY_OPEN;
- /*hold state mechine lock*/
- if (_btif_state_hold(p_btif))
- return E_BTIF_INTR;
- /*disable deepidle*/
- _btif_dpidle_notify_ctrl(p_btif, BTIF_DPIDLE_DISABLE);
- i_ret = _btif_init(p_btif);
- if (0 == i_ret) {
- /*set BTIF's enable flag*/
- p_btif->enable = true;
- _btif_state_set(p_btif, B_S_ON);
- } else {
- _btif_dpidle_notify_ctrl(p_btif, BTIF_DPIDLE_ENABLE);
- }
- btif_log_buf_reset(&p_btif->tx_log);
- btif_log_buf_reset(&p_btif->rx_log);
- BTIF_STATE_RELEASE(p_btif);
- BTIF_DBG_FUNC("BTIF's Tx Mode:%d, Rx Mode(%d)\n",
- p_btif->tx_mode, p_btif->rx_mode);
- return i_ret;
- }
- int btif_close(p_mtk_btif p_btif)
- {
- int i_ret = 0;
- if (!(p_btif->enable))
- return E_BTIF_NOT_OPEN;
- /*hold state mechine lock*/
- if (_btif_state_hold(p_btif))
- return E_BTIF_INTR;
- /*always set state back to B_S_ON before do close operation*/
- _btif_exit_dpidle(p_btif);
- /*set BTIF's state to disable state*/
- p_btif->enable = false;
- _btif_controller_free(p_btif);
- _btif_controller_tx_free(p_btif);
- _btif_controller_rx_free(p_btif);
- /*reset BTIF's rx_cb function*/
- p_btif->rx_cb = NULL;
- p_btif->rx_notify = NULL;
- p_btif->lpbk_flag = false;
- /*set state mechine to B_S_OFF*/
- _btif_state_set(p_btif, B_S_OFF);
- btif_log_buf_disable(&p_btif->tx_log);
- btif_log_buf_disable(&p_btif->rx_log);
- BTIF_STATE_RELEASE(p_btif);
- return i_ret;
- }
- int _btif_exit_dpidle(p_mtk_btif p_btif)
- {
- int i_ret = -1;
- ENUM_BTIF_STATE state = B_S_MAX;
- state = _btif_state_get(p_btif);
- switch (state) {
- case B_S_DPIDLE:
- i_ret = _btif_exit_dpidle_from_dpidle(p_btif);
- break;
- case B_S_SUSPEND:
- /*in suspend state, need to do reinit of btif*/
- i_ret = _btif_exit_dpidle_from_sus(p_btif);
- break;
- case B_S_OFF:
- i_ret = _btif_init(p_btif);
- break;
- case B_S_ON:
- i_ret = 0; /* for btif_close case */
- break;
- default:
- i_ret = E_BTIF_INVAL_PARAM;
- BTIF_INFO_FUNC("invalid state change:%d->\n", state, B_S_ON);
- break;
- }
- if (0 == i_ret)
- i_ret = _btif_state_set(p_btif, B_S_ON);
- return i_ret;
- }
- int btif_exit_dpidle(p_mtk_btif p_btif)
- {
- int i_ret = 0;
- /*hold state mechine lock*/
- if (_btif_state_hold(p_btif))
- return E_BTIF_INTR;
- i_ret = _btif_exit_dpidle(p_btif);
- BTIF_STATE_RELEASE(p_btif);
- return i_ret;
- }
- int _btif_enter_dpidle(p_mtk_btif p_btif)
- {
- int i_ret = 0;
- ENUM_BTIF_STATE state = B_S_MAX;
- state = _btif_state_get(p_btif);
- if (B_S_ON == state) {
- i_ret = _btif_enter_dpidle_from_on(p_btif);
- } else if (B_S_SUSPEND == state) {
- /*do reinit and enter deepidle*/
- i_ret = _btif_enter_dpidle_from_sus(p_btif);
- } else if (B_S_DPIDLE == state) {
- /*do nothing*/
- i_ret = 0;
- } else {
- BTIF_WARN_FUNC("operation is not allowed, current state:%d\n",
- state);
- i_ret = E_BTIF_INVAL_STATE;
- }
- /*anyway, set to B_S_DPIDLE state*/
- if (0 == i_ret)
- i_ret = _btif_state_set(p_btif, B_S_DPIDLE);
- return i_ret;
- }
- int btif_enter_dpidle(p_mtk_btif p_btif)
- {
- int i_ret = 0;
- /*hold state mechine lock*/
- if (_btif_state_hold(p_btif))
- return E_BTIF_INTR;
- i_ret = _btif_enter_dpidle(p_btif);
- BTIF_STATE_RELEASE(p_btif);
- return i_ret;
- }
- int _btif_exit_dpidle_from_dpidle(p_mtk_btif p_btif)
- {
- int i_ret = 0;
- /*in dpidle state, only need to open related clock*/
- if (p_btif->tx_mode == BTIF_MODE_DMA) {
- /*enable BTIF Tx DMA's clock*/
- i_ret += hal_btif_dma_clk_ctrl(p_btif->p_tx_dma->p_dma_info,
- CLK_OUT_ENABLE);
- }
- if (p_btif->rx_mode == BTIF_MODE_DMA) {
- /*enable BTIF Rx DMA's clock*/
- i_ret += hal_btif_dma_clk_ctrl(p_btif->p_rx_dma->p_dma_info,
- CLK_OUT_ENABLE);
- }
- /*enable BTIF's clock*/
- i_ret += hal_btif_clk_ctrl(p_btif->p_btif_info, CLK_OUT_ENABLE);
- if (0 != i_ret)
- BTIF_WARN_FUNC("failed, i_ret:%d\n", i_ret);
- return i_ret;
- }
- int _btif_exit_dpidle_from_sus(p_mtk_btif p_btif)
- {
- /*in suspend state, need to do driver re-init*/
- int i_ret = _btif_init(p_btif);
- return i_ret;
- }
- int _btif_enter_dpidle_from_sus(p_mtk_btif p_btif)
- {
- /*do driiver reinit*/
- int i_ret = _btif_init(p_btif);
- if (0 == i_ret)
- i_ret = _btif_enter_dpidle_from_on(p_btif);
- return i_ret;
- }
- int _btif_enter_dpidle_from_on(p_mtk_btif p_btif)
- {
- #define MAX_WAIT_TIME_MS 5000
- /*this max wait time cannot exceed 12s,
- because dpm will monitor each device's
- resume/suspend process by start up a watch dog timer of 12s
- incase of one driver's suspend/resume process block other device's suspend/resume
- */
- int i_ret = 0;
- unsigned int retry = 0;
- unsigned int wait_period = 1;
- unsigned int max_retry = MAX_WAIT_TIME_MS / wait_period;
- struct timeval timer_start;
- struct timeval timer_now;
- do_gettimeofday(&timer_start);
- while ((!_btif_is_tx_complete(p_btif)) && (retry < max_retry)) {
- do_gettimeofday(&timer_now);
- if ((MAX_WAIT_TIME_MS/1000) <= (timer_now.tv_sec - timer_start.tv_sec)) {
- BTIF_WARN_FUNC("max retry timer expired, timer_start.tv_sec:%d, timer_now.tv_sec:%d,",
- "retry:%d\n", timer_start.tv_sec, timer_now.tv_sec, retry);
- break;
- }
- msleep(wait_period);
- retry++;
- }
- if (retry < max_retry) {
- if (p_btif->tx_mode == BTIF_MODE_DMA) {
- /*disable BTIF Tx DMA's clock*/
- i_ret +=
- hal_btif_dma_clk_ctrl(p_btif->p_tx_dma->p_dma_info,
- CLK_OUT_DISABLE);
- }
- if (p_btif->rx_mode == BTIF_MODE_DMA) {
- /*disable BTIF Rx DMA's clock*/
- i_ret +=
- hal_btif_dma_clk_ctrl(p_btif->p_rx_dma->p_dma_info,
- CLK_OUT_DISABLE);
- }
- /*disable BTIF's clock*/
- i_ret +=
- hal_btif_clk_ctrl(p_btif->p_btif_info, CLK_OUT_DISABLE);
- if (i_ret)
- BTIF_WARN_FUNC("failed, i_ret:%d\n", i_ret);
- } else
- i_ret = -1;
- return i_ret;
- }
- int _btif_dpidle_notify_ctrl(p_mtk_btif p_btif, ENUM_BTIF_DPIDLE_CTRL en_flag)
- {
- /*call WCP's API to control deepidle's enable/disable*/
- if (BTIF_DPIDLE_DISABLE == en_flag)
- hal_btif_pm_ops(p_btif->p_btif_info, BTIF_PM_DPIDLE_DIS);
- else
- hal_btif_pm_ops(p_btif->p_btif_info, BTIF_PM_DPIDLE_EN);
- return 0;
- }
- int btif_rx_cb_reg(p_mtk_btif p_btif, MTK_WCN_BTIF_RX_CB rx_cb)
- {
- if (p_btif->rx_cb) {
- BTIF_WARN_FUNC
- ("rx cb already exist, rewrite from (0x%p) to (0x%p)\n",
- p_btif->rx_cb, rx_cb);
- }
- p_btif->rx_cb = rx_cb;
- return 0;
- }
- int btif_raise_wak_signal(p_mtk_btif p_btif)
- {
- int i_ret = 0;
- P_MTK_BTIF_INFO_STR p_btif_info = p_btif->p_btif_info;
- #if MTK_BTIF_ENABLE_CLK_REF_COUNTER
- hal_btif_clk_ctrl(p_btif->p_btif_info, CLK_OUT_ENABLE);
- #endif
- i_ret = hal_btif_raise_wak_sig(p_btif_info);
- #if MTK_BTIF_ENABLE_CLK_REF_COUNTER
- hal_btif_clk_ctrl(p_btif_info, CLK_OUT_DISABLE);
- #endif
- return i_ret;
- }
- bool _btif_is_tx_complete(p_mtk_btif p_btif)
- {
- bool b_ret = false;
- ENUM_BTIF_MODE tx_mode = p_btif->tx_mode;
- /*make sure BTIF tx finished in PIO mode
- make sure BTIF tx finished and DMA tx finished in DMA mode
- */
- if (BTIF_MODE_DMA == tx_mode) {
- b_ret = hal_dma_is_tx_complete(p_btif->p_tx_dma->p_dma_info);
- if (b_ret == false) {
- BTIF_DBG_FUNC("Tx DMA is not finished\n");
- return b_ret;
- }
- }
- b_ret = hal_btif_is_tx_complete(p_btif->p_btif_info);
- if (b_ret == false) {
- BTIF_DBG_FUNC("BTIF Tx is not finished\n");
- return b_ret;
- }
- b_ret = true;
- return b_ret;
- }
- /*--------------------------------Functions-------------------------------------------*/
- static int _btif_vfifo_init(p_mtk_btif_dma p_dma)
- {
- P_DMA_VFIFO p_vfifo = NULL;
- struct device *dev = NULL;
- p_mtk_btif p_btif = NULL;
- if (NULL == p_dma) {
- BTIF_ERR_FUNC("p_dma is NULL\n");
- return E_BTIF_INVAL_PARAM;
- }
- p_btif = (p_mtk_btif)p_dma->p_btif;
- if (NULL == p_btif) {
- BTIF_ERR_FUNC("invalid parameter: p_btif(0x%p)\n", p_btif);
- return E_BTIF_INVAL_PARAM;
- }
- dev = (struct device *)p_btif->private_data;
- if (NULL == dev)
- BTIF_WARN_FUNC("Null dev pointer!!!!\n");
- p_vfifo = p_dma->p_dma_info->p_vfifo;
- if (NULL != p_vfifo->p_vir_addr) {
- BTIF_ERR_FUNC
- ("BTIF vFIFO memory already allocated, do nothing\n");
- return E_BTIF_BAD_POINTER;
- }
- /*vFIFO memory allocation*/
- p_vfifo->p_vir_addr = dma_zalloc_coherent(dev,
- p_vfifo->vfifo_size,
- &p_vfifo->phy_addr, GFP_DMA | GFP_DMA32);
- if (NULL == p_vfifo->p_vir_addr) {
- BTIF_ERR_FUNC("alloc vFIFO memory for BTIF failed\n");
- return E_BTIF_FAIL;
- }
- if (sizeof(dma_addr_t) == sizeof(unsigned long long))
- BTIF_INFO_FUNC("alloc vFIFO for BTIF succeed in arch64,vir addr:0x%p,",
- "phy addr:0x%llx\n", p_vfifo->p_vir_addr, p_vfifo->phy_addr);
- else
- BTIF_INFO_FUNC("alloc vFIFO for BTIF succeed in arch32,vir addr:0x%p,",
- "phy addr:0x%08x\n", p_vfifo->p_vir_addr, p_vfifo->phy_addr);
- return 0;
- }
- static int _btif_vfifo_deinit(p_mtk_btif_dma p_dma)
- {
- P_DMA_VFIFO p_vfifo = NULL;
- struct device *dev = NULL;
- p_mtk_btif p_btif = NULL;
- if (NULL == p_dma) {
- BTIF_ERR_FUNC("p_dma is NULL\n");
- return E_BTIF_INVAL_PARAM;
- }
- p_btif = (p_mtk_btif)p_dma->p_btif;
- if (NULL == p_btif) {
- BTIF_ERR_FUNC("invalid parameter: p_btif(0x%p)\n", p_btif);
- return E_BTIF_INVAL_PARAM;
- }
- dev = (struct device *)p_btif->private_data;
- if (NULL == dev)
- BTIF_WARN_FUNC("Null dev pointer!!!!\n");
- p_vfifo = p_dma->p_dma_info->p_vfifo;
- /*free DMA memory if allocated successfully before*/
- if (NULL != p_vfifo->p_vir_addr) {
- dma_free_coherent(dev,
- p_vfifo->vfifo_size,
- p_vfifo->p_vir_addr, p_vfifo->phy_addr);
- p_vfifo->p_vir_addr = NULL;
- }
- return 0;
- }
- static int _btif_state_init(p_mtk_btif p_btif)
- {
- if (NULL == p_btif) {
- BTIF_ERR_FUNC("p_btif is NULL\n");
- return E_BTIF_INVAL_PARAM;
- }
- p_btif->state = B_S_OFF;
- mutex_init(&(p_btif->state_mtx));
- return 0;
- }
- static int _btif_state_hold(p_mtk_btif p_btif)
- {
- return mutex_lock_killable(&(p_btif->state_mtx));
- }
- static int _btif_state_set(p_mtk_btif p_btif, ENUM_BTIF_STATE state)
- {
- /*chaozhong: To do: need to finished state mechine here*/
- int i_ret = 0;
- int ori_state = p_btif->state;
- if (ori_state == state) {
- BTIF_INFO_FUNC("already in %s state\n", g_state[state]);
- return i_ret;
- }
- if ((B_S_OFF <= state) && (B_S_MAX > state)) {
- BTIF_DBG_FUNC("%s->%s request\n", g_state[ori_state],
- g_state[state]);
- if (B_S_ON == state)
- _btif_dpidle_notify_ctrl(p_btif, BTIF_DPIDLE_DISABLE);
- switch (ori_state) {
- case B_S_ON:
- /*B_S_ON can only be switched to B_S_OFF, B_S_SUSPEND and B_S_DPIDLE*/
- /*B_S_ON->B_S_OFF : do nothing here*/
- /*B_S_ON->B_S_DPLE : disable clock backup
- BTIF and DMA controller's register if necessary*/
- if (B_S_DPIDLE == state) {
- /*clock controlled id done in _btif_enter_dpidle*/
- p_btif->state = state;
- i_ret = 0;
- } else if (B_S_OFF == state) {
- /*clock controlled is done in btif_close*/
- p_btif->state = state;
- i_ret = 0;
- } else if (B_S_SUSPEND == state) {
- /*clock controlled is done in btif_close*/
- p_btif->state = state;
- i_ret = 0;
- } else {
- BTIF_ERR_FUNC("%s->%s is not allowed\n",
- g_state[ori_state],
- g_state[state]);
- i_ret = E_BTIF_INVAL_STATE;
- }
- break;
- case B_S_DPIDLE:
- /*B_S_DPIDLE can only be switched to B_S_ON and B_S_SUSPEND*/
- /*B_S_DPIDLE-> B_S_ON: do nothing for this moment*/
- /*B_S_DPIDLE-> B_S_SUSPEND:
- disable clock backup BTIF and DMA controller's register if necessary*/
- if (B_S_ON == state) {
- /*clock controlled id done in _btif_exit_dpidle*/
- p_btif->state = state;
- i_ret = 0;
- } else if (B_S_SUSPEND == state) {
- /*clock controlled is done in _btif_exit_dpidle*/
- p_btif->state = state;
- i_ret = 0;
- } else {
- BTIF_ERR_FUNC("%s->%s is not allowed\n",
- g_state[ori_state],
- g_state[state]);
- i_ret = E_BTIF_INVAL_STATE;
- }
- break;
- case B_S_SUSPEND:
- /*B_S_SUSPEND can be switched to B_S_IDLE and B_S_ON*/
- /*reinit BTIF controller and DMA controller*/
- if (B_S_DPIDLE == state) {
- /*system call resume API, do resume operation,
- change to deepidle state*/
- p_btif->state = state;
- i_ret = 0;
- } else if (B_S_ON == state) {
- /*when stp want to send data before
- system do resume operation*/
- p_btif->state = state;
- i_ret = 0;
- } else {
- BTIF_ERR_FUNC("%s->%s is not allowed\n",
- g_state[ori_state],
- g_state[state]);
- i_ret = E_BTIF_INVAL_STATE;
- }
- break;
- case B_S_OFF:{
- /*B_S_OFF can only be switched to B_S_ON*/
- if (B_S_ON == state) {
- /*clock controlled is done in btif_open*/
- p_btif->state = state;
- i_ret = 0;
- } else {
- BTIF_ERR_FUNC("%s->%s is not allowed\n",
- g_state[ori_state],
- g_state[state]);
- i_ret = E_BTIF_INVAL_STATE;
- }
- }
- break;
- default:
- /*no this possibility*/
- BTIF_ERR_FUNC
- ("state change request is not allowed, this should never happen\n");
- break;
- }
- if (B_S_ON != state)
- _btif_dpidle_notify_ctrl(p_btif, BTIF_DPIDLE_ENABLE);
- } else {
- i_ret = E_BTIF_INVAL_PARAM;
- BTIF_ERR_FUNC("invalid state:%d, do nothing\n", state);
- }
- return i_ret;
- }
- static ENUM_BTIF_STATE _btif_state_get(p_mtk_btif p_btif)
- {
- return p_btif->state;
- }
- static int _btif_state_release(p_mtk_btif p_btif)
- {
- int i_ret = 0;
- BTIF_MUTEX_UNLOCK(&(p_btif->state_mtx));
- return i_ret;
- }
- static int _btif_state_deinit(p_mtk_btif p_btif)
- {
- if (NULL == p_btif) {
- BTIF_ERR_FUNC("p_btif is NULL\n");
- return E_BTIF_INVAL_PARAM;
- }
- p_btif->state = B_S_OFF;
- mutex_destroy(&(p_btif->state_mtx));
- return 0;
- }
- static int btif_rx_data_consummer(p_mtk_btif p_btif)
- {
- unsigned int length = 0;
- unsigned char *p_buf = NULL;
- /*get BTIF rx buffer's information*/
- p_btif_buf_str p_bbs = &(p_btif->btif_buf);
- /*wr_idx of btif_buf may be modified in IRQ handler,
- in order not to be effected by case in which irq interrupt this operation,
- we record wr_idx here*/
- unsigned int wr_idx = p_bbs->wr_idx;
- length = BBS_COUNT_CUR(p_bbs, wr_idx);
- /*make sure length of rx buffer data > 0*/
- do {
- if (0 < length) {
- /*check if rx_cb empty or not, if registered ,
- call user's rx callback to handle these data*/
- if (p_btif->rx_cb) {
- if (p_bbs->rd_idx <= wr_idx) {
- p_buf = BBS_PTR(p_bbs, p_bbs->rd_idx);
- /* p_buf = &(p_bbs->buf[p_bbs->rd_idx]); */
- /* length = BBS_COUNT(p_bbs); */
- length = (wr_idx >= (p_bbs)->rd_idx) ?
- (wr_idx - (p_bbs)->rd_idx) :
- BBS_SIZE(p_bbs) -
- ((p_bbs)->rd_idx - wr_idx);
- if (p_btif->rx_cb)
- (*(p_btif->rx_cb)) (p_buf, length);
- else
- BTIF_ERR_FUNC("p_btif->rx_cb is NULL\n");
- /*update rx data read index*/
- p_bbs->rd_idx = wr_idx;
- } else {
- unsigned int len_tail =
- BBS_SIZE(p_bbs) - (p_bbs)->rd_idx;
- /*p_buf = &(p_bbs->buf[p_bbs->->rd_idx]);*/
- p_buf = BBS_PTR(p_bbs, p_bbs->rd_idx);
- if (p_btif->rx_cb)
- (*(p_btif->rx_cb)) (p_buf, len_tail);
- else
- BTIF_ERR_FUNC("p_btif->rx_cb is NULL\n");
- length = BBS_COUNT_CUR(p_bbs, wr_idx);
- length -= len_tail;
- /*p_buf = &(p_bbs->buf[0]);*/
- p_buf = BBS_PTR(p_bbs, 0);
- if (p_btif->rx_cb)
- (*(p_btif->rx_cb)) (p_buf, length);
- else
- BTIF_ERR_FUNC("p_btif->rx_cb is NULL\n");
- /*update rx data read index*/
- p_bbs->rd_idx = wr_idx;
- }
- } else if (NULL != p_btif->rx_notify) {
- (*p_btif->rx_notify) ();
- } else {
- BTIF_WARN_FUNC
- ("p_btif:0x%p, both rx_notify and rx_cb are NULL\n",
- p_btif);
- break;
- }
- } else {
- BTIF_DBG_FUNC("length:%d\n", length);
- break;
- }
- wr_idx = p_bbs->wr_idx;
- length = BBS_COUNT_CUR(p_bbs, wr_idx);
- } while (1);
- return length;
- }
- #if BTIF_RXD_BE_BLOCKED_DETECT
- static int mtk_btif_rxd_be_blocked_by_timer(void)
- {
- int ret = 0;
- int counter = 0;
- unsigned int i;
- struct timeval now;
- int time_gap[MAX_BTIF_RXD_TIME_REC];
- do_gettimeofday(&now);
- for (i = 0; i < MAX_BTIF_RXD_TIME_REC; i++) {
- BTIF_INFO_FUNC("btif_rxd_time_stamp[%d]=%d.%d\n", i,
- btif_rxd_time_stamp[i].tv_sec, btif_rxd_time_stamp[i].tv_usec);
- if (now.tv_sec >= btif_rxd_time_stamp[i].tv_sec) {
- time_gap[i] = now.tv_sec - btif_rxd_time_stamp[i].tv_sec;
- time_gap[i] *= 1000000; /*second*/
- if (now.tv_usec >= btif_rxd_time_stamp[i].tv_usec)
- time_gap[i] += now.tv_usec - btif_rxd_time_stamp[i].tv_usec;
- else
- time_gap[i] += 1000000 - now.tv_usec + btif_rxd_time_stamp[i].tv_usec;
- if (time_gap[i] > 1000000)
- counter++;
- BTIF_INFO_FUNC("time_gap[%d]=%d,counter:%d\n", i, time_gap[i], counter);
- } else {
- time_gap[i] = 0;
- BTIF_ERR_FUNC("abnormal case now:%d < time_stamp[%d]:%d\n", now.tv_sec,
- i, btif_rxd_time_stamp[i].tv_usec);
- }
- }
- if (counter > (MAX_BTIF_RXD_TIME_REC - 2))
- ret = 1;
- return ret;
- }
- static int mtk_btif_rxd_be_blocked_by_data(void)
- {
- unsigned int out_index = 0;
- unsigned int in_index = 0;
- unsigned int dump_size = 0;
- unsigned int len = 0;
- unsigned long flags;
- unsigned int sync_pkt_n = 0;
- P_BTIF_LOG_BUF_T p_log_buf = NULL;
- P_BTIF_LOG_QUEUE_T p_log_que = NULL;
- p_mtk_btif p_btif = &(g_btif[0]);
- p_log_que = &p_btif->rx_log;
- spin_lock_irqsave(&p_log_que->lock, flags);
- in_index = p_log_que->in;
- dump_size = p_log_que->size;
- out_index = p_log_que->size >=
- BTIF_LOG_ENTRY_NUM ? in_index : (BTIF_LOG_ENTRY_NUM -
- p_log_que->size +
- in_index) % BTIF_LOG_ENTRY_NUM;
- if (0 != dump_size) {
- while (dump_size--) {
- p_log_buf = p_log_que->p_queue[0] + out_index;
- len = p_log_buf->len;
- if (len > BTIF_LOG_SZ)
- len = BTIF_LOG_SZ;
- if ((0x7f == *(p_log_buf->buffer)) && (0x7f == *(p_log_buf->buffer + 1))) {
- sync_pkt_n++;
- BTIF_INFO_FUNC("tx pkt_count:%d is sync pkt\n", out_index);
- }
- out_index++;
- out_index %= BTIF_LOG_ENTRY_NUM;
- }
- }
- if (0 == sync_pkt_n)
- BTIF_ERR_FUNC("there is no sync pkt in BTIF buffer\n");
- else
- BTIF_ERR_FUNC("there are %d sync pkt in BTIF buffer\n", sync_pkt_n);
- spin_unlock_irqrestore(&p_log_que->lock, flags);
- return sync_pkt_n;
- }
- int mtk_btif_rxd_be_blocked_flag_get(void)
- {
- int ret = 0;
- int condition1 = 0, condition2 = 0;
- condition1 = mtk_btif_rxd_be_blocked_by_timer();
- condition2 = mtk_btif_rxd_be_blocked_by_data();
- if (condition1 && condition2) {
- BTIF_ERR_FUNC("btif_rxd thread be blocked too long!\n");
- ret = 1;
- }
- return ret;
- }
- #endif
- static int btif_rx_thread(void *p_data)
- {
- #if BTIF_RXD_BE_BLOCKED_DETECT
- unsigned int i = 0;
- #endif
- p_mtk_btif p_btif = (p_mtk_btif)p_data;
- while (1) {
- if (p_btif->enable) {
- /*if BTIF is enabled we will polling if there's any data received at least each 360ms*/
- wait_for_completion_interruptible_timeout(&p_btif->rx_comp, msecs_to_jiffies(360));
- } else {
- /*if BTIF is not enabled, stop polling*/
- wait_for_completion_interruptible(&p_btif->rx_comp);
- }
- if (kthread_should_stop()) {
- BTIF_WARN_FUNC("btif rx thread stoping ...\n");
- break;
- }
- #ifdef BTIF_RXD_BE_BLOCKED_DETECT
- do_gettimeofday(&btif_rxd_time_stamp[i]);
- i++;
- if (i >= MAX_BTIF_RXD_TIME_REC)
- i = 0;
- #endif
- btif_rx_data_consummer(p_btif);
- }
- return 0;
- }
- static void btif_rx_worker(struct work_struct *p_work)
- {
- /*get mtk_btif's pointer*/
- p_mtk_btif p_btif = container_of(p_work, mtk_btif, rx_work);
- BTIF_DBG_FUNC("p_btif:0x%p\n", p_btif);
- /*lock rx_mutex*/
- if (mutex_lock_killable(&(p_btif->rx_mtx))) {
- BTIF_ERR_FUNC("mutex_lock_killable return failed\n");
- return;
- }
- btif_rx_data_consummer(p_btif);
- BTIF_MUTEX_UNLOCK(&(p_btif->rx_mtx));
- }
- static void btif_tx_worker(struct work_struct *p_work)
- {
- int i_ret = 0;
- int leng_sent = 0;
- /*tx fifo out*/
- int how_much_get = 0;
- unsigned char local_buf[384];
- /*get mtk_btif's pointer*/
- p_mtk_btif p_btif = container_of(p_work, mtk_btif, tx_work);
- BTIF_DBG_FUNC("p_btif:0x%p\n", p_btif);
- if (mutex_lock_killable(&(p_btif->tx_mtx))) {
- BTIF_ERR_FUNC("mutex_lock_killable return failed\n");
- return;
- }
- how_much_get =
- kfifo_out(p_btif->p_tx_fifo, local_buf, sizeof(local_buf));
- do {
- while (leng_sent < how_much_get) {
- i_ret = _btif_send_data(p_btif,
- local_buf + leng_sent,
- how_much_get - leng_sent);
- if (0 < i_ret) {
- leng_sent += i_ret;
- } else if (0 == i_ret) {
- BTIF_WARN_FUNC
- ("_btif_send_data return 0, retry\n");
- } else {
- BTIF_WARN_FUNC
- ("btif send data fail,reset tx fifo, i_ret(%d)\n",
- i_ret);
- kfifo_reset(p_btif->p_tx_fifo);
- break;
- }
- }
- how_much_get =
- kfifo_out(p_btif->p_tx_fifo, local_buf, sizeof(local_buf));
- leng_sent = 0;
- } while (0 < how_much_get);
- BTIF_MUTEX_UNLOCK(&(p_btif->tx_mtx));
- }
- static void btif_rx_tasklet(unsigned long func_data)
- {
- unsigned long flags;
- /*get mtk_btif's pointer*/
- p_mtk_btif p_btif = (p_mtk_btif) func_data;
- BTIF_DBG_FUNC("p_btif:0x%p\n", p_btif);
- /*lock rx_spinlock*/
- spin_lock_irqsave(&p_btif->rx_tasklet_spinlock, flags);
- btif_rx_data_consummer(p_btif);
- spin_unlock_irqrestore(&p_btif->rx_tasklet_spinlock, flags);
- }
- static int _btif_tx_ctx_init(p_mtk_btif p_btif)
- {
- int i_ret = -1;
- if (NULL == p_btif) {
- BTIF_ERR_FUNC("p_btif is NULL\n");
- return E_BTIF_INVAL_PARAM;
- }
- if (BTIF_TX_SINGLE_CTX == p_btif->tx_ctx) {
- p_btif->p_tx_wq = create_singlethread_workqueue("btif_txd");
- if (!(p_btif->p_tx_wq)) {
- BTIF_ERR_FUNC
- ("create_singlethread_workqueue for tx thread fail\n");
- i_ret = -ENOMEM;
- goto btm_init_err;
- }
- mutex_init(&(p_btif->tx_mtx));
- /* init btif tx work */
- INIT_WORK(&(p_btif->tx_work), btif_tx_worker);
- BTIF_INFO_FUNC("btif_tx_worker init succeed\n");
- p_btif->p_tx_fifo = kzalloc(sizeof(struct kfifo), GFP_ATOMIC);
- if (NULL == p_btif->p_tx_fifo) {
- i_ret = -ENOMEM;
- BTIF_ERR_FUNC("kzalloc for p_btif->p_tx_fifo failed\n");
- goto btm_init_err;
- }
- i_ret = kfifo_alloc(p_btif->p_tx_fifo,
- BTIF_TX_FIFO_SIZE, GFP_ATOMIC);
- if (0 != i_ret) {
- BTIF_ERR_FUNC("kfifo_alloc failed, errno(%d)\n", i_ret);
- i_ret = -ENOMEM;
- goto btm_init_err;
- }
- } else if (BTIF_TX_USER_CTX == p_btif->tx_ctx) {
- BTIF_INFO_FUNC
- ("nothing is done when btif tx in user's thread\n");
- } else {
- BTIF_ERR_FUNC("unsupported tx context type:%d\n",
- p_btif->tx_ctx);
- goto btm_init_err;
- }
- BTIF_INFO_FUNC("succeed\n");
- i_ret = 0;
- return i_ret;
- btm_init_err:
- if (BTIF_TX_SINGLE_CTX == p_btif->tx_ctx) {
- if (p_btif->p_tx_wq) {
- destroy_workqueue(p_btif->p_tx_wq);
- p_btif->p_tx_wq = NULL;
- BTIF_INFO_FUNC("btif_tx_workqueue destroyed\n");
- }
- kfree(p_btif->p_tx_fifo);
- }
- return i_ret;
- }
- static int _btif_tx_ctx_deinit(p_mtk_btif p_btif)
- {
- int i_ret = 0;
- if (BTIF_TX_SINGLE_CTX == p_btif->tx_ctx) {
- if (p_btif->p_tx_wq) {
- destroy_workqueue(p_btif->p_tx_wq);
- p_btif->p_tx_wq = NULL;
- BTIF_INFO_FUNC("btif_tx_workqueue destroyed\n");
- }
- if (p_btif->p_tx_fifo) {
- kfifo_free(p_btif->p_tx_fifo);
- kfree(p_btif->p_tx_fifo);
- p_btif->p_tx_fifo = NULL;
- }
- }
- return i_ret;
- }
- static int _btif_rx_btm_init(p_mtk_btif p_btif)
- {
- int i_ret = -1;
- if (NULL == p_btif) {
- BTIF_ERR_FUNC("p_btif is NULL\n");
- return E_BTIF_INVAL_PARAM;
- }
- if (BTIF_THREAD_CTX == p_btif->btm_type) {
- init_completion(&p_btif->rx_comp);
- /*create kernel thread for later rx data handle*/
- p_btif->p_task = kthread_create(btif_rx_thread, p_btif, "btif_rxd");
- if (NULL == p_btif->p_task) {
- BTIF_ERR_FUNC("kthread_create fail\n");
- i_ret = -ENOMEM;
- goto btm_init_err;
- }
- #if ENABLE_BTIF_RX_THREAD_RT_SCHED
- {
- int i_ret = -1;
- int policy = SCHED_FIFO;
- struct sched_param param;
- param.sched_priority = MAX_RT_PRIO - 20;
- i_ret = sched_setscheduler(p_btif->p_task, policy, ¶m);
- if (0 != i_ret)
- BTIF_WARN_FUNC("set RT to btif_rxd workqueue failed\n");
- else
- BTIF_INFO_FUNC("set RT to btif_rxd workqueue succeed\n");
- }
- #endif
- wake_up_process(p_btif->p_task);
- BTIF_INFO_FUNC("btif_rxd start to work!\n");
- } else if (BTIF_WQ_CTX == p_btif->btm_type) {
- p_btif->p_rx_wq = create_singlethread_workqueue("btif_rxwq");
- if (!(p_btif->p_rx_wq)) {
- BTIF_ERR_FUNC("create_singlethread_workqueue fail\n");
- i_ret = -ENOMEM;
- goto btm_init_err;
- }
- mutex_init(&(p_btif->rx_mtx));
- /* init btif rx work */
- INIT_WORK(&(p_btif->rx_work), btif_rx_worker);
- BTIF_INFO_FUNC("btif_rx_worker init succeed\n");
- } else if (BTIF_TASKLET_CTX == p_btif->btm_type) {
- /*init rx tasklet*/
- tasklet_init(&(p_btif->rx_tasklet), btif_rx_tasklet,
- (unsigned long)p_btif);
- spin_lock_init(&(p_btif->rx_tasklet_spinlock));
- BTIF_INFO_FUNC("btif_rx_tasklet init succeed\n");
- } else {
- BTIF_ERR_FUNC("unsupported rx context type:%d\n",
- p_btif->btm_type);
- }
- /*spinlock init*/
- spin_lock_init(&(p_btif->rx_irq_spinlock));
- BTIF_INFO_FUNC("rx_spin_lock init succeed\n");
- i_ret = 0;
- return i_ret;
- btm_init_err:
- if (BTIF_THREAD_CTX == p_btif->btm_type) {
- /*do nothing*/
- BTIF_INFO_FUNC("failed\n");
- } else if (BTIF_WQ_CTX == p_btif->btm_type) {
- if (p_btif->p_rx_wq) {
- destroy_workqueue(p_btif->p_rx_wq);
- p_btif->p_rx_wq = NULL;
- BTIF_INFO_FUNC("btif_rx_workqueue destroyed\n");
- }
- }
- return i_ret;
- }
- static int _btif_rx_btm_sched(p_mtk_btif p_btif)
- {
- if (NULL == p_btif) {
- BTIF_ERR_FUNC("p_btif is NULL\n");
- return E_BTIF_INVAL_PARAM;
- }
- if (BTIF_THREAD_CTX == p_btif->btm_type) {
- complete(&p_btif->rx_comp);
- BTIF_DBG_FUNC("schedule btif_rx_thread\n");
- } else if (BTIF_WQ_CTX == p_btif->btm_type) {
- queue_work(p_btif->p_rx_wq, &(p_btif->rx_work));
- BTIF_DBG_FUNC("schedule btif_rx_worker\n");
- } else if (BTIF_TASKLET_CTX == p_btif->btm_type) {
- /*schedule it!*/
- tasklet_schedule(&(p_btif->rx_tasklet));
- BTIF_DBG_FUNC("schedule btif_rx_tasklet\n");
- } else {
- BTIF_ERR_FUNC("unsupported rx context type:%d\n",
- p_btif->btm_type);
- }
- return 0;
- }
- static int _btif_rx_btm_deinit(p_mtk_btif p_btif)
- {
- if (NULL == p_btif) {
- BTIF_ERR_FUNC("p_btif is NULL\n");
- return E_BTIF_INVAL_PARAM;
- }
- if (BTIF_THREAD_CTX == p_btif->btm_type) {
- if (NULL != p_btif->p_task) {
- BTIF_INFO_FUNC("signaling btif rx thread to stop ...\n");
- kthread_stop(p_btif->p_task);
- }
- } else if (BTIF_WQ_CTX == p_btif->btm_type) {
- if (p_btif->p_rx_wq) {
- cancel_work_sync(&(p_btif->rx_work));
- BTIF_INFO_FUNC("btif_rx_worker cancelled\n");
- destroy_workqueue(p_btif->p_rx_wq);
- p_btif->p_rx_wq = NULL;
- BTIF_INFO_FUNC("btif_rx_workqueue destroyed\n");
- }
- mutex_destroy(&(p_btif->rx_mtx));
- } else if (BTIF_TASKLET_CTX == p_btif->btm_type) {
- tasklet_kill(&(p_btif->rx_tasklet));
- BTIF_INFO_FUNC("rx_tasklet killed\n");
- } else {
- BTIF_ERR_FUNC("unsupported rx context type:%d\n",
- p_btif->btm_type);
- }
- spin_lock_init(&(p_btif->rx_irq_spinlock));
- return 0;
- }
- void btif_dump_bbs_str(unsigned char *p_str, p_btif_buf_str p_bbs)
- {
- BTIF_INFO_FUNC
- ("%s UBS:0x%p\n Size:0x%p\n read:0x%08x\n write:0x%08x\n",
- p_str, p_bbs, p_bbs->size, p_bbs->rd_idx, p_bbs->wr_idx);
- }
- unsigned int btif_bbs_write(p_btif_buf_str p_bbs,
- unsigned char *p_buf, unsigned int buf_len)
- {
- /*in IRQ context, so read operation won't interrupt this operation*/
- unsigned int wr_len = 0;
- unsigned int emp_len = BBS_LEFT(p_bbs);
- unsigned int ava_len = emp_len - 1;
- p_mtk_btif p_btif = container_of(p_bbs, mtk_btif, btif_buf);
- if (0 >= ava_len) {
- BTIF_ERR_FUNC
- ("no empty space left for write, (%d)ava_len, (%d)to write\n",
- ava_len, buf_len);
- hal_btif_dump_reg(p_btif->p_btif_info, REG_BTIF_ALL);
- hal_dma_dump_reg(p_btif->p_rx_dma->p_dma_info, REG_RX_DMA_ALL);
- return 0;
- }
- if (ava_len < buf_len) {
- BTIF_ERR_FUNC("BTIF overrun, (%d)empty, (%d)needed\n",
- emp_len, buf_len);
- hal_btif_dump_reg(p_btif->p_btif_info, REG_BTIF_ALL);
- hal_dma_dump_reg(p_btif->p_rx_dma->p_dma_info, REG_RX_DMA_ALL);
- _btif_dump_memory("<DMA Rx vFIFO>", p_buf, buf_len);
- }
- if (buf_len >= g_max_pkg_len) {
- BTIF_WARN_FUNC("buf_len too long, (%d)ava_len, (%d)to write\n",
- ava_len, buf_len);
- hal_btif_dump_reg(p_btif->p_btif_info, REG_BTIF_ALL);
- hal_dma_dump_reg(p_btif->p_rx_dma->p_dma_info, REG_RX_DMA_ALL);
- _btif_dump_memory("<DMA Rx vFIFO>", p_buf, buf_len);
- }
- wr_len = min(buf_len, ava_len);
- btif_bbs_wr_direct(p_bbs, p_buf, wr_len);
- if (BBS_COUNT(p_bbs) >= g_max_pding_data_size) {
- BTIF_WARN_FUNC("Rx buf_len too long, size(%d)\n",
- BBS_COUNT(p_bbs));
- btif_dump_bbs_str("Rx buffer tooo long", p_bbs);
- hal_btif_dump_reg(p_btif->p_btif_info, REG_BTIF_ALL);
- hal_dma_dump_reg(p_btif->p_rx_dma->p_dma_info, REG_RX_DMA_ALL);
- _btif_dump_memory("<DMA Rx vFIFO>", p_buf, buf_len);
- BBS_INIT(p_bbs);
- }
- return wr_len;
- }
- unsigned int btif_bbs_read(p_btif_buf_str p_bbs,
- unsigned char *p_buf, unsigned int buf_len)
- {
- unsigned int rd_len = 0;
- unsigned int ava_len = 0;
- unsigned int wr_idx = p_bbs->wr_idx;
- ava_len = BBS_COUNT_CUR(p_bbs, wr_idx);
- if (ava_len >= 4096) {
- BTIF_WARN_FUNC("ava_len too long, size(%d)\n", ava_len);
- btif_dump_bbs_str("Rx buffer tooo long", p_bbs);
- }
- if (0 != ava_len) {
- if (buf_len >= ava_len) {
- rd_len = ava_len;
- if (wr_idx >= (p_bbs)->rd_idx) {
- memcpy(p_buf, BBS_PTR(p_bbs,
- p_bbs->rd_idx),
- ava_len);
- (p_bbs)->rd_idx = wr_idx;
- } else {
- unsigned int tail_len = BBS_SIZE(p_bbs) -
- (p_bbs)->rd_idx;
- memcpy(p_buf, BBS_PTR(p_bbs,
- p_bbs->rd_idx),
- tail_len);
- memcpy(p_buf + tail_len, BBS_PTR(p_bbs,
- 0), ava_len - tail_len);
- (p_bbs)->rd_idx = wr_idx;
- }
- } else {
- rd_len = buf_len;
- if (wr_idx >= (p_bbs)->rd_idx) {
- memcpy(p_buf, BBS_PTR(p_bbs,
- p_bbs->rd_idx),
- rd_len);
- (p_bbs)->rd_idx = (p_bbs)->rd_idx + rd_len;
- } else {
- unsigned int tail_len = BBS_SIZE(p_bbs) -
- (p_bbs)->rd_idx;
- if (tail_len >= rd_len) {
- memcpy(p_buf, BBS_PTR(p_bbs, p_bbs->rd_idx),
- rd_len);
- (p_bbs)->rd_idx =
- ((p_bbs)->rd_idx + rd_len) & (BBS_MASK(p_bbs));
- } else {
- memcpy(p_buf, BBS_PTR(p_bbs, p_bbs->rd_idx), tail_len);
- memcpy(p_buf + tail_len,
- (p_bbs)->p_buf, rd_len - tail_len);
- (p_bbs)->rd_idx = rd_len - tail_len;
- }
- }
- }
- }
- mb();
- return rd_len;
- }
- unsigned int btif_bbs_wr_direct(p_btif_buf_str p_bbs,
- unsigned char *p_buf, unsigned int buf_len)
- {
- unsigned int tail_len = 0;
- unsigned int l = 0;
- unsigned int tmp_wr_idx = p_bbs->wr_idx;
- tail_len = BBS_SIZE(p_bbs) - (tmp_wr_idx & BBS_MASK(p_bbs));
- l = min(tail_len, buf_len);
- memcpy((p_bbs->p_buf) + (tmp_wr_idx & BBS_MASK(p_bbs)), p_buf, l);
- memcpy(p_bbs->p_buf, p_buf + l, buf_len - l);
- mb();
- tmp_wr_idx += buf_len;
- tmp_wr_idx &= BBS_MASK(p_bbs);
- p_bbs->wr_idx = tmp_wr_idx;
- mb();
- return buf_len;
- }
- int _btif_dma_write(p_mtk_btif p_btif,
- const unsigned char *p_buf, unsigned int buf_len)
- {
- unsigned int i_ret = 0;
- unsigned int retry = 0;
- unsigned int max_tx_retry = 10;
- P_MTK_DMA_INFO_STR p_dma_info = p_btif->p_tx_dma->p_dma_info;
- _btif_irq_ctrl_sync(p_dma_info->p_irq, false);
- do {
- /*wait until tx is allowed*/
- while (!hal_dma_is_tx_allow(p_dma_info) &&
- (retry < max_tx_retry)) {
- retry++;
- if (retry >= max_tx_retry) {
- BTIF_ERR_FUNC("wait for tx allowed timeout\n");
- break;
- }
- }
- if (retry >= max_tx_retry)
- break;
- if (buf_len <= hal_dma_get_ava_room(p_dma_info))
- i_ret = hal_dma_send_data(p_dma_info, p_buf, buf_len);
- else
- i_ret = 0;
- } while (0);
- _btif_irq_ctrl_sync(p_dma_info->p_irq, true);
- return i_ret;
- }
- int _btif_pio_write(p_mtk_btif p_btif,
- const unsigned char *p_buf, unsigned int buf_len)
- {
- unsigned int i_ret = 0;
- unsigned int sent_len = 0;
- unsigned int retry = 0;
- unsigned int max_tx_retry = 10;
- P_MTK_BTIF_INFO_STR p_btif_info = p_btif->p_btif_info;
- while ((sent_len < buf_len)) {
- if (hal_btif_is_tx_allow(p_btif_info)) {
- i_ret = hal_btif_send_data(p_btif_info,
- p_buf + sent_len,
- buf_len - sent_len);
- if (0 < i_ret) {
- sent_len += i_ret;
- BTIF_DBG_FUNC("lent sent:%d, total sent:%d\n",
- i_ret, sent_len);
- retry = 0;
- }
- }
- if ((++retry > max_tx_retry) || (0 > i_ret)) {
- BTIF_INFO_FUNC("exceed retry times limit :%d\n", retry);
- break;
- }
- }
- i_ret = sent_len;
- return i_ret;
- }
- int _btif_dump_memory(char *str, unsigned char *p_buf, unsigned int buf_len)
- {
- unsigned int idx = 0;
- pr_debug("%s:, length:%d\n", str, buf_len);
- for (idx = 0; idx < buf_len;) {
- pr_debug("%02x ", p_buf[idx]);
- idx++;
- if (0 == idx % 8)
- pr_debug("\n");
- }
- return 0;
- }
- int btif_send_data(p_mtk_btif p_btif,
- const unsigned char *p_buf, unsigned int buf_len)
- {
- int i_ret = 0;
- if (BTIF_TX_USER_CTX == p_btif->tx_ctx) {
- i_ret = _btif_send_data(p_btif, p_buf, buf_len);
- } else if (BTIF_TX_SINGLE_CTX == p_btif->tx_ctx) {
- int length = 0;
- /*tx fifo in*/
- length = kfifo_in(p_btif->p_tx_fifo,
- (unsigned char *)p_buf, buf_len);
- if (length == buf_len) {
- queue_work(p_btif->p_tx_wq, &(p_btif->tx_work));
- BTIF_DBG_FUNC("schedule btif_tx_worker\n");
- i_ret = length;
- } else {
- i_ret = 0;
- BTIF_ERR_FUNC("fifo in failed, target len(%d),in len(%d),",
- "don't schedule btif_tx_worker\n", buf_len, length);
- }
- } else {
- BTIF_ERR_FUNC("invalid btif tx context:%d\n", p_btif->tx_ctx);
- i_ret = 0;
- }
- return i_ret;
- }
- int _btif_send_data(p_mtk_btif p_btif,
- const unsigned char *p_buf, unsigned int buf_len)
- {
- int i_ret = 0;
- unsigned int state = 0;
- /*make sure BTIF in ON state before doing tx operation*/
- if (_btif_state_hold(p_btif))
- return E_BTIF_INTR;
- state = _btif_state_get(p_btif);
- if (B_S_ON != state)
- i_ret = _btif_exit_dpidle(p_btif);
- if (0 != i_ret) {
- i_ret = E_BTIF_INVAL_STATE;
- } else if (BTIF_MODE_DMA == p_btif->tx_mode) {
- /*_btif_dump_memory("tx data:", p_buf, buf_len);*/
- i_ret = _btif_dma_write(p_btif, p_buf, buf_len);
- } else if (BTIF_MODE_PIO == p_btif->tx_mode) {
- /*_btif_dump_memory("tx data:", p_buf, buf_len);*/
- i_ret = _btif_pio_write(p_btif, p_buf, buf_len);
- } else {
- BTIF_ERR_FUNC("invalid tx mode:%d\n", p_btif->tx_mode);
- i_ret = 0;
- }
- /*save Tx packet here*/
- if (0 < i_ret)
- btif_log_buf_dmp_in(&p_btif->tx_log, p_buf, i_ret);
- BTIF_STATE_RELEASE(p_btif);
- return i_ret;
- }
- int btif_dump_reg(p_mtk_btif p_btif)
- {
- int i_ret = 0;
- unsigned int ori_state = 0;
- /*make sure BTIF in ON state before doing tx operation*/
- if (_btif_state_hold(p_btif))
- return E_BTIF_INTR;
- ori_state = _btif_state_get(p_btif);
- if (B_S_OFF == ori_state) {
- i_ret = E_BTIF_INVAL_STATE;
- BTIF_ERR_FUNC
- ("BTIF in OFF state, ",
- "should no need to dump register, ",
- "please check wmt's operation is okay or not.\n");
- goto dmp_reg_err;
- }
- if ((B_S_ON != ori_state) && (B_S_MAX > ori_state)) {
- BTIF_ERR_FUNC("BTIF's original state is %s, not B_S_ON\n", g_state[ori_state]);
- BTIF_ERR_FUNC("!!!-<-<-<This should never happen in normal mode>->->-!!!");
- i_ret = _btif_exit_dpidle(p_btif);
- }
- if (0 != i_ret) {
- i_ret = E_BTIF_INVAL_STATE;
- BTIF_ERR_FUNC("switch to B_S_ON failed\n");
- goto dmp_reg_err;
- }
- /*dump BTIF register*/
- hal_btif_dump_reg(p_btif->p_btif_info, REG_BTIF_ALL);
- /*dump BTIF Tx DMA channel register if in DMA mode*/
- if (BTIF_MODE_DMA == p_btif->tx_mode)
- hal_dma_dump_reg(p_btif->p_tx_dma->p_dma_info, REG_TX_DMA_ALL);
- else
- BTIF_INFO_FUNC("BTIF Tx in PIO mode,no need to dump Tx DMA's register\n");
- /*dump BTIF Rx DMA channel register if in DMA mode*/
- if (BTIF_MODE_DMA == p_btif->rx_mode)
- hal_dma_dump_reg(p_btif->p_rx_dma->p_dma_info, REG_RX_DMA_ALL);
- else
- BTIF_INFO_FUNC("BTIF Rx in PIO mode,no need to dump Rx DMA's register\n");
- switch (ori_state) {
- case B_S_SUSPEND:
- /*return to dpidle state*/
- /* break; */
- case B_S_DPIDLE:
- /*return to dpidle state*/
- _btif_enter_dpidle(p_btif);
- break;
- case B_S_ON:
- /*nothing needs to be done*/
- break;
- default:
- break;
- }
- dmp_reg_err:
- BTIF_STATE_RELEASE(p_btif);
- return i_ret;
- }
- int btif_rx_notify_reg(p_mtk_btif p_btif, MTK_BTIF_RX_NOTIFY rx_notify)
- {
- if (p_btif->rx_notify) {
- BTIF_WARN_FUNC
- ("rx cb already exist, rewrite from (0x%p) to (0x%p)\n",
- p_btif->rx_notify, rx_notify);
- }
- p_btif->rx_notify = rx_notify;
- return 0;
- }
- int btif_dump_data(char *p_buf, int len)
- {
- unsigned int idx = 0;
- for (idx = 0; idx < len; idx++, p_buf++) {
- pr_debug("%02x ", *p_buf);
- if (7 == (idx % 8))
- pr_debug("\n");
- }
- pr_debug("\n");
- return 0;
- }
- int btif_log_buf_dmp_in(P_BTIF_LOG_QUEUE_T p_log_que, const char *p_buf,
- int len)
- {
- P_BTIF_LOG_BUF_T p_log_buf = NULL;
- char *dir = NULL;
- struct timeval *p_timer = NULL;
- unsigned long flags;
- bool output_flag = false;
- BTIF_DBG_FUNC("++\n");
- if ((NULL == p_log_que) || (NULL == p_buf) || (0 == len)) {
- BTIF_ERR_FUNC("invalid parameter, p_log_que(0x%x), buf(0x%x), ",
- "len(%d)\n", p_log_que, p_buf, len);
- return 0;
- }
- if (!(p_log_que->enable))
- return 0;
- dir = p_log_que->dir == BTIF_TX ? "Tx" : "Rx";
- output_flag = p_log_que->output_flag;
- spin_lock_irqsave(&(p_log_que->lock), flags);
- /*get next log buffer for record usage*/
- p_log_buf = p_log_que->p_queue[0] + p_log_que->in;
- p_timer = &p_log_buf->timer;
- /*log time stamp*/
- do_gettimeofday(p_timer);
- /*record data information including length and content*/
- p_log_buf->len = len;
- memcpy(p_log_buf->buffer, p_buf, len > BTIF_LOG_SZ ? BTIF_LOG_SZ : len);
- /*update log queue size information*/
- p_log_que->size++;
- p_log_que->size = p_log_que->size >
- BTIF_LOG_ENTRY_NUM ? BTIF_LOG_ENTRY_NUM : p_log_que->size;
- /*update log queue index information*/
- p_log_que->in++;
- p_log_que->in %= BTIF_LOG_ENTRY_NUM;
- spin_unlock_irqrestore(&p_log_que->lock, flags);
- /*check if log dynamic output function is enabled or not*/
- if (output_flag) {
- pr_debug("BTIF-DBG, dir:%s, %d.%ds len:%d\n",
- dir, (int)p_timer->tv_sec, (int)p_timer->tv_usec, len);
- /*output buffer content*/
- btif_dump_data((char *)p_buf, len);
- }
- BTIF_DBG_FUNC("--\n");
- return 0;
- }
- int btif_log_buf_dmp_out(P_BTIF_LOG_QUEUE_T p_log_que)
- {
- P_BTIF_LOG_BUF_T p_log_buf = NULL;
- unsigned int out_index = 0;
- unsigned int in_index = 0;
- unsigned int dump_size = 0;
- unsigned char *p_buf = NULL;
- unsigned int len = 0;
- unsigned int pkt_count = 0;
- unsigned char *p_dir = NULL;
- struct timeval *p_timer = NULL;
- unsigned long flags;
- #if 0 /* no matter enable or not, we allowed output */
- if (!(p_log_que->enable))
- return;
- #endif
- BTIF_DBG_FUNC("++\n");
- spin_lock_irqsave(&p_log_que->lock, flags);
- in_index = p_log_que->in;
- dump_size = p_log_que->size;
- out_index = p_log_que->size >=
- BTIF_LOG_ENTRY_NUM ? in_index : (BTIF_LOG_ENTRY_NUM -
- p_log_que->size +
- in_index) % BTIF_LOG_ENTRY_NUM;
- p_dir = BTIF_TX == p_log_que->dir ? "Tx" : "Rx";
- BTIF_INFO_FUNC("btif %s log buffer size:%d\n", p_dir, dump_size);
- if (0 != dump_size) {
- while (dump_size--) {
- p_log_buf = p_log_que->p_queue[0] + out_index;
- len = p_log_buf->len;
- p_buf = p_log_buf->buffer;
- p_timer = &p_log_buf->timer;
- len = len > BTIF_LOG_SZ ? BTIF_LOG_SZ : len;
- BTIF_INFO_FUNC("dir:%s, pkt_count:%d, %d.%ds len:%d\n",
- p_dir,
- pkt_count++,
- (int)p_timer->tv_sec,
- (int)p_timer->tv_usec, len);
- /*output buffer content*/
- btif_dump_data(p_log_buf->buffer, len);
- out_index++;
- out_index %= BTIF_LOG_ENTRY_NUM;
- }
- }
- spin_unlock_irqrestore(&p_log_que->lock, flags);
- BTIF_DBG_FUNC("--\n");
- return 0;
- }
- int btif_log_buf_enable(P_BTIF_LOG_QUEUE_T p_log_que)
- {
- unsigned long flags;
- spin_lock_irqsave(&p_log_que->lock, flags);
- p_log_que->enable = true;
- spin_unlock_irqrestore(&p_log_que->lock, flags);
- BTIF_INFO_FUNC("enable %s log function\n",
- p_log_que->dir == BTIF_TX ? "Tx" : "Rx");
- return 0;
- }
- int btif_log_buf_disable(P_BTIF_LOG_QUEUE_T p_log_que)
- {
- unsigned long flags;
- spin_lock_irqsave(&p_log_que->lock, flags);
- p_log_que->enable = false;
- spin_unlock_irqrestore(&p_log_que->lock, flags);
- BTIF_INFO_FUNC("disable %s log function\n",
- p_log_que->dir == BTIF_TX ? "Tx" : "Rx");
- return 0;
- }
- int btif_log_output_enable(P_BTIF_LOG_QUEUE_T p_log_que)
- {
- unsigned long flags;
- spin_lock_irqsave(&p_log_que->lock, flags);
- p_log_que->output_flag = true;
- spin_unlock_irqrestore(&p_log_que->lock, flags);
- BTIF_INFO_FUNC("%s log rt output enabled\n",
- p_log_que->dir == BTIF_TX ? "Tx" : "Rx");
- return 0;
- }
- int btif_log_output_disable(P_BTIF_LOG_QUEUE_T p_log_que)
- {
- unsigned long flags;
- spin_lock_irqsave(&p_log_que->lock, flags);
- p_log_que->output_flag = false;
- spin_unlock_irqrestore(&p_log_que->lock, flags);
- BTIF_INFO_FUNC("%s log rt output disabled\n",
- p_log_que->dir == BTIF_TX ? "Tx" : "Rx");
- return 0;
- }
- int btif_log_buf_reset(P_BTIF_LOG_QUEUE_T p_log_que)
- {
- unsigned long flags;
- spin_lock_irqsave(&p_log_que->lock, flags);
- /*tx log buffer init*/
- p_log_que->in = 0;
- p_log_que->out = 0;
- p_log_que->size = 0;
- p_log_que->enable = true;
- memset((p_log_que->p_queue[0]), 0, sizeof(BTIF_LOG_BUF_T));
- spin_unlock_irqrestore(&p_log_que->lock, flags);
- BTIF_DBG_FUNC("reset %s log buffer\n",
- p_log_que->dir == BTIF_TX ? "Tx" : "Rx");
- return 0;
- }
- int btif_log_buf_init(p_mtk_btif p_btif)
- {
- /*tx log buffer init*/
- p_btif->tx_log.dir = BTIF_TX;
- p_btif->tx_log.in = 0;
- p_btif->tx_log.out = 0;
- p_btif->tx_log.size = 0;
- p_btif->tx_log.output_flag = false;
- p_btif->tx_log.enable = true;
- spin_lock_init(&(p_btif->tx_log.lock));
- BTIF_DBG_FUNC("tx_log.p_queue:0x%p\n", p_btif->tx_log.p_queue[0]);
- memset((p_btif->tx_log.p_queue[0]), 0, sizeof(BTIF_LOG_BUF_T));
- /*rx log buffer init*/
- p_btif->rx_log.dir = BTIF_RX;
- p_btif->rx_log.in = 0;
- p_btif->rx_log.out = 0;
- p_btif->rx_log.size = 0;
- p_btif->rx_log.output_flag = false;
- p_btif->rx_log.enable = true;
- spin_lock_init(&(p_btif->rx_log.lock));
- BTIF_DBG_FUNC("rx_log.p_queue:0x%p\n", p_btif->rx_log.p_queue[0]);
- memset((p_btif->rx_log.p_queue[0]), 0, sizeof(BTIF_LOG_BUF_T));
- return 0;
- }
- int btif_tx_dma_mode_set(int en)
- {
- int index = 0;
- ENUM_BTIF_MODE mode = (1 == en) ? BTIF_MODE_DMA : BTIF_MODE_PIO;
- for (index = 0; index < BTIF_PORT_NR; index++)
- g_btif[index].tx_mode = mode;
- return 0;
- }
- int btif_rx_dma_mode_set(int en)
- {
- int index = 0;
- ENUM_BTIF_MODE mode = (1 == en) ? BTIF_MODE_DMA : BTIF_MODE_PIO;
- for (index = 0; index < BTIF_PORT_NR; index++)
- g_btif[index].rx_mode = mode;
- return 0;
- }
- static int BTIF_init(void)
- {
- int i_ret = -1;
- int index = 0;
- p_mtk_btif_dma p_tx_dma = NULL;
- p_mtk_btif_dma p_rx_dma = NULL;
- unsigned char *p_btif_buffer = NULL;
- unsigned char *p_tx_queue = NULL;
- unsigned char *p_rx_queue = NULL;
- BTIF_DBG_FUNC("++\n");
- /*Platform Driver initialization*/
- i_ret = platform_driver_register(&mtk_btif_dev_drv);
- if (i_ret) {
- BTIF_ERR_FUNC("BTIF platform driver registered failed, ret(%d)\n", i_ret);
- goto err_exit1;
- }
- i_ret = driver_create_file(&mtk_btif_dev_drv.driver, &driver_attr_flag);
- if (i_ret)
- BTIF_ERR_FUNC("BTIF pdriver_create_file failed, ret(%d)\n", i_ret);
- /*SW init*/
- for (index = 0; index < BTIF_PORT_NR; index++) {
- p_btif_buffer = kmalloc(BTIF_RX_BUFFER_SIZE, GFP_ATOMIC);
- if (!p_btif_buffer) {
- BTIF_ERR_FUNC("p_btif_buffer kmalloc memory fail\n");
- return -1;
- }
- BTIF_INFO_FUNC("p_btif_buffer get memory 0x%p\n", p_btif_buffer);
- p_tx_queue = kmalloc_array(BTIF_LOG_ENTRY_NUM, sizeof(BTIF_LOG_BUF_T), GFP_ATOMIC);
- if (!p_tx_queue) {
- BTIF_ERR_FUNC("p_tx_queue kmalloc memory fail\n");
- kfree(p_btif_buffer);
- return -1;
- }
- BTIF_INFO_FUNC("p_tx_queue get memory 0x%p\n", p_tx_queue);
- p_rx_queue = kmalloc_array(BTIF_LOG_ENTRY_NUM, sizeof(BTIF_LOG_BUF_T), GFP_ATOMIC);
- if (!p_rx_queue) {
- BTIF_ERR_FUNC("p_rx_queue kmalloc memory fail\n");
- kfree(p_btif_buffer);
- kfree(p_tx_queue);
- return -1;
- }
- BTIF_INFO_FUNC("p_rx_queue get memory 0x%p\n", p_rx_queue);
- INIT_LIST_HEAD(&(g_btif[index].user_list));
- BBS_INIT(&(g_btif[index].btif_buf));
- g_btif[index].enable = false;
- g_btif[index].open_counter = 0;
- g_btif[index].setting = &g_btif_setting[index];
- g_btif[index].p_btif_info = hal_btif_info_get();
- g_btif[index].tx_mode = g_btif_setting[index].tx_mode;
- g_btif[index].rx_mode = g_btif_setting[index].rx_mode;
- g_btif[index].btm_type = g_btif_setting[index].rx_type;
- g_btif[index].tx_ctx = g_btif_setting[index].tx_type;
- g_btif[index].lpbk_flag = false;
- g_btif[index].rx_cb = NULL;
- g_btif[index].rx_notify = NULL;
- g_btif[index].btif_buf.p_buf = p_btif_buffer;
- g_btif[index].tx_log.p_queue[0] = (P_BTIF_LOG_BUF_T) p_tx_queue;
- g_btif[index].rx_log.p_queue[0] = (P_BTIF_LOG_BUF_T) p_rx_queue;
- btif_log_buf_init(&g_btif[index]);
- #if !(MTK_BTIF_ENABLE_CLK_REF_COUNTER)
- /*enable BTIF clock gating by default*/
- i_ret = hal_btif_clk_ctrl(g_btif[index].p_btif_info,
- CLK_OUT_DISABLE);
- if (0 != i_ret) {
- BTIF_ERR_FUNC("BTIF controller CG failed\n");
- goto err_exit2;
- }
- #endif
- /*viftual FIFO memory must be physical continious, \
- because DMA will access it directly without MMU*/
- #if ENABLE_BTIF_TX_DMA
- p_tx_dma = &g_dma[index][BTIF_TX];
- g_btif[index].p_tx_dma = p_tx_dma;
- p_tx_dma->dir = BTIF_TX;
- p_tx_dma->p_btif = &(g_btif[index]);
- /*DMA Tx vFIFO initialization*/
- p_tx_dma->p_dma_info = hal_btif_dma_info_get(DMA_DIR_TX);
- /*spinlock init*/
- spin_lock_init(&(p_tx_dma->iolock));
- /*entry setup*/
- atomic_set(&(p_tx_dma->entry), 0);
- /*vFIFO initialization*/
- i_ret = _btif_vfifo_init(p_tx_dma);
- if (0 != i_ret) {
- BTIF_ERR_FUNC("BTIF Tx vFIFO allocation failed\n");
- goto err_exit2;
- }
- #if !(MTK_BTIF_ENABLE_CLK_REF_COUNTER)
- /*enable BTIF Tx DMA channel's clock gating by default*/
- i_ret = hal_btif_dma_clk_ctrl(p_tx_dma->p_dma_info,
- CLK_OUT_DISABLE);
- if (0 != i_ret) {
- BTIF_ERR_FUNC("BTIF Tx DMA's CG failed\n");
- goto err_exit2;
- }
- #endif
- #else
- g_btif[index].p_tx_dma = NULL;
- /*force tx mode to DMA no matter what it is in default setting*/
- g_btif[index].tx_mode = BTIF_MODE_PIO;
- #endif
- #if ENABLE_BTIF_RX_DMA
- p_rx_dma = &g_dma[index][BTIF_RX];
- g_btif[index].p_rx_dma = p_rx_dma;
- p_rx_dma->p_btif = &(g_btif[index]);
- p_rx_dma->dir = BTIF_RX;
- /*DMA Tx vFIFO initialization*/
- p_rx_dma->p_dma_info = hal_btif_dma_info_get(DMA_DIR_RX);
- /*spinlock init*/
- spin_lock_init(&(p_rx_dma->iolock));
- /*entry setup*/
- atomic_set(&(p_rx_dma->entry), 0);
- /*vFIFO initialization*/
- i_ret = _btif_vfifo_init(p_rx_dma);
- if (0 != i_ret) {
- BTIF_ERR_FUNC("BTIF Rx vFIFO allocation failed\n");
- goto err_exit2;
- }
- #if !(MTK_BTIF_ENABLE_CLK_REF_COUNTER)
- /*enable BTIF Tx DMA channel's clock gating by default*/
- i_ret = hal_btif_dma_clk_ctrl(p_rx_dma->p_dma_info,
- CLK_OUT_DISABLE);
- if (0 != i_ret) {
- BTIF_ERR_FUNC("BTIF Rx DMA's CG failed\n");
- goto err_exit2;
- }
- #endif
- #else
- g_btif[index].p_rx_dma = NULL;
- /*force rx mode to DMA no matter what it is in default setting*/
- g_btif[index].rx_mode = BTIF_MODE_PIO;
- #endif
- /*PM state mechine initialization*/
- i_ret = _btif_state_init(&(g_btif[index]));
- if (0 != i_ret) {
- BTIF_ERR_FUNC("BTIF state mechanism init failed\n");
- goto err_exit2;
- }
- /*Rx bottom half initialization*/
- i_ret = _btif_rx_btm_init(&(g_btif[index]));
- if (0 != i_ret) {
- BTIF_ERR_FUNC("BTIF Rx btm init failed\n");
- goto err_exit3;
- }
- i_ret = _btif_tx_ctx_init(&(g_btif[index]));
- if (0 != i_ret) {
- BTIF_ERR_FUNC("BTIF Tx context init failed\n");
- goto err_exit4;
- }
- /*Character Device initialization*/
- /*Chaozhong: ToDo: to be initialized*/
- mutex_init(&g_btif[index].ops_mtx);
- }
- /*Debug purpose initialization*/
- #if BTIF_CDEV_SUPPORT
- btif_chrdev_init();
- #endif
- return 0;
- err_exit4:
- for (index = 0; index < BTIF_PORT_NR; index++)
- _btif_tx_ctx_deinit(&(g_btif[index]));
- err_exit3:
- for (index = 0; index < BTIF_PORT_NR; index++) {
- _btif_rx_btm_deinit(&(g_btif[index]));
- _btif_state_deinit(&(g_btif[index]));
- }
- err_exit2:
- for (index = 0; index < BTIF_PORT_NR; index++) {
- p_tx_dma = &g_dma[index][BTIF_TX];
- p_rx_dma = &g_dma[index][BTIF_RX];
- #if ENABLE_BTIF_TX_DMA
- _btif_vfifo_deinit(p_tx_dma);
- #endif
- #if ENABLE_BTIF_RX_DMA
- _btif_vfifo_deinit(p_rx_dma);
- #endif
- g_btif[index].open_counter = 0;
- g_btif[index].enable = false;
- }
- driver_remove_file(&mtk_btif_dev_drv.driver, &driver_attr_flag);
- platform_driver_unregister(&mtk_btif_dev_drv);
- err_exit1:
- i_ret = -1;
- BTIF_DBG_FUNC("--\n");
- return i_ret;
- }
- static void BTIF_exit(void)
- {
- unsigned int index = 0;
- p_mtk_btif_dma p_tx_dma = NULL;
- p_mtk_btif_dma p_rx_dma = NULL;
- BTIF_DBG_FUNC("++\n");
- for (index = 0; index < BTIF_PORT_NR; index++) {
- g_btif[index].open_counter = 0;
- g_btif[index].enable = false;
- p_tx_dma = &g_dma[index][BTIF_TX];
- p_rx_dma = &g_dma[index][BTIF_RX];
- #if ENABLE_BTIF_TX_DMA
- _btif_vfifo_deinit(p_tx_dma);
- #endif
- #if ENABLE_BTIF_RX_DMA
- _btif_vfifo_deinit(p_rx_dma);
- #endif
- _btif_state_deinit(&(g_btif[index]));
- _btif_rx_btm_deinit(&(g_btif[index]));
- mutex_destroy(&g_btif[index].ops_mtx);
- }
- #if !defined(CONFIG_MTK_CLKMGR)
- hal_btif_clk_unprepare();
- #endif
- driver_remove_file(&mtk_btif_dev_drv.driver, &driver_attr_flag);
- platform_driver_unregister(&mtk_btif_dev_drv);
- BTIF_DBG_FUNC("--\n");
- }
- int mtk_btif_hal_get_log_lvl(void)
- {
- return mtk_btif_dbg_lvl;
- }
- /*---------------------------------------------------------------------------*/
- module_init(BTIF_init);
- module_exit(BTIF_exit);
- /*---------------------------------------------------------------------------*/
- MODULE_AUTHOR("MBJ/WCN/SE/SS1/Chaozhong.Liang");
- MODULE_DESCRIPTION("MTK BTIF Driver$1.0$");
- MODULE_LICENSE("GPL");
- /*---------------------------------------------------------------------------*/
|