12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842 |
- /* Copyright (c) 2013, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- */
- #define pr_fmt(fmt) "%s: " fmt, __func__
- #include <linux/bitrev.h>
- #include <linux/crc-ccitt.h>
- #include <linux/delay.h>
- #include <linux/device.h>
- #include <linux/init.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/mutex.h>
- #include <linux/of.h>
- #include <linux/slab.h>
- #include <linux/string.h>
- #include <linux/workqueue.h>
- #include <linux/bif/consumer.h>
- #include <linux/bif/driver.h>
- /**
- * struct bif_ctrl_dev - holds controller device specific information
- * @list: Doubly-linked list parameter linking to other
- * BIF controllers registered in the system
- * @desc: Description structure for this BIF controller
- * @mutex: Mutex lock that is used to ensure mutual
- * exclusion between transactions performed on the
- * BIF bus for this controller
- * @ctrl_dev: Device pointer to the BIF controller device
- * @driver_data: Private data used by the BIF controller
- * @selected_sdev: Slave device that is currently selected on
- * the BIF bus of this controller
- * @bus_change_notifier: Head of a notifier list containing notifier
- * blocks that are notified when the battery
- * presence changes
- * @enter_irq_mode_work: Work task that is scheduled after a transaction
- * completes when there are consumers that are
- * actively monitoring BIF slave interrupts
- * @irq_count: This is a count of the total number of BIF slave
- * interrupts that are currently being monitored
- * for the BIF slaves connected to this BIF
- * controller
- * @irq_mode_delay_jiffies: Number of jiffies to wait before scheduling the
- * enter IRQ mode task. Using a larger value
- * helps to improve the performance of BIF
- * consumers that perform many BIF transactions.
- * Using a smaller value reduces the latency of
- * BIF slave interrupts.
- * @battery_present: Cached value of the battery presence. This is
- * used to filter out spurious presence update
- * calls when the battery presence state has not
- * changed.
- */
- struct bif_ctrl_dev {
- struct list_head list;
- struct bif_ctrl_desc *desc;
- struct mutex mutex;
- struct device *ctrl_dev;
- void *driver_data;
- struct bif_slave_dev *selected_sdev;
- struct blocking_notifier_head bus_change_notifier;
- struct delayed_work enter_irq_mode_work;
- int irq_count;
- int irq_mode_delay_jiffies;
- bool battery_present;
- };
- /**
- * struct bif_ctrl - handle used by BIF consumers for bus oriented BIF
- * operations
- * @bdev: Pointer to BIF controller device
- * @exclusive_lock: Flag which indicates that the BIF consumer responsible
- * for this handle has locked the BIF bus of this
- * controller. BIF transactions from other consumers are
- * blocked until the bus is unlocked.
- */
- struct bif_ctrl {
- struct bif_ctrl_dev *bdev;
- bool exclusive_lock;
- };
- /**
- * struct bif_slave_dev - holds BIF slave device information
- * @list: Doubly-linked list parameter linking to other
- * BIF slaves that have been enumerated
- * @bdev: Pointer to the BIF controller device that this
- * slave is physically connected to
- * @slave_addr: 8-bit BIF DEV_ADR assigned to this slave
- * @unique_id: 80-bit BIF unique ID of the slave
- * @unique_id_bits_known: Number of bits of the UID that are currently
- * known. This number starts is incremented during
- * a UID search and must end at 80 if the slave
- * responds to the search properly.
- * @present: Boolean value showing if this slave is
- * physically present in the system at a given
- * point in time. The value is set to false if the
- * battery pack containing the slave is
- * disconnected.
- * @l1_data: BIF DDB L1 data of the slave as read from the
- * slave's memory
- * @function_directory: Pointer to the BIF DDB L2 function directory
- * list as read from the slave's memory
- * @protocol_function: Pointer to constant protocol function data as
- * well as software state information if the slave
- * has a protocol function
- * @slave_ctrl_function: Pointer to constant slave control function data
- * as well as software state information if the
- * slave has a slave control function
- * @nvm_function: Pointer to constant non-volatile memory function
- * data as well as software state information if
- * the slave has a non-volatile memory function
- *
- * bif_slave_dev objects are stored indefinitely after enumeration in order to
- * speed up battery reinsertion. Only a UID check is needed after inserting a
- * battery assuming it has been enumerated before.
- *
- * unique_id bytes are stored such that unique_id[0] = MSB and
- * unique_id[BIF_UNIQUE_ID_BYTE_LENGTH - 1] = LSB
- */
- struct bif_slave_dev {
- struct list_head list;
- struct bif_ctrl_dev *bdev;
- u8 slave_addr;
- u8 unique_id[BIF_UNIQUE_ID_BYTE_LENGTH];
- int unique_id_bits_known;
- bool present;
- struct bif_ddb_l1_data l1_data;
- struct bif_ddb_l2_data *function_directory;
- struct bif_protocol_function *protocol_function;
- struct bif_slave_control_function *slave_ctrl_function;
- struct bif_nvm_function *nvm_function;
- };
- /**
- * struct bif_slave - handle used by BIF consumers for slave oriented BIF
- * operations
- * @ctrl: Consumer BIF controller handle data
- * @sdev: Pointer to BIF slave device
- */
- struct bif_slave {
- struct bif_ctrl ctrl;
- struct bif_slave_dev *sdev;
- };
- /* Number of times to retry a full BIF transaction before returning an error. */
- #define BIF_TRANSACTION_RETRY_COUNT 5
- static DEFINE_MUTEX(bif_ctrl_list_mutex);
- static LIST_HEAD(bif_ctrl_list);
- static DEFINE_MUTEX(bif_sdev_list_mutex);
- static LIST_HEAD(bif_sdev_list);
- static u8 next_dev_addr = 0x02;
- #define DEBUG_PRINT_BUFFER_SIZE 256
- static void fill_string(char *str, size_t str_len, u8 *buf, int buf_len)
- {
- int pos = 0;
- int i;
- for (i = 0; i < buf_len; i++) {
- pos += scnprintf(str + pos, str_len - pos, "0x%02X", buf[i]);
- if (i < buf_len - 1)
- pos += scnprintf(str + pos, str_len - pos, ", ");
- }
- }
- static void bif_print_slave_data(struct bif_slave_dev *sdev)
- {
- char str[DEBUG_PRINT_BUFFER_SIZE];
- u8 *uid;
- int i, j;
- struct bif_object *object;
- if (sdev->unique_id_bits_known != BIF_UNIQUE_ID_BIT_LENGTH)
- return;
- uid = sdev->unique_id;
- pr_debug("BIF slave: 0x%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X\n",
- uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6],
- uid[7], uid[8], uid[9]);
- pr_debug(" present=%d, dev_adr=0x%02X\n", sdev->present,
- sdev->slave_addr);
- pr_debug(" revision=0x%02X, level=0x%02X, device class=0x%04X\n",
- sdev->l1_data.revision, sdev->l1_data.level,
- sdev->l1_data.device_class);
- pr_debug(" manufacturer ID=0x%04X, product ID=0x%04X\n",
- sdev->l1_data.manufacturer_id, sdev->l1_data.product_id);
- pr_debug(" function directory length=%d\n", sdev->l1_data.length);
- for (i = 0; i < sdev->l1_data.length / 4; i++) {
- pr_debug(" Function %d: type=0x%02X, version=0x%02X, pointer=0x%04X\n",
- i, sdev->function_directory[i].function_type,
- sdev->function_directory[i].function_version,
- sdev->function_directory[i].function_pointer);
- }
- if (sdev->nvm_function) {
- pr_debug(" NVM function: pointer=0x%04X, task=%d, wr_buf_size=%d, nvm_base=0x%04X, nvm_size=%d, nvm_lock_offset=%d\n",
- sdev->nvm_function->nvm_pointer,
- sdev->nvm_function->slave_control_channel,
- (sdev->nvm_function->write_buffer_size
- ? sdev->nvm_function->write_buffer_size : 0),
- sdev->nvm_function->nvm_base_address,
- sdev->nvm_function->nvm_size,
- sdev->nvm_function->nvm_lock_offset);
- if (sdev->nvm_function->object_count)
- pr_debug(" NVM objects:\n");
- i = 0;
- list_for_each_entry(object, &sdev->nvm_function->object_list,
- list) {
- pr_debug(" Object %d - addr=0x%04X, data len=%d, type=0x%02X, version=0x%02X, manufacturer ID=0x%04X, crc=0x%04X\n",
- i, object->addr, object->length - 8,
- object->type, object->version,
- object->manufacturer_id, object->crc);
- for (j = 0; j < DIV_ROUND_UP(object->length - 8, 16);
- j++) {
- fill_string(str, DEBUG_PRINT_BUFFER_SIZE,
- object->data + j * 16,
- min(16, object->length - 8 - (j * 16)));
- pr_debug(" data(0x%04X): %s\n", j * 16,
- str);
- }
- i++;
- }
- }
- }
- static void bif_print_slaves(void)
- {
- struct bif_slave_dev *sdev;
- mutex_lock(&bif_sdev_list_mutex);
- list_for_each_entry(sdev, &bif_sdev_list, list) {
- /* Skip slaves without fully known UIDs. */
- if (sdev->unique_id_bits_known != BIF_UNIQUE_ID_BIT_LENGTH)
- continue;
- bif_print_slave_data(sdev);
- }
- mutex_unlock(&bif_sdev_list_mutex);
- }
- static struct bif_slave_dev *bif_add_slave(struct bif_ctrl_dev *bdev)
- {
- struct bif_slave_dev *sdev;
- sdev = kzalloc(sizeof(struct bif_slave_dev), GFP_KERNEL);
- if (sdev == NULL) {
- pr_err("Memory allocation failed for bif_slave_dev\n");
- return ERR_PTR(-ENOMEM);
- }
- sdev->bdev = bdev;
- INIT_LIST_HEAD(&sdev->list);
- list_add_tail(&sdev->list, &bif_sdev_list);
- return sdev;
- }
- static void bif_remove_slave(struct bif_slave_dev *sdev)
- {
- list_del(&sdev->list);
- if (sdev->bdev->selected_sdev == sdev)
- sdev->bdev->selected_sdev = NULL;
- if (sdev->slave_ctrl_function)
- kfree(sdev->slave_ctrl_function->irq_notifier_list);
- kfree(sdev->slave_ctrl_function);
- kfree(sdev->protocol_function);
- kfree(sdev->function_directory);
- kfree(sdev);
- }
- /* This function assumes that the uid array is all 0 to start with. */
- static void set_uid_bit(u8 uid[BIF_UNIQUE_ID_BYTE_LENGTH], unsigned int bit,
- unsigned int value)
- {
- u8 mask;
- if (bit >= BIF_UNIQUE_ID_BIT_LENGTH)
- return;
- mask = 1 << (7 - (bit % 8));
- uid[bit / 8] &= ~mask;
- uid[bit / 8] |= value << (7 - (bit % 8));
- }
- static unsigned int get_uid_bit(u8 uid[BIF_UNIQUE_ID_BYTE_LENGTH],
- unsigned int bit)
- {
- if (bit >= BIF_UNIQUE_ID_BIT_LENGTH)
- return 0;
- return (uid[bit / 8] & (1 << (7 - (bit % 8)))) ? 1 : 0;
- }
- static void bif_enter_irq_mode_work(struct work_struct *work)
- {
- struct delayed_work *dwork = to_delayed_work(work);
- struct bif_ctrl_dev *bdev
- = container_of(dwork, struct bif_ctrl_dev, enter_irq_mode_work);
- int rc, i;
- mutex_lock(&bdev->mutex);
- for (i = 0; i < BIF_TRANSACTION_RETRY_COUNT; i++) {
- rc = bdev->desc->ops->set_bus_state(bdev,
- BIF_BUS_STATE_INTERRUPT);
- if (rc == 0)
- break;
- }
- mutex_unlock(&bdev->mutex);
- /* Reschedule the task if the transaction failed. */
- if (rc) {
- pr_err("Could not set BIF bus to interrupt mode, rc=%d\n", rc);
- schedule_delayed_work(&bdev->enter_irq_mode_work,
- bdev->irq_mode_delay_jiffies);
- }
- }
- static void bif_cancel_irq_mode_work(struct bif_ctrl_dev *bdev)
- {
- cancel_delayed_work(&bdev->enter_irq_mode_work);
- }
- static void bif_schedule_irq_mode_work(struct bif_ctrl_dev *bdev)
- {
- if (bdev->irq_count > 0 &&
- bdev->desc->ops->get_bus_state(bdev) != BIF_BUS_STATE_INTERRUPT)
- schedule_delayed_work(&bdev->enter_irq_mode_work,
- bdev->irq_mode_delay_jiffies);
- }
- static int _bif_select_slave_no_retry(struct bif_slave_dev *sdev)
- {
- struct bif_ctrl_dev *bdev = sdev->bdev;
- int rc = 0;
- int i;
- /* Check if the slave is already selected. */
- if (sdev->bdev->selected_sdev == sdev)
- return 0;
- if (sdev->slave_addr) {
- /* Select using DEV_ADR. */
- rc = bdev->desc->ops->bus_transaction(bdev, BIF_TRANS_SDA,
- sdev->slave_addr);
- if (!rc)
- sdev->bdev->selected_sdev = sdev;
- } else if (sdev->unique_id_bits_known == BIF_UNIQUE_ID_BIT_LENGTH) {
- /* Select using full UID. */
- for (i = 0; i < BIF_UNIQUE_ID_BYTE_LENGTH - 1; i++) {
- rc = bdev->desc->ops->bus_transaction(bdev,
- BIF_TRANS_EDA, sdev->unique_id[i]);
- if (rc)
- goto out;
- }
- rc = bdev->desc->ops->bus_transaction(bdev, BIF_TRANS_SDA,
- sdev->unique_id[BIF_UNIQUE_ID_BYTE_LENGTH - 1]);
- if (rc)
- goto out;
- } else {
- pr_err("Cannot select slave because it has neither UID nor DEV_ADR.\n");
- return -EINVAL;
- }
- sdev->bdev->selected_sdev = sdev;
- return 0;
- out:
- pr_err("bus_transaction failed, rc=%d\n", rc);
- return rc;
- }
- static int bif_select_slave(struct bif_slave_dev *sdev)
- {
- int rc = -EPERM;
- int i;
- for (i = 0; i < BIF_TRANSACTION_RETRY_COUNT; i++) {
- rc = _bif_select_slave_no_retry(sdev);
- if (rc == 0)
- break;
- /* Force slave reselection. */
- sdev->bdev->selected_sdev = NULL;
- }
- return rc;
- }
- /*
- * Returns 1 if slave is selected, 0 if slave is not selected, or errno if
- * error.
- */
- static int bif_is_slave_selected(struct bif_ctrl_dev *bdev)
- {
- int rc = -EPERM;
- int tack, i;
- for (i = 0; i < BIF_TRANSACTION_RETRY_COUNT; i++) {
- /* Attempt a transaction query. */
- rc = bdev->desc->ops->bus_transaction_read(bdev, BIF_TRANS_BC,
- BIF_CMD_TQ, &tack);
- if (rc == 0 || rc == -ETIMEDOUT)
- break;
- }
- if (rc == 0)
- rc = 1;
- else if (rc == -ETIMEDOUT)
- rc = 0;
- else
- pr_err("BIF bus_transaction_read failed, rc=%d\n", rc);
- return rc;
- }
- /* Read from a specified number of consecutive registers. */
- static int _bif_slave_read_no_retry(struct bif_slave_dev *sdev, u16 addr,
- u8 *buf, int len)
- {
- struct bif_ctrl_dev *bdev = sdev->bdev;
- int rc = 0;
- int i, response;
- rc = bif_select_slave(sdev);
- if (rc)
- return rc;
- if (bdev->desc->ops->read_slave_registers) {
- /*
- * Use low level slave register read implementation in order to
- * receive the benefits of BIF burst reads.
- */
- rc = bdev->desc->ops->read_slave_registers(bdev, addr, buf,
- len);
- if (rc)
- pr_debug("read_slave_registers failed, rc=%d\n", rc);
- else
- return rc;
- /*
- * Fall back on individual transactions if high level register
- * read failed.
- */
- }
- for (i = 0; i < len; i++) {
- rc = bdev->desc->ops->bus_transaction(bdev, BIF_TRANS_ERA,
- addr >> 8);
- if (rc) {
- pr_err("bus_transaction failed, rc=%d\n", rc);
- return rc;
- }
- rc = bdev->desc->ops->bus_transaction_read(bdev, BIF_TRANS_RRA,
- addr & 0xFF, &response);
- if (rc) {
- pr_err("bus_transaction_read failed, rc=%d\n", rc);
- return rc;
- }
- if (!(response & BIF_SLAVE_RD_ACK)) {
- pr_err("BIF register read error=0x%02X\n",
- response & BIF_SLAVE_RD_ERR);
- return -EIO;
- }
- buf[i] = response & BIF_SLAVE_RD_DATA;
- addr++;
- }
- return rc;
- }
- /*
- * Read from a specified number of consecutive registers. Retry the transaction
- * several times in case of communcation failures.
- */
- static int _bif_slave_read(struct bif_slave_dev *sdev, u16 addr, u8 *buf,
- int len)
- {
- int rc = -EPERM;
- int i;
- for (i = 0; i < BIF_TRANSACTION_RETRY_COUNT; i++) {
- rc = _bif_slave_read_no_retry(sdev, addr, buf, len);
- if (rc == 0)
- break;
- /* Force slave reselection. */
- sdev->bdev->selected_sdev = NULL;
- }
- return rc;
- }
- /* Write to a specified number of consecutive registers. */
- static int _bif_slave_write_no_retry(struct bif_slave_dev *sdev, u16 addr,
- u8 *buf, int len)
- {
- struct bif_ctrl_dev *bdev = sdev->bdev;
- int rc = 0;
- int i;
- rc = bif_select_slave(sdev);
- if (rc)
- return rc;
- if (bdev->desc->ops->write_slave_registers) {
- /*
- * Use low level slave register write implementation in order to
- * receive the benefits of BIF burst writes.
- */
- rc = bdev->desc->ops->write_slave_registers(bdev, addr, buf,
- len);
- if (rc)
- pr_debug("write_slave_registers failed, rc=%d\n", rc);
- else
- return rc;
- /*
- * Fall back on individual transactions if high level register
- * write failed.
- */
- }
- rc = bdev->desc->ops->bus_transaction(bdev, BIF_TRANS_ERA, addr >> 8);
- if (rc)
- goto out;
- rc = bdev->desc->ops->bus_transaction(bdev, BIF_TRANS_WRA, addr & 0xFF);
- if (rc)
- goto out;
- for (i = 0; i < len; i++) {
- rc = bdev->desc->ops->bus_transaction(bdev, BIF_TRANS_WD,
- buf[i]);
- if (rc)
- goto out;
- }
- return 0;
- out:
- pr_err("bus_transaction failed, rc=%d\n", rc);
- return rc;
- }
- /*
- * Write to a specified number of consecutive registers. Retry the transaction
- * several times in case of communcation failures.
- */
- static int _bif_slave_write(struct bif_slave_dev *sdev, u16 addr, u8 *buf,
- int len)
- {
- int rc = -EPERM;
- int i;
- for (i = 0; i < BIF_TRANSACTION_RETRY_COUNT; i++) {
- rc = _bif_slave_write_no_retry(sdev, addr, buf, len);
- if (rc == 0)
- break;
- /* Force slave reselection. */
- sdev->bdev->selected_sdev = NULL;
- }
- return rc;
- }
- /* Perform a read-modify-write sequence on a single BIF slave register. */
- static int _bif_slave_masked_write(struct bif_slave_dev *sdev, u16 addr, u8 val,
- u8 mask)
- {
- int rc;
- u8 reg;
- rc = _bif_slave_read(sdev, addr, ®, 1);
- if (rc)
- return rc;
- reg = (reg & ~mask) | (val & mask);
- return _bif_slave_write(sdev, addr, ®, 1);
- }
- static int _bif_check_task(struct bif_slave_dev *sdev, unsigned int task)
- {
- if (IS_ERR_OR_NULL(sdev)) {
- pr_err("Invalid slave device handle=%ld\n", PTR_ERR(sdev));
- return -EINVAL;
- } else if (!sdev->bdev) {
- pr_err("BIF controller has been removed\n");
- return -ENXIO;
- } else if (!sdev->slave_ctrl_function
- || sdev->slave_ctrl_function->task_count == 0) {
- pr_err("BIF slave does not support slave control\n");
- return -ENODEV;
- } else if (task >= sdev->slave_ctrl_function->task_count) {
- pr_err("Requested task: %u greater than max: %u for this slave\n",
- task, sdev->slave_ctrl_function->task_count);
- return -EINVAL;
- }
- return 0;
- }
- static int _bif_task_is_busy(struct bif_slave_dev *sdev, unsigned int task)
- {
- int rc;
- u16 addr;
- u8 reg = 0;
- rc = _bif_check_task(sdev, task);
- if (rc) {
- pr_err("Invalid slave device or task, rc=%d\n", rc);
- return rc;
- }
- /* Check the task busy state. */
- addr = SLAVE_CTRL_FUNC_TASK_BUSY_ADDR(
- sdev->slave_ctrl_function->slave_ctrl_pointer, task);
- rc = _bif_slave_read(sdev, addr, ®, 1);
- if (rc) {
- pr_err("BIF slave register read failed, rc=%d\n", rc);
- return rc;
- }
- return (reg & BIT(task % SLAVE_CTRL_TASKS_PER_SET)) ? 1 : 0;
- }
- static int _bif_enable_auto_task(struct bif_slave_dev *sdev, unsigned int task)
- {
- int rc;
- u16 addr;
- u8 mask;
- rc = _bif_check_task(sdev, task);
- if (rc) {
- pr_err("Invalid slave device or task, rc=%d\n", rc);
- return rc;
- }
- /* Enable the auto task within the slave */
- mask = BIT(task % SLAVE_CTRL_TASKS_PER_SET);
- addr = SLAVE_CTRL_FUNC_TASK_AUTO_TRIGGER_ADDR(
- sdev->slave_ctrl_function->slave_ctrl_pointer, task);
- if (task / SLAVE_CTRL_TASKS_PER_SET == 0) {
- /* Set global auto task enable. */
- mask |= BIT(0);
- }
- rc = _bif_slave_masked_write(sdev, addr, 0xFF, mask);
- if (rc) {
- pr_err("BIF slave register masked write failed, rc=%d\n", rc);
- return rc;
- }
- /* Set global auto task enable if task not in set 0. */
- if (task / SLAVE_CTRL_TASKS_PER_SET != 0) {
- addr = SLAVE_CTRL_FUNC_TASK_AUTO_TRIGGER_ADDR(
- sdev->slave_ctrl_function->slave_ctrl_pointer, 0);
- rc = _bif_slave_masked_write(sdev, addr, 0xFF, BIT(0));
- if (rc) {
- pr_err("BIF slave register masked write failed, rc=%d\n",
- rc);
- return rc;
- }
- }
- return rc;
- }
- static int _bif_disable_auto_task(struct bif_slave_dev *sdev, unsigned int task)
- {
- int rc;
- u16 addr;
- u8 mask;
- rc = _bif_check_task(sdev, task);
- if (rc) {
- pr_err("Invalid slave or task, rc=%d\n", rc);
- return rc;
- }
- /* Disable the auto task within the slave */
- mask = BIT(task % SLAVE_CTRL_TASKS_PER_SET);
- addr = SLAVE_CTRL_FUNC_TASK_AUTO_TRIGGER_ADDR(
- sdev->slave_ctrl_function->slave_ctrl_pointer, task);
- rc = _bif_slave_masked_write(sdev, addr, 0x00, mask);
- if (rc) {
- pr_err("BIF slave register masked write failed, rc=%d\n", rc);
- return rc;
- }
- return rc;
- }
- /*
- * The MIPI-BIF spec does not define a maximum time in which an NVM write must
- * complete. The following delay and recheck count therefore represent
- * arbitrary but reasonable values.
- */
- #define NVM_WRITE_POLL_DELAY_MS 20
- #define NVM_WRITE_MAX_POLL_COUNT 50
- static int _bif_slave_nvm_raw_write(struct bif_slave_dev *sdev, u16 offset,
- u8 *buf, int len)
- {
- int rc = 0;
- int write_len, poll_count, rc2;
- u8 write_buf[3];
- if (!sdev->nvm_function) {
- pr_err("BIF slave has no NVM function\n");
- return -ENODEV;
- } else if (offset + len > sdev->nvm_function->nvm_size) {
- pr_err("write offset + len = %d > NVM size = %d\n",
- offset + len, sdev->nvm_function->nvm_size);
- return -EINVAL;
- } else if (offset < sdev->nvm_function->nvm_lock_offset) {
- pr_err("write offset = %d < first writable offset = %d\n",
- offset, sdev->nvm_function->nvm_lock_offset);
- return -EINVAL;
- }
- rc = _bif_enable_auto_task(sdev,
- sdev->nvm_function->slave_control_channel);
- if (rc) {
- pr_err("Failed to enable NVM auto task, rc=%d\n", rc);
- return rc;
- }
- while (len > 0) {
- write_len = sdev->nvm_function->write_buffer_size;
- if (write_len == 0)
- write_len = 256;
- write_len = min(write_len, len);
- write_buf[0] = offset >> 8;
- write_buf[1] = offset;
- write_buf[2] = (write_len == 256) ? 0 : write_len;
- /* Write offset and size registers. */
- rc = _bif_slave_write(sdev, sdev->nvm_function->nvm_pointer + 6,
- write_buf, 3);
- if (rc) {
- pr_err("BIF slave write failed, rc=%d\n", rc);
- goto done;
- }
- /* Write to NVM write buffer registers. */
- rc = _bif_slave_write(sdev, sdev->nvm_function->nvm_pointer + 9,
- buf, write_len);
- if (rc) {
- pr_err("BIF slave write failed, rc=%d\n", rc);
- goto done;
- }
- /*
- * Wait for completion of the NVM write which was auto-triggered
- * by the register write of the last byte in the NVM write
- * buffer.
- */
- poll_count = NVM_WRITE_MAX_POLL_COUNT;
- do {
- msleep(NVM_WRITE_POLL_DELAY_MS);
- rc = _bif_task_is_busy(sdev,
- sdev->nvm_function->slave_control_channel);
- poll_count--;
- } while (rc > 0 && poll_count > 0);
- if (rc < 0) {
- pr_err("Failed to check task state, rc=%d", rc);
- goto done;
- } else if (rc > 0) {
- pr_err("BIF slave NVM write not completed after %d ms\n",
- NVM_WRITE_POLL_DELAY_MS * NVM_WRITE_MAX_POLL_COUNT);
- rc = -ETIMEDOUT;
- goto done;
- }
- len -= write_len;
- offset += write_len;
- buf += write_len;
- }
- done:
- rc2 = _bif_disable_auto_task(sdev,
- sdev->nvm_function->slave_control_channel);
- if (rc2) {
- pr_err("Failed to disable NVM auto task, rc=%d\n", rc2);
- return rc2;
- }
- return rc;
- }
- /* Takes a mutex if this consumer is not an exclusive bus user. */
- static void bif_ctrl_lock(struct bif_ctrl *ctrl)
- {
- if (!ctrl->exclusive_lock) {
- mutex_lock(&ctrl->bdev->mutex);
- bif_cancel_irq_mode_work(ctrl->bdev);
- }
- }
- /* Releases a mutex if this consumer is not an exclusive bus user. */
- static void bif_ctrl_unlock(struct bif_ctrl *ctrl)
- {
- if (!ctrl->exclusive_lock) {
- bif_schedule_irq_mode_work(ctrl->bdev);
- mutex_unlock(&ctrl->bdev->mutex);
- }
- }
- static void bif_slave_ctrl_lock(struct bif_slave *slave)
- {
- bif_ctrl_lock(&slave->ctrl);
- }
- static void bif_slave_ctrl_unlock(struct bif_slave *slave)
- {
- bif_ctrl_unlock(&slave->ctrl);
- }
- /**
- * bif_crc_ccitt() - calculate the CRC-CCITT CRC value of the data specified
- * @buffer: Data to calculate the CRC of
- * @len: Length of the data buffer in bytes
- *
- * MIPI-BIF specifies the usage of CRC-CCITT for BIF data objects. This
- * function performs the CRC calculation while taking into account the bit
- * ordering used by BIF.
- */
- u16 bif_crc_ccitt(const u8 *buffer, unsigned int len)
- {
- u16 crc = 0xFFFF;
- while (len--) {
- crc = crc_ccitt_byte(crc, bitrev8(*buffer));
- buffer++;
- }
- return bitrev16(crc);
- }
- EXPORT_SYMBOL(bif_crc_ccitt);
- static u16 bif_object_crc_ccitt(const struct bif_object *object)
- {
- u16 crc = 0xFFFF;
- int i;
- crc = crc_ccitt_byte(crc, bitrev8(object->type));
- crc = crc_ccitt_byte(crc, bitrev8(object->version));
- crc = crc_ccitt_byte(crc, bitrev8(object->manufacturer_id >> 8));
- crc = crc_ccitt_byte(crc, bitrev8(object->manufacturer_id));
- crc = crc_ccitt_byte(crc, bitrev8(object->length >> 8));
- crc = crc_ccitt_byte(crc, bitrev8(object->length));
- for (i = 0; i < object->length - 8; i++)
- crc = crc_ccitt_byte(crc, bitrev8(object->data[i]));
- return bitrev16(crc);
- }
- static int bif_check_task(struct bif_slave *slave, unsigned int task)
- {
- if (IS_ERR_OR_NULL(slave)) {
- pr_err("Invalid slave pointer=%ld\n", PTR_ERR(slave));
- return -EINVAL;
- }
- return _bif_check_task(slave->sdev, task);
- }
- /**
- * bif_request_irq() - request a BIF slave IRQ by slave task number
- * @slave: BIF slave handle
- * @task: BIF task number of the IRQ inside of the slave. This
- * corresponds to the slave control channel specified for a given
- * BIF function inside of the slave.
- * @nb: Notifier block to call when the IRQ fires
- *
- * This function registers a notifier block to call when the BIF slave interrupt
- * is triggered and also enables the interrupt. The interrupt is enabled inside
- * of the BIF slave's slave control function and also the BIF bus is put into
- * interrupt mode.
- *
- * Returns 0 for success or errno if an error occurred.
- */
- int bif_request_irq(struct bif_slave *slave, unsigned int task,
- struct notifier_block *nb)
- {
- int rc;
- u16 addr;
- u8 reg, mask;
- rc = bif_check_task(slave, task);
- if (rc) {
- pr_err("Invalid slave or task, rc=%d\n", rc);
- return rc;
- }
- bif_slave_ctrl_lock(slave);
- rc = blocking_notifier_chain_register(
- &slave->sdev->slave_ctrl_function->irq_notifier_list[task], nb);
- if (rc) {
- pr_err("Notifier registration failed, rc=%d\n", rc);
- goto done;
- }
- /* Enable the interrupt within the slave */
- mask = BIT(task % SLAVE_CTRL_TASKS_PER_SET);
- addr = SLAVE_CTRL_FUNC_IRQ_EN_ADDR(
- slave->sdev->slave_ctrl_function->slave_ctrl_pointer, task);
- if (task / SLAVE_CTRL_TASKS_PER_SET == 0) {
- /* Set global interrupt enable. */
- mask |= BIT(0);
- }
- rc = _bif_slave_read(slave->sdev, addr, ®, 1);
- if (rc) {
- pr_err("BIF slave register read failed, rc=%d\n", rc);
- goto notifier_unregister;
- }
- reg |= mask;
- rc = _bif_slave_write(slave->sdev, addr, ®, 1);
- if (rc) {
- pr_err("BIF slave register write failed, rc=%d\n", rc);
- goto notifier_unregister;
- }
- /* Set global interrupt enable if task not in set 0. */
- if (task / SLAVE_CTRL_TASKS_PER_SET != 0) {
- mask = BIT(0);
- addr = SLAVE_CTRL_FUNC_IRQ_EN_ADDR(
- slave->sdev->slave_ctrl_function->slave_ctrl_pointer, 0);
- rc = _bif_slave_read(slave->sdev, addr, ®, 1);
- if (rc) {
- pr_err("BIF slave register read failed, rc=%d\n", rc);
- goto notifier_unregister;
- }
- reg |= mask;
- rc = _bif_slave_write(slave->sdev, addr, ®, 1);
- if (rc) {
- pr_err("BIF slave register write failed, rc=%d\n", rc);
- goto notifier_unregister;
- }
- }
- rc = slave->sdev->bdev->desc->ops->set_bus_state(slave->sdev->bdev,
- BIF_BUS_STATE_INTERRUPT);
- if (rc) {
- pr_err("Could not set BIF bus to interrupt mode, rc=%d\n", rc);
- goto notifier_unregister;
- }
- slave->sdev->bdev->irq_count++;
- done:
- bif_slave_ctrl_unlock(slave);
- return rc;
- notifier_unregister:
- blocking_notifier_chain_unregister(
- &slave->sdev->slave_ctrl_function->irq_notifier_list[task],
- nb);
- bif_slave_ctrl_unlock(slave);
- return rc;
- }
- EXPORT_SYMBOL(bif_request_irq);
- /**
- * bif_free_irq() - free a BIF slave IRQ by slave task number
- * @slave: BIF slave handle
- * @task: BIF task number of the IRQ inside of the slave. This
- * corresponds to the slave control channel specified for a given
- * BIF function inside of the slave.
- * @nb: Notifier block previously registered with this interrupt
- *
- * This function unregisters a notifier block that was previously registered
- * with bif_request_irq().
- *
- * Returns 0 for success or errno if an error occurred.
- */
- int bif_free_irq(struct bif_slave *slave, unsigned int task,
- struct notifier_block *nb)
- {
- int rc;
- u16 addr;
- u8 reg;
- rc = bif_check_task(slave, task);
- if (rc) {
- pr_err("Invalid slave or task, rc=%d\n", rc);
- return rc;
- }
- bif_slave_ctrl_lock(slave);
- /* Disable the interrupt within the slave */
- reg = BIT(task % SLAVE_CTRL_TASKS_PER_SET);
- addr = SLAVE_CTRL_FUNC_IRQ_CLEAR_ADDR(
- slave->sdev->slave_ctrl_function->slave_ctrl_pointer, task);
- rc = _bif_slave_write(slave->sdev, addr, ®, 1);
- if (rc) {
- pr_err("BIF slave register write failed, rc=%d\n", rc);
- goto done;
- }
- rc = blocking_notifier_chain_unregister(
- &slave->sdev->slave_ctrl_function->irq_notifier_list[task], nb);
- if (rc) {
- pr_err("Notifier unregistration failed, rc=%d\n", rc);
- goto done;
- }
- slave->sdev->bdev->irq_count--;
- if (slave->sdev->bdev->irq_count == 0) {
- bif_cancel_irq_mode_work(slave->sdev->bdev);
- } else if (slave->sdev->bdev->irq_count < 0) {
- pr_err("Unbalanced IRQ free.\n");
- rc = -EINVAL;
- slave->sdev->bdev->irq_count = 0;
- }
- done:
- bif_slave_ctrl_unlock(slave);
- return rc;
- }
- EXPORT_SYMBOL(bif_free_irq);
- /**
- * bif_trigger_task() - trigger a task within a BIF slave
- * @slave: BIF slave handle
- * @task: BIF task inside of the slave to trigger. This corresponds to
- * the slave control channel specified for a given BIF function
- * inside of the slave.
- *
- * Returns 0 for success or errno if an error occurred.
- */
- int bif_trigger_task(struct bif_slave *slave, unsigned int task)
- {
- int rc;
- u16 addr;
- u8 reg;
- rc = bif_check_task(slave, task);
- if (rc) {
- pr_err("Invalid slave or task, rc=%d\n", rc);
- return rc;
- }
- bif_slave_ctrl_lock(slave);
- /* Trigger the task within the slave. */
- reg = BIT(task % SLAVE_CTRL_TASKS_PER_SET);
- addr = SLAVE_CTRL_FUNC_TASK_TRIGGER_ADDR(
- slave->sdev->slave_ctrl_function->slave_ctrl_pointer, task);
- rc = _bif_slave_write(slave->sdev, addr, ®, 1);
- if (rc) {
- pr_err("BIF slave register write failed, rc=%d\n", rc);
- goto done;
- }
- done:
- bif_slave_ctrl_unlock(slave);
- return rc;
- }
- EXPORT_SYMBOL(bif_trigger_task);
- /**
- * bif_enable_auto_task() - enable task auto triggering for the specified task
- * @slave: BIF slave handle
- * @task: BIF task inside of the slave to configure for automatic
- * triggering. This corresponds to the slave control channel
- * specified for a given BIF function inside of the slave.
- *
- * Returns 0 for success or errno if an error occurred.
- */
- int bif_enable_auto_task(struct bif_slave *slave, unsigned int task)
- {
- int rc;
- if (IS_ERR_OR_NULL(slave)) {
- pr_err("Invalid slave pointer=%ld\n", PTR_ERR(slave));
- return -EINVAL;
- }
- bif_slave_ctrl_lock(slave);
- rc = _bif_enable_auto_task(slave->sdev, task);
- bif_slave_ctrl_unlock(slave);
- return rc;
- }
- EXPORT_SYMBOL(bif_enable_auto_task);
- /**
- * bif_disable_auto_task() - disable task auto triggering for the specified task
- * @slave: BIF slave handle
- * @task: BIF task inside of the slave to stop automatic triggering on.
- * This corresponds to the slave control channel specified for a
- * given BIF function inside of the slave.
- *
- * This function should be called after bif_enable_auto_task() in a paired
- * fashion.
- *
- * Returns 0 for success or errno if an error occurred.
- */
- int bif_disable_auto_task(struct bif_slave *slave, unsigned int task)
- {
- int rc;
- if (IS_ERR_OR_NULL(slave)) {
- pr_err("Invalid slave pointer=%ld\n", PTR_ERR(slave));
- return -EINVAL;
- }
- bif_slave_ctrl_lock(slave);
- rc = _bif_disable_auto_task(slave->sdev, task);
- bif_slave_ctrl_unlock(slave);
- return rc;
- }
- EXPORT_SYMBOL(bif_disable_auto_task);
- /**
- * bif_task_is_busy() - checks the state of a BIF slave task
- * @slave: BIF slave handle
- * @task: BIF task inside of the slave to trigger. This corresponds to
- * the slave control channel specified for a given BIF function
- * inside of the slave.
- *
- * Returns 1 if the task is busy, 0 if it is not busy, and errno on error.
- */
- int bif_task_is_busy(struct bif_slave *slave, unsigned int task)
- {
- int rc;
- if (IS_ERR_OR_NULL(slave)) {
- pr_err("Invalid slave pointer=%ld\n", PTR_ERR(slave));
- return -EINVAL;
- }
- bif_slave_ctrl_lock(slave);
- rc = _bif_task_is_busy(slave->sdev, task);
- bif_slave_ctrl_unlock(slave);
- return rc;
- }
- EXPORT_SYMBOL(bif_task_is_busy);
- static int bif_slave_notify_irqs(struct bif_slave_dev *sdev, int set, u8 val)
- {
- int rc = 0;
- int i, task;
- for (i = 0; i < SLAVE_CTRL_TASKS_PER_SET; i++) {
- if (val & (1 << i)) {
- task = set * SLAVE_CTRL_TASKS_PER_SET + i;
- rc = blocking_notifier_call_chain(
- &sdev->slave_ctrl_function->irq_notifier_list[task],
- task, sdev->bdev);
- rc = notifier_to_errno(rc);
- if (rc)
- pr_err("Notification failed for task %d\n",
- task);
- }
- }
- return rc;
- }
- static int bif_slave_handle_irq(struct bif_slave_dev *sdev)
- {
- struct bif_ctrl_dev *bdev = sdev->bdev;
- bool resp = false;
- int rc = 0;
- int i;
- u16 addr;
- u8 reg;
- mutex_lock(&sdev->bdev->mutex);
- bif_cancel_irq_mode_work(sdev->bdev);
- rc = bif_select_slave(sdev);
- if (rc) {
- pr_err("Could not select slave, rc=%d\n", rc);
- goto done;
- }
- /* Check overall slave interrupt status. */
- rc = bdev->desc->ops->bus_transaction_query(bdev, BIF_TRANS_BC,
- BIF_CMD_ISTS, &resp);
- if (rc) {
- pr_err("Could not query slave interrupt status, rc=%d\n", rc);
- goto done;
- }
- if (resp) {
- for (i = 0; i < sdev->slave_ctrl_function->task_count
- / SLAVE_CTRL_TASKS_PER_SET; i++) {
- addr = sdev->slave_ctrl_function->slave_ctrl_pointer
- + 4 * i + 1;
- rc = _bif_slave_read(sdev, addr, ®, 1);
- if (rc) {
- pr_err("BIF slave register read failed, rc=%d\n",
- rc);
- goto done;
- }
- /* Ensure that interrupts are pending in the set. */
- if (reg != 0x00) {
- /*
- * Release mutex before notifying consumers so
- * that they can use the bus.
- */
- mutex_unlock(&sdev->bdev->mutex);
- rc = bif_slave_notify_irqs(sdev, i, reg);
- if (rc) {
- pr_err("BIF slave irq notification failed, rc=%d\n",
- rc);
- goto notification_failed;
- }
- mutex_lock(&sdev->bdev->mutex);
- rc = bif_select_slave(sdev);
- if (rc) {
- pr_err("Could not select slave, rc=%d\n",
- rc);
- goto done;
- }
- /* Clear all interrupts in this set. */
- rc = _bif_slave_write(sdev, addr, ®, 1);
- if (rc) {
- pr_err("BIF slave register write failed, rc=%d\n",
- rc);
- goto done;
- }
- }
- }
- }
- done:
- bif_schedule_irq_mode_work(sdev->bdev);
- mutex_unlock(&sdev->bdev->mutex);
- notification_failed:
- if (rc == 0)
- rc = resp;
- return rc;
- }
- /**
- * bif_ctrl_notify_slave_irq() - notify the BIF framework that a slave interrupt
- * was received by a BIF controller
- * @bdev: BIF controller device pointer
- *
- * This function should only be called from a BIF controller driver.
- *
- * Returns 0 for success or errno if an error occurred.
- */
- int bif_ctrl_notify_slave_irq(struct bif_ctrl_dev *bdev)
- {
- struct bif_slave_dev *sdev;
- int rc = 0, handled = 0;
- if (IS_ERR_OR_NULL(bdev))
- return -EINVAL;
- mutex_lock(&bif_sdev_list_mutex);
- list_for_each_entry(sdev, &bif_sdev_list, list) {
- if (sdev->bdev == bdev && sdev->present) {
- rc = bif_slave_handle_irq(sdev);
- if (rc < 0) {
- pr_err("Could not handle BIF slave irq, rc=%d\n",
- rc);
- break;
- }
- handled += rc;
- }
- }
- mutex_unlock(&bif_sdev_list_mutex);
- if (handled == 0)
- pr_info("Spurious BIF slave interrupt detected.\n");
- if (rc > 0)
- rc = 0;
- return rc;
- }
- EXPORT_SYMBOL(bif_ctrl_notify_slave_irq);
- /**
- * bif_ctrl_notify_battery_changed() - notify the BIF framework that a battery
- * pack has been inserted or removed
- * @bdev: BIF controller device pointer
- *
- * This function should only be called from a BIF controller driver.
- *
- * Returns 0 for success or errno if an error occurred.
- */
- int bif_ctrl_notify_battery_changed(struct bif_ctrl_dev *bdev)
- {
- int rc = 0;
- int present;
- if (IS_ERR_OR_NULL(bdev))
- return -EINVAL;
- if (bdev->desc->ops->get_battery_presence) {
- present = bdev->desc->ops->get_battery_presence(bdev);
- if (present < 0) {
- pr_err("Could not determine battery presence, rc=%d\n",
- rc);
- return rc;
- }
- if (bdev->battery_present == !!present)
- return 0;
- bdev->battery_present = present;
- rc = blocking_notifier_call_chain(&bdev->bus_change_notifier,
- present ? BIF_BUS_EVENT_BATTERY_INSERTED
- : BIF_BUS_EVENT_BATTERY_REMOVED, bdev);
- if (rc)
- pr_err("Call chain noification failed, rc=%d\n", rc);
- }
- return rc;
- }
- EXPORT_SYMBOL(bif_ctrl_notify_battery_changed);
- /**
- * bif_ctrl_signal_battery_changed() - notify the BIF framework that a battery
- * pack has been inserted or removed
- * @ctrl: BIF controller consumer handle
- *
- * This function should only be called by a BIF consumer driver on systems where
- * the BIF controller driver is unable to determine when a battery is inserted
- * or removed.
- *
- * Returns 0 for success or errno if an error occurred.
- */
- int bif_ctrl_signal_battery_changed(struct bif_ctrl *ctrl)
- {
- if (IS_ERR_OR_NULL(ctrl))
- return -EINVAL;
- return bif_ctrl_notify_battery_changed(ctrl->bdev);
- }
- EXPORT_SYMBOL(bif_ctrl_signal_battery_changed);
- /**
- * bif_ctrl_notifier_register() - register a notifier block to be called when
- * a battery pack is inserted or removed
- * @ctrl: BIF controller consumer handle
- *
- * The value passed into the notifier when it is called is one of
- * enum bif_bus_event.
- *
- * Returns 0 for success or errno if an error occurred.
- */
- int bif_ctrl_notifier_register(struct bif_ctrl *ctrl, struct notifier_block *nb)
- {
- int rc;
- if (IS_ERR_OR_NULL(ctrl))
- return -EINVAL;
- rc = blocking_notifier_chain_register(&ctrl->bdev->bus_change_notifier,
- nb);
- if (rc)
- pr_err("Notifier registration failed, rc=%d\n", rc);
- return rc;
- }
- EXPORT_SYMBOL(bif_ctrl_notifier_register);
- /**
- * bif_ctrl_notifier_unregister() - unregister a battery status change notifier
- * block that was previously registered
- * @ctrl: BIF controller consumer handle
- *
- * Returns 0 for success or errno if an error occurred.
- */
- int bif_ctrl_notifier_unregister(struct bif_ctrl *ctrl,
- struct notifier_block *nb)
- {
- int rc;
- if (IS_ERR_OR_NULL(ctrl))
- return -EINVAL;
- rc =
- blocking_notifier_chain_unregister(&ctrl->bdev->bus_change_notifier,
- nb);
- if (rc)
- pr_err("Notifier unregistration failed, rc=%d\n", rc);
- return rc;
- }
- EXPORT_SYMBOL(bif_ctrl_notifier_unregister);
- /**
- * bif_get_bus_handle() - returns the BIF controller consumer handle associated
- * with a BIF slave handle
- * @slave: BIF slave handle
- *
- * Note, bif_ctrl_put() should never be called for the pointer output by
- * bif_get_bus_handle().
- */
- struct bif_ctrl *bif_get_bus_handle(struct bif_slave *slave)
- {
- if (IS_ERR_OR_NULL(slave))
- return ERR_PTR(-EINVAL);
- return &slave->ctrl;
- }
- EXPORT_SYMBOL(bif_get_bus_handle);
- /**
- * bif_ctrl_count() - returns the number of registered BIF controllers
- */
- int bif_ctrl_count(void)
- {
- struct bif_ctrl_dev *bdev;
- int count = 0;
- mutex_lock(&bif_ctrl_list_mutex);
- list_for_each_entry(bdev, &bif_ctrl_list, list) {
- count++;
- }
- mutex_unlock(&bif_ctrl_list_mutex);
- return count;
- }
- EXPORT_SYMBOL(bif_ctrl_count);
- /**
- * bif_ctrl_get_by_id() - get a handle for the id'th BIF controller registered
- * in the system
- * @id: Arbitrary number associated with the BIF bus in the system
- *
- * id must be in the range [0, bif_ctrl_count() - 1]. This function should only
- * need to be called by a BIF consumer that is unable to link to a given BIF
- * controller via a device tree binding.
- *
- * Returns a BIF controller consumer handle if successful or an ERR_PTR if not.
- */
- struct bif_ctrl *bif_ctrl_get_by_id(unsigned int id)
- {
- struct bif_ctrl_dev *bdev;
- struct bif_ctrl_dev *bdev_found = NULL;
- struct bif_ctrl *ctrl = ERR_PTR(-ENODEV);
- mutex_lock(&bif_ctrl_list_mutex);
- list_for_each_entry(bdev, &bif_ctrl_list, list) {
- if (id == 0) {
- bdev_found = bdev;
- break;
- }
- id--;
- }
- mutex_unlock(&bif_ctrl_list_mutex);
- if (bdev_found) {
- ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
- if (!ctrl) {
- pr_err("Bus handle allocation failed\n");
- ctrl = ERR_PTR(-ENOMEM);
- } else {
- ctrl->bdev = bdev_found;
- }
- }
- return ctrl;
- }
- EXPORT_SYMBOL(bif_ctrl_get_by_id);
- /**
- * bif_ctrl_get() - get a handle for the BIF controller that is linked to the
- * consumer device in the device tree
- * @consumer_dev: Pointer to the consumer's device
- *
- * In order to use this function, the BIF consumer's device must specify the
- * "qcom,bif-ctrl" property in its device tree node which points to a BIF
- * controller device node.
- *
- * Returns a BIF controller consumer handle if successful or an ERR_PTR if not.
- * If the BIF controller linked to the consumer device has not yet probed, then
- * ERR_PTR(-EPROBE_DEFER) is returned.
- */
- struct bif_ctrl *bif_ctrl_get(struct device *consumer_dev)
- {
- struct device_node *ctrl_node = NULL;
- struct bif_ctrl_dev *bdev_found = NULL;
- struct bif_ctrl *ctrl = ERR_PTR(-EPROBE_DEFER);
- struct bif_ctrl_dev *bdev = NULL;
- if (!consumer_dev || !consumer_dev->of_node) {
- pr_err("Invalid device node\n");
- return ERR_PTR(-EINVAL);
- }
- ctrl_node = of_parse_phandle(consumer_dev->of_node, "qcom,bif-ctrl", 0);
- if (!ctrl_node) {
- pr_err("Could not find qcom,bif-ctrl property in %s\n",
- consumer_dev->of_node->full_name);
- return ERR_PTR(-ENXIO);
- }
- mutex_lock(&bif_ctrl_list_mutex);
- list_for_each_entry(bdev, &bif_ctrl_list, list) {
- if (bdev->ctrl_dev && bdev->ctrl_dev->of_node == ctrl_node) {
- bdev_found = bdev;
- break;
- }
- }
- mutex_unlock(&bif_ctrl_list_mutex);
- if (bdev_found) {
- ctrl = kzalloc(sizeof(*ctrl), GFP_KERNEL);
- if (!ctrl) {
- pr_err("Bus handle allocation failed\n");
- ctrl = ERR_PTR(-ENOMEM);
- } else {
- ctrl->bdev = bdev_found;
- }
- }
- return ctrl;
- }
- EXPORT_SYMBOL(bif_ctrl_get);
- /**
- * bif_ctrl_put() - frees a BIF controller handle
- * @ctrl: BIF controller consumer handle
- */
- void bif_ctrl_put(struct bif_ctrl *ctrl)
- {
- if (!IS_ERR_OR_NULL(ctrl) && ctrl->exclusive_lock)
- mutex_unlock(&ctrl->bdev->mutex);
- kfree(ctrl);
- }
- EXPORT_SYMBOL(bif_ctrl_put);
- static bool bif_slave_object_match(const struct bif_object *object,
- const struct bif_match_criteria *criteria)
- {
- return (object->type == criteria->obj_type)
- && (object->version == criteria->obj_version
- || !(criteria->match_mask & BIF_MATCH_OBJ_VERSION))
- && (object->manufacturer_id == criteria->obj_manufacturer_id
- || !(criteria->match_mask & BIF_MATCH_OBJ_MANUFACTURER_ID));
- }
- /*
- * Returns true if all parameters are matched, otherwise false.
- * function_type and function_version mean that their exists some function in
- * the slave which has the specified type and subtype. ctrl == NULL is treated
- * as a wildcard.
- */
- static bool bif_slave_match(struct bif_ctrl *ctrl,
- struct bif_slave_dev *sdev, const struct bif_match_criteria *criteria)
- {
- int i, type, version;
- struct bif_object *object;
- bool function_found = false;
- bool object_found = false;
- if (ctrl && (ctrl->bdev != sdev->bdev))
- return false;
- if (!sdev->present
- && (!(criteria->match_mask & BIF_MATCH_IGNORE_PRESENCE)
- || ((criteria->match_mask & BIF_MATCH_IGNORE_PRESENCE)
- && !criteria->ignore_presence)))
- return false;
- if ((criteria->match_mask & BIF_MATCH_MANUFACTURER_ID)
- && sdev->l1_data.manufacturer_id != criteria->manufacturer_id)
- return false;
- if ((criteria->match_mask & BIF_MATCH_PRODUCT_ID)
- && sdev->l1_data.product_id != criteria->product_id)
- return false;
- if (criteria->match_mask & BIF_MATCH_FUNCTION_TYPE) {
- if (!sdev->function_directory)
- return false;
- for (i = 0; i < sdev->l1_data.length / 4; i++) {
- type = sdev->function_directory[i].function_type;
- version = sdev->function_directory[i].function_version;
- if (type == criteria->function_type &&
- (version == criteria->function_version
- || !(criteria->match_mask
- & BIF_MATCH_FUNCTION_VERSION))) {
- function_found = true;
- break;
- }
- }
- if (!function_found)
- return false;
- }
- if (criteria->match_mask & BIF_MATCH_OBJ_TYPE) {
- if (!sdev->nvm_function)
- return false;
- bif_ctrl_lock(ctrl);
- list_for_each_entry(object, &sdev->nvm_function->object_list,
- list) {
- if (bif_slave_object_match(object, criteria)) {
- object_found = true;
- break;
- }
- }
- bif_ctrl_unlock(ctrl);
- if (!object_found)
- return false;
- }
- return true;
- }
- /**
- * bif_slave_match_count() - returns the number of slaves associated with the
- * specified BIF controller which fit the matching
- * criteria
- * @ctrl: BIF controller consumer handle
- * @match_criteria: Matching criteria used to filter slaves
- */
- int bif_slave_match_count(struct bif_ctrl *ctrl,
- const struct bif_match_criteria *match_criteria)
- {
- struct bif_slave_dev *sdev;
- int count = 0;
- mutex_lock(&bif_sdev_list_mutex);
- list_for_each_entry(sdev, &bif_sdev_list, list) {
- if (bif_slave_match(ctrl, sdev, match_criteria))
- count++;
- }
- mutex_unlock(&bif_sdev_list_mutex);
- return count;
- }
- EXPORT_SYMBOL(bif_slave_match_count);
- /**
- * bif_slave_match_get() - get a slave handle for the id'th slave associated
- * with the specified BIF controller which fits the
- * matching criteria
- * @ctrl: BIF controller consumer handle
- * @id: Index into the set of matching slaves
- * @match_criteria: Matching criteria used to filter slaves
- *
- * id must be in the range [0, bif_slave_match_count(ctrl, match_criteria) - 1].
- *
- * Returns a BIF slave handle if successful or an ERR_PTR if not.
- */
- struct bif_slave *bif_slave_match_get(struct bif_ctrl *ctrl,
- unsigned int id, const struct bif_match_criteria *match_criteria)
- {
- struct bif_slave_dev *sdev;
- struct bif_slave *slave = ERR_PTR(-ENODEV);
- struct bif_slave_dev *sdev_found = NULL;
- int count = 0;
- mutex_lock(&bif_sdev_list_mutex);
- list_for_each_entry(sdev, &bif_sdev_list, list) {
- if (bif_slave_match(ctrl, sdev, match_criteria))
- count++;
- if (count == id + 1) {
- sdev_found = sdev;
- break;
- }
- }
- mutex_unlock(&bif_sdev_list_mutex);
- if (sdev_found) {
- slave = kzalloc(sizeof(*slave), GFP_KERNEL);
- if (!slave) {
- pr_err("Slave allocation failed\n");
- slave = ERR_PTR(-ENOMEM);
- } else {
- slave->sdev = sdev_found;
- slave->ctrl.bdev = sdev_found->bdev;
- }
- }
- return slave;
- }
- EXPORT_SYMBOL(bif_slave_match_get);
- /**
- * bif_slave_put() - frees a BIF slave handle
- * @slave: BIF slave handle
- */
- void bif_slave_put(struct bif_slave *slave)
- {
- if (!IS_ERR_OR_NULL(slave) && slave->ctrl.exclusive_lock)
- mutex_unlock(&slave->sdev->bdev->mutex);
- kfree(slave);
- }
- EXPORT_SYMBOL(bif_slave_put);
- /**
- * bif_slave_find_function() - get the function pointer and version of a
- * BIF function if it is present on the specified slave
- * @slave: BIF slave handle
- * @function: BIF function to search for inside of the slave
- * @version: If the function is found, then 'version' is set to the
- * version value of the function
- * @function_pointer: If the function is found, then 'function_pointer' is set
- * to the BIF slave address of the function
- *
- * Returns 0 for success or errno if an error occurred. If the function is not
- * found in the slave, then -ENODEV is returned.
- */
- int bif_slave_find_function(struct bif_slave *slave, u8 function, u8 *version,
- u16 *function_pointer)
- {
- int rc = -ENODEV;
- struct bif_ddb_l2_data *func;
- int i;
- if (IS_ERR_OR_NULL(slave) || IS_ERR_OR_NULL(version)
- || IS_ERR_OR_NULL(function_pointer)) {
- pr_err("Invalid pointer input.\n");
- return -EINVAL;
- }
- func = slave->sdev->function_directory;
- for (i = 0; i < slave->sdev->l1_data.length / 4; i++) {
- if (function == func[i].function_type) {
- *version = func[i].function_version;
- *function_pointer = func[i].function_pointer;
- rc = 0;
- break;
- }
- }
- return rc;
- }
- EXPORT_SYMBOL(bif_slave_find_function);
- static bool bif_object_match(const struct bif_object *object,
- const struct bif_obj_match_criteria *criteria)
- {
- return (object->type == criteria->type
- || !(criteria->match_mask & BIF_OBJ_MATCH_TYPE))
- && (object->version == criteria->version
- || !(criteria->match_mask & BIF_OBJ_MATCH_VERSION))
- && (object->manufacturer_id == criteria->manufacturer_id
- || !(criteria->match_mask & BIF_OBJ_MATCH_MANUFACTURER_ID));
- }
- /**
- * bif_object_match_count() - returns the number of objects associated with the
- * specified BIF slave which fit the matching criteria
- * @slave: BIF slave handle
- * @match_criteria: Matching criteria used to filter objects
- */
- int bif_object_match_count(struct bif_slave *slave,
- const struct bif_obj_match_criteria *match_criteria)
- {
- struct bif_object *object;
- int count = 0;
- if (IS_ERR_OR_NULL(slave) || IS_ERR_OR_NULL(match_criteria)) {
- pr_err("Invalid pointer input.\n");
- return -EINVAL;
- }
- if (!slave->sdev->nvm_function)
- return 0;
- bif_slave_ctrl_lock(slave);
- list_for_each_entry(object, &slave->sdev->nvm_function->object_list,
- list) {
- if (bif_object_match(object, match_criteria))
- count++;
- }
- bif_slave_ctrl_unlock(slave);
- return count;
- }
- EXPORT_SYMBOL(bif_object_match_count);
- /**
- * bif_object_match_get() - get a BIF object handle for the id'th object found
- * in the non-volatile memory of the specified BIF slave
- * which fits the matching criteria
- * @slave: BIF slave handle
- * @id: Index into the set of matching objects
- * @match_criteria: Matching criteria used to filter objects
- *
- * id must be in range [0, bif_object_match_count(slave, match_criteria) - 1].
- *
- * Returns a BIF object handle if successful or an ERR_PTR if not. This handle
- * must be freed using bif_object_put() when it is no longer needed.
- */
- struct bif_object *bif_object_match_get(struct bif_slave *slave,
- unsigned int id, const struct bif_obj_match_criteria *match_criteria)
- {
- struct bif_object *object;
- struct bif_object *object_found = NULL;
- struct bif_object *object_consumer = ERR_PTR(-ENODEV);
- int count = 0;
- if (IS_ERR_OR_NULL(slave) || IS_ERR_OR_NULL(match_criteria)) {
- pr_err("Invalid pointer input.\n");
- return ERR_PTR(-EINVAL);
- }
- if (!slave->sdev->nvm_function)
- return object_consumer;
- bif_slave_ctrl_lock(slave);
- list_for_each_entry(object, &slave->sdev->nvm_function->object_list,
- list) {
- if (bif_object_match(object, match_criteria))
- count++;
- if (count == id + 1) {
- object_found = object;
- break;
- }
- }
- if (object_found) {
- object_consumer = kmemdup(object_found,
- sizeof(*object_consumer), GFP_KERNEL);
- if (!object_consumer) {
- pr_err("out of memory\n");
- object_consumer = ERR_PTR(-ENOMEM);
- goto done;
- }
- object_consumer->data = kmemdup(object_found->data,
- object_found->length - 8, GFP_KERNEL);
- if (!object_consumer->data) {
- pr_err("out of memory\n");
- kfree(object_consumer);
- object_consumer = ERR_PTR(-ENOMEM);
- goto done;
- }
- /*
- * Use prev pointer in consumer struct to point to original
- * struct in the internal linked list.
- */
- object_consumer->list.prev = &object_found->list;
- }
- done:
- bif_slave_ctrl_unlock(slave);
- return object_consumer;
- }
- EXPORT_SYMBOL(bif_object_match_get);
- /**
- * bif_object_put() - frees the memory allocated for a BIF object pointer
- * returned by bif_object_match_get()
- * @object: BIF object to free
- */
- void bif_object_put(struct bif_object *object)
- {
- if (object)
- kfree(object->data);
- kfree(object);
- }
- EXPORT_SYMBOL(bif_object_put);
- /* Copies the contents of object into buf following MIPI-BIF formatting. */
- static void bif_object_flatten(u8 *buf, const struct bif_object *object)
- {
- buf[0] = object->type;
- buf[1] = object->version;
- buf[2] = object->manufacturer_id >> 8;
- buf[3] = object->manufacturer_id;
- buf[4] = object->length >> 8;
- buf[5] = object->length;
- memcpy(&buf[6], object->data, object->length - 8);
- buf[object->length - 2] = object->crc >> 8;
- buf[object->length - 1] = object->crc;
- }
- /**
- * bif_object_write() - writes a new BIF object at the end of the object list in
- * the non-volatile memory of a slave
- * @slave: BIF slave handle
- * @type: Type of the object
- * @version: Version of the object
- * @manufacturer_id: Manufacturer ID number allocated by MIPI
- * @data: Data contained in the object
- * @data_len: Length of the data
- *
- * Returns 0 on success or errno on failure. This function will fail if the NVM
- * lock points to an offset after the BIF object list terminator (0x00).
- */
- int bif_object_write(struct bif_slave *slave, u8 type, u8 version,
- u16 manufacturer_id, const u8 *data, int data_len)
- {
- struct bif_object *object;
- struct bif_object *tail_object;
- struct bif_nvm_function *nvm;
- int rc;
- int add_null = 0;
- u16 offset = 0;
- u8 *buf;
- if (IS_ERR_OR_NULL(slave) || IS_ERR_OR_NULL(data)) {
- pr_err("Invalid input pointer\n");
- return -EINVAL;
- }
- nvm = slave->sdev->nvm_function;
- if (!nvm) {
- pr_err("BIF slave has no NVM function\n");
- return -ENODEV;
- }
- bif_slave_ctrl_lock(slave);
- if (nvm->object_count > 0) {
- tail_object = list_entry(nvm->object_list.prev,
- struct bif_object, list);
- offset = tail_object->addr - nvm->nvm_base_address
- + tail_object->length;
- }
- if (offset < nvm->nvm_lock_offset) {
- pr_err("Cannot write BIF object to NVM because the end of the object list is locked (end=%d < lock=%d)\n",
- offset, nvm->nvm_lock_offset);
- rc = -EPERM;
- goto error_unlock;
- } else if (offset + data_len + 8 > nvm->nvm_size) {
- pr_err("Cannot write BIF object to NVM because there is not enough remaining space (size=%d > remaining=%d)\n",
- data_len + 8, nvm->nvm_size - offset);
- rc = -EINVAL;
- goto error_unlock;
- }
- if (offset + data_len + 8 < nvm->nvm_size)
- add_null = 1;
- object = kzalloc(sizeof(*object), GFP_KERNEL);
- if (!object) {
- pr_err("kzalloc failed\n");
- rc = -ENOMEM;
- goto error_unlock;
- }
- object->data = kzalloc(data_len, GFP_KERNEL);
- if (!object->data) {
- pr_err("kzalloc failed\n");
- rc = -ENOMEM;
- goto free_object;
- }
- buf = kzalloc(data_len + 8 + add_null, GFP_KERNEL);
- if (!buf) {
- pr_err("kzalloc failed\n");
- rc = -ENOMEM;
- goto free_data;
- }
- object->type = type;
- object->version = version;
- object->manufacturer_id = manufacturer_id;
- object->length = data_len + 8;
- memcpy(object->data, data, data_len);
- object->crc = bif_object_crc_ccitt(object);
- object->addr = offset + nvm->nvm_base_address;
- bif_object_flatten(buf, object);
- if (add_null)
- buf[object->length] = BIF_OBJ_END_OF_LIST;
- rc = _bif_slave_nvm_raw_write(slave->sdev, offset, buf,
- object->length + add_null);
- if (rc < 0) {
- pr_err("NVM write failed, rc=%d\n", rc);
- kfree(buf);
- goto free_data;
- }
- kfree(buf);
- list_add_tail(&object->list, &nvm->object_list);
- nvm->object_count++;
- bif_slave_ctrl_unlock(slave);
- return rc;
- free_data:
- kfree(object->data);
- free_object:
- kfree(object);
- error_unlock:
- bif_slave_ctrl_unlock(slave);
- return rc;
- }
- EXPORT_SYMBOL(bif_object_write);
- /*
- * Returns a pointer to the internal object referenced by a consumer object
- * if it exists. Returns NULL if the internal object cannot be found.
- */
- static struct bif_object *bif_object_consumer_search(
- struct bif_nvm_function *nvm, const struct bif_object *consumer_object)
- {
- struct bif_object *object = NULL;
- struct bif_object *search_object;
- /*
- * Internal struct in object linked list is pointed to by consumer
- * object list.prev.
- */
- search_object = list_entry(consumer_object->list.prev,
- struct bif_object, list);
- list_for_each_entry(object, &nvm->object_list, list) {
- if (object == search_object)
- break;
- }
- if (object != search_object)
- return NULL;
- return object;
- }
- /**
- * bif_object_overwrite() - overwrites an existing BIF object found in the
- * non-volatile memory of a slave
- * @slave: BIF slave handle
- * @object: Existing object in the slave to overwrite
- * @type: Type of the object
- * @version: Version of the object
- * @manufacturer_id: Manufacturer ID number allocated by MIPI
- * @data: Data contained in the object
- * @data_len: Length of the data
- *
- * Returns 0 on success or errno on failure. The data stored within 'object'
- * is updated to the new values upon success. The new data written to the
- * object must have exactly the same length as the old data (i.e.
- * data_len == object->length - 8).
- *
- * This function will fail if the NVM lock points to an offset after the
- * beginning of the existing BIF object.
- */
- int bif_object_overwrite(struct bif_slave *slave,
- struct bif_object *object, u8 type, u8 version,
- u16 manufacturer_id, const u8 *data, int data_len)
- {
- struct bif_object *edit_object = NULL;
- struct bif_nvm_function *nvm;
- int rc;
- u16 crc;
- u8 *buf;
- if (IS_ERR_OR_NULL(slave) || IS_ERR_OR_NULL(object)
- || IS_ERR_OR_NULL(data)) {
- pr_err("Invalid input pointer\n");
- return -EINVAL;
- }
- nvm = slave->sdev->nvm_function;
- if (!nvm) {
- pr_err("BIF slave has no NVM function\n");
- return -ENODEV;
- }
- if (data_len + 8 != object->length) {
- pr_err("New data length=%d is different from existing length=%d\n",
- data_len, object->length - 8);
- return -EINVAL;
- }
- bif_slave_ctrl_lock(slave);
- edit_object = bif_object_consumer_search(nvm, object);
- if (!edit_object) {
- pr_err("BIF object not found within slave\n");
- rc = -EINVAL;
- goto error_unlock;
- }
- if (edit_object->addr - nvm->nvm_base_address < nvm->nvm_lock_offset) {
- pr_err("Cannot overwrite BIF object in NVM because some portion of it is locked\n");
- rc = -EPERM;
- goto error_unlock;
- }
- buf = kzalloc(data_len + 8, GFP_KERNEL);
- if (!buf) {
- pr_err("kzalloc failed\n");
- rc = -ENOMEM;
- goto error_unlock;
- }
- buf[0] = type;
- buf[1] = version;
- buf[2] = manufacturer_id >> 8;
- buf[3] = manufacturer_id;
- buf[4] = (data_len + 8) >> 8;
- buf[5] = data_len + 8;
- memcpy(&buf[6], data, data_len);
- crc = bif_crc_ccitt(buf, data_len + 6);
- buf[data_len + 6] = crc >> 8;
- buf[data_len + 7] = crc;
- rc = _bif_slave_nvm_raw_write(slave->sdev,
- object->addr - nvm->nvm_base_address, buf, data_len + 8);
- if (rc < 0) {
- pr_err("NVM write failed, rc=%d\n", rc);
- kfree(buf);
- goto error_unlock;
- }
- kfree(buf);
- /* Update internal object struct. */
- edit_object->type = type;
- edit_object->version = version;
- edit_object->manufacturer_id = manufacturer_id;
- edit_object->length = data_len + 8;
- memcpy(edit_object->data, data, data_len);
- edit_object->crc = crc;
- /* Update consumer object struct. */
- object->type = type;
- object->version = version;
- object->manufacturer_id = manufacturer_id;
- object->length = data_len + 8;
- memcpy(object->data, data, data_len);
- object->crc = crc;
- error_unlock:
- bif_slave_ctrl_unlock(slave);
- return rc;
- }
- EXPORT_SYMBOL(bif_object_overwrite);
- /**
- * bif_object_delete() - deletes an existing BIF object found in the
- * non-volatile memory of a slave. Objects found in the
- * object list in the NVM of the slave are shifted forward
- * in order to fill the hole left by the deleted object
- * @slave: BIF slave handle
- * @object: Existing object in the slave to delete
- *
- * Returns 0 on success or errno on failure. bif_object_put() must still be
- * called after this function in order to free the memory in the consumer
- * 'object' struct pointer.
- *
- * This function will fail if the NVM lock points to an offset after the
- * beginning of the existing BIF object.
- */
- int bif_object_delete(struct bif_slave *slave, const struct bif_object *object)
- {
- struct bif_object *del_object = NULL;
- struct bif_object *tail_object;
- struct bif_nvm_function *nvm;
- bool found = false;
- int pos = 0;
- int rc;
- u8 *buf;
- if (IS_ERR_OR_NULL(slave) || IS_ERR_OR_NULL(object)) {
- pr_err("Invalid input pointer\n");
- return -EINVAL;
- }
- nvm = slave->sdev->nvm_function;
- if (!nvm) {
- pr_err("BIF slave has no NVM function\n");
- return -ENODEV;
- }
- bif_slave_ctrl_lock(slave);
- del_object = bif_object_consumer_search(nvm, object);
- if (!del_object) {
- pr_err("BIF object not found within slave\n");
- rc = -EINVAL;
- goto error_unlock;
- }
- if (del_object->addr - nvm->nvm_base_address < nvm->nvm_lock_offset) {
- pr_err("Cannot delete BIF object in NVM because some portion of it is locked\n");
- rc = -EPERM;
- goto error_unlock;
- }
- buf = kmalloc(nvm->nvm_size, GFP_KERNEL);
- if (!buf) {
- pr_err("kzalloc failed\n");
- rc = -ENOMEM;
- goto error_unlock;
- }
- /*
- * Copy the contents of objects after the one to be deleted into a flat
- * array.
- */
- list_for_each_entry(tail_object, &nvm->object_list, list) {
- if (found) {
- bif_object_flatten(&buf[pos], tail_object);
- pos += tail_object->length;
- } else if (tail_object == del_object) {
- found = true;
- }
- }
- /* Add the list terminator. */
- buf[pos++] = BIF_OBJ_END_OF_LIST;
- rc = _bif_slave_nvm_raw_write(slave->sdev,
- del_object->addr - nvm->nvm_base_address, buf, pos);
- if (rc < 0) {
- pr_err("NVM write failed, rc=%d\n", rc);
- kfree(buf);
- goto error_unlock;
- }
- kfree(buf);
- /* Update the addresses of the objects after the one to be deleted. */
- found = false;
- list_for_each_entry(tail_object, &nvm->object_list, list) {
- if (found)
- tail_object->addr -= del_object->length;
- else if (tail_object == del_object)
- found = true;
- }
- list_del(&del_object->list);
- kfree(del_object->data);
- kfree(del_object);
- nvm->object_count--;
- error_unlock:
- bif_slave_ctrl_unlock(slave);
- return rc;
- }
- EXPORT_SYMBOL(bif_object_delete);
- /**
- * bif_slave_read() - read contiguous memory values from a BIF slave
- * @slave: BIF slave handle
- * @addr: BIF slave address to begin reading at
- * @buf: Buffer to fill with memory values
- * @len: Number of byte to read
- *
- * Returns 0 for success or errno if an error occurred.
- */
- int bif_slave_read(struct bif_slave *slave, u16 addr, u8 *buf, int len)
- {
- int rc;
- if (IS_ERR_OR_NULL(slave) || IS_ERR_OR_NULL(buf)) {
- pr_err("Invalid pointer input.\n");
- return -EINVAL;
- }
- bif_slave_ctrl_lock(slave);
- rc = _bif_slave_read(slave->sdev, addr, buf, len);
- if (rc)
- pr_err("BIF slave read failed, rc=%d\n", rc);
- bif_slave_ctrl_unlock(slave);
- return rc;
- }
- EXPORT_SYMBOL(bif_slave_read);
- /**
- * bif_slave_write() - write contiguous memory values to a BIF slave
- * @slave: BIF slave handle
- * @addr: BIF slave address to begin writing at
- * @buf: Buffer containing values to write
- * @len: Number of byte to write
- *
- * Returns 0 for success or errno if an error occurred.
- */
- int bif_slave_write(struct bif_slave *slave, u16 addr, u8 *buf, int len)
- {
- int rc;
- if (IS_ERR_OR_NULL(slave) || IS_ERR_OR_NULL(buf)) {
- pr_err("Invalid pointer input.\n");
- return -EINVAL;
- }
- bif_slave_ctrl_lock(slave);
- rc = _bif_slave_write(slave->sdev, addr, buf, len);
- if (rc)
- pr_err("BIF slave write failed, rc=%d\n", rc);
- bif_slave_ctrl_unlock(slave);
- return rc;
- }
- EXPORT_SYMBOL(bif_slave_write);
- /**
- * bif_slave_nvm_raw_read() - read contiguous memory values from a BIF slave's
- * non-volatile memory (NVM)
- * @slave: BIF slave handle
- * @offset: Offset from the beginning of BIF slave NVM to begin reading at
- * @buf: Buffer to fill with memory values
- * @len: Number of byte to read
- *
- * Returns 0 for success or errno if an error occurred.
- */
- int bif_slave_nvm_raw_read(struct bif_slave *slave, u16 offset, u8 *buf,
- int len)
- {
- if (IS_ERR_OR_NULL(slave)) {
- pr_err("Invalid slave pointer=%ld\n", PTR_ERR(slave));
- return -EINVAL;
- } else if (IS_ERR_OR_NULL(buf)) {
- pr_err("Invalid buffer pointer=%ld\n", PTR_ERR(buf));
- return -EINVAL;
- } else if (!slave->sdev->nvm_function) {
- pr_err("BIF slave has no NVM function\n");
- return -ENODEV;
- } else if (offset + len > slave->sdev->nvm_function->nvm_size) {
- pr_err("read offset + len = %d > NVM size = %d\n",
- offset + len, slave->sdev->nvm_function->nvm_size);
- return -EINVAL;
- }
- return bif_slave_read(slave,
- slave->sdev->nvm_function->nvm_base_address + offset, buf, len);
- }
- EXPORT_SYMBOL(bif_slave_nvm_raw_read);
- /**
- * bif_slave_nvm_raw_write() - write contiguous memory values to a BIF slave's
- * non-volatile memory (NVM)
- * @slave: BIF slave handle
- * @offset: Offset from the beginning of BIF slave NVM to begin writing at
- * @buf: Buffer containing values to write
- * @len: Number of byte to write
- *
- * Note that this function does *not* respect the MIPI-BIF object data
- * formatting specification. It can cause corruption of the object data list
- * stored in NVM if used improperly.
- *
- * Returns 0 for success or errno if an error occurred.
- */
- int bif_slave_nvm_raw_write(struct bif_slave *slave, u16 offset, u8 *buf,
- int len)
- {
- int rc;
- if (IS_ERR_OR_NULL(slave)) {
- pr_err("Invalid slave pointer=%ld\n", PTR_ERR(slave));
- return -EINVAL;
- } else if (IS_ERR_OR_NULL(buf)) {
- pr_err("Invalid buffer pointer=%ld\n", PTR_ERR(buf));
- return -EINVAL;
- }
- bif_slave_ctrl_lock(slave);
- rc = _bif_slave_nvm_raw_write(slave->sdev, offset, buf, len);
- bif_slave_ctrl_unlock(slave);
- return rc;
- }
- EXPORT_SYMBOL(bif_slave_nvm_raw_write);
- /**
- * bif_slave_is_present() - check if a slave is currently physically present
- * in the system
- * @slave: BIF slave handle
- *
- * Returns 1 if the slave is present, 0 if the slave is not present, or errno
- * if an error occurred.
- *
- * This function can be used by BIF consumer drivers to check if their slave
- * handles are still meaningful after battery reinsertion.
- */
- int bif_slave_is_present(struct bif_slave *slave)
- {
- if (IS_ERR_OR_NULL(slave)) {
- pr_err("Invalid pointer input.\n");
- return -EINVAL;
- }
- return slave->sdev->present;
- }
- EXPORT_SYMBOL(bif_slave_is_present);
- /**
- * bif_slave_is_selected() - check if a slave is currently selected on the BIF
- * bus
- * @slave: BIF slave handle
- *
- * Returns 1 if the slave is selected, 0 if the slave is not selected, or errno
- * if an error occurred.
- *
- * This function should not be required under normal circumstances since the
- * bif-core framework ensures that slaves are always selected when needed.
- * It would be most useful when used as a helper in conjunction with
- * bif_ctrl_bus_lock() and the raw transaction functions.
- */
- int bif_slave_is_selected(struct bif_slave *slave)
- {
- int rc;
- if (IS_ERR_OR_NULL(slave)) {
- pr_err("Invalid pointer input.\n");
- return -EINVAL;
- }
- if (slave->sdev->bdev->selected_sdev != slave->sdev)
- return false;
- bif_slave_ctrl_lock(slave);
- rc = bif_is_slave_selected(slave->sdev->bdev);
- bif_slave_ctrl_unlock(slave);
- return rc;
- }
- EXPORT_SYMBOL(bif_slave_is_selected);
- /**
- * bif_slave_select() - select a slave on the BIF bus
- * @slave: BIF slave handle
- *
- * Returns 0 on success or errno if an error occurred.
- *
- * This function should not be required under normal circumstances since the
- * bif-core framework ensures that slaves are always selected when needed.
- * It would be most useful when used as a helper in conjunction with
- * bif_ctrl_bus_lock() and the raw transaction functions.
- */
- int bif_slave_select(struct bif_slave *slave)
- {
- int rc;
- if (IS_ERR_OR_NULL(slave)) {
- pr_err("Invalid pointer input.\n");
- return -EINVAL;
- }
- bif_slave_ctrl_lock(slave);
- slave->sdev->bdev->selected_sdev = NULL;
- rc = bif_select_slave(slave->sdev);
- bif_slave_ctrl_unlock(slave);
- return rc;
- }
- EXPORT_SYMBOL(bif_slave_select);
- /**
- * bif_ctrl_raw_transaction() - perform a raw BIF transaction on the bus which
- * expects no slave response
- * @ctrl: BIF controller consumer handle
- * @transaction: BIF transaction to carry out. This should be one of the
- * values in enum bif_transaction.
- * @data: 8-bit data to use in the transaction. The meaning of
- * this data depends upon the transaction that is to be
- * performed.
- *
- * When performing a bus command (BC) transaction, values in enum
- * bif_bus_command may be used for the data parameter. Additional manufacturer
- * specific values may also be used in a BC transaction.
- *
- * Returns 0 on success or errno if an error occurred.
- *
- * This function should only need to be used when BIF transactions are required
- * that are not handled by the bif-core directly.
- */
- int bif_ctrl_raw_transaction(struct bif_ctrl *ctrl, int transaction, u8 data)
- {
- int rc;
- if (IS_ERR_OR_NULL(ctrl)) {
- pr_err("Invalid pointer input.\n");
- return -EINVAL;
- }
- bif_ctrl_lock(ctrl);
- rc = ctrl->bdev->desc->ops->bus_transaction(ctrl->bdev, transaction,
- data);
- if (rc)
- pr_err("BIF bus transaction failed, rc=%d\n", rc);
- bif_ctrl_unlock(ctrl);
- return rc;
- }
- EXPORT_SYMBOL(bif_ctrl_raw_transaction);
- /**
- * bif_ctrl_raw_transaction_read() - perform a raw BIF transaction on the bus
- * which expects an RD or TACK slave response word
- * @ctrl: BIF controller consumer handle
- * @transaction: BIF transaction to carry out. This should be one of the
- * values in enum bif_transaction.
- * @data: 8-bit data to use in the transaction. The meaning of
- * this data depends upon the transaction that is to be
- * performed.
- * @response: Pointer to an integer which is filled with the 11-bit
- * slave response word upon success. The 11-bit format is
- * (MSB to LSB) BCF, ACK, EOT, D7-D0.
- *
- * When performing a bus command (BC) transaction, values in enum
- * bif_bus_command may be used for the data parameter. Additional manufacturer
- * specific values may also be used in a BC transaction.
- *
- * Returns 0 on success or errno if an error occurred.
- *
- * This function should only need to be used when BIF transactions are required
- * that are not handled by the bif-core directly.
- */
- int bif_ctrl_raw_transaction_read(struct bif_ctrl *ctrl, int transaction,
- u8 data, int *response)
- {
- int rc;
- if (IS_ERR_OR_NULL(ctrl) || IS_ERR_OR_NULL(response)) {
- pr_err("Invalid pointer input.\n");
- return -EINVAL;
- }
- bif_ctrl_lock(ctrl);
- rc = ctrl->bdev->desc->ops->bus_transaction_read(ctrl->bdev,
- transaction, data, response);
- if (rc)
- pr_err("BIF bus transaction failed, rc=%d\n", rc);
- bif_ctrl_unlock(ctrl);
- return rc;
- }
- EXPORT_SYMBOL(bif_ctrl_raw_transaction_read);
- /**
- * bif_ctrl_raw_transaction_query() - perform a raw BIF transaction on the bus
- * which expects a BQ slave response
- * @ctrl: BIF controller consumer handle
- * @transaction: BIF transaction to carry out. This should be one of the
- * values in enum bif_transaction.
- * @data: 8-bit data to use in the transaction. The meaning of
- * this data depends upon the transaction that is to be
- * performed.
- * @query_response: Pointer to boolean which is set to true if a BQ pulse
- * is receieved, or false if no BQ pulse is received before
- * timing out.
- *
- * When performing a bus command (BC) transaction, values in enum
- * bif_bus_command may be used for the data parameter. Additional manufacturer
- * specific values may also be used in a BC transaction.
- *
- * Returns 0 on success or errno if an error occurred.
- *
- * This function should only need to be used when BIF transactions are required
- * that are not handled by the bif-core directly.
- */
- int bif_ctrl_raw_transaction_query(struct bif_ctrl *ctrl, int transaction,
- u8 data, bool *query_response)
- {
- int rc;
- if (IS_ERR_OR_NULL(ctrl) || IS_ERR_OR_NULL(query_response)) {
- pr_err("Invalid pointer input.\n");
- return -EINVAL;
- }
- bif_ctrl_lock(ctrl);
- rc = ctrl->bdev->desc->ops->bus_transaction_query(ctrl->bdev,
- transaction, data, query_response);
- if (rc)
- pr_err("BIF bus transaction failed, rc=%d\n", rc);
- bif_ctrl_unlock(ctrl);
- return rc;
- }
- EXPORT_SYMBOL(bif_ctrl_raw_transaction_query);
- /**
- * bif_ctrl_bus_lock() - lock the BIF bus of a controller for exclusive access
- * @ctrl: BIF controller consumer handle
- *
- * This function should only need to be called in circumstances where a BIF
- * consumer is issuing special BIF bus commands that have strict ordering
- * requirements.
- */
- void bif_ctrl_bus_lock(struct bif_ctrl *ctrl)
- {
- if (IS_ERR_OR_NULL(ctrl)) {
- pr_err("Invalid controller handle.\n");
- return;
- }
- if (ctrl->exclusive_lock) {
- pr_err("BIF bus exclusive lock already held\n");
- return;
- }
- mutex_lock(&ctrl->bdev->mutex);
- ctrl->exclusive_lock = true;
- bif_cancel_irq_mode_work(ctrl->bdev);
- }
- EXPORT_SYMBOL(bif_ctrl_bus_lock);
- /**
- * bif_ctrl_bus_unlock() - lock the BIF bus of a controller that was previously
- * locked for exclusive access
- * @ctrl: BIF controller consumer handle
- *
- * This function must only be called after first calling bif_ctrl_bus_lock().
- */
- void bif_ctrl_bus_unlock(struct bif_ctrl *ctrl)
- {
- if (IS_ERR_OR_NULL(ctrl)) {
- pr_err("Invalid controller handle.\n");
- return;
- }
- if (!ctrl->exclusive_lock) {
- pr_err("BIF bus exclusive lock not already held\n");
- return;
- }
- ctrl->exclusive_lock = false;
- bif_schedule_irq_mode_work(ctrl->bdev);
- mutex_unlock(&ctrl->bdev->mutex);
- }
- EXPORT_SYMBOL(bif_ctrl_bus_unlock);
- /**
- * bif_ctrl_measure_rid() - measure the battery pack Rid pull-down resistance
- * in ohms
- * @ctrl: BIF controller consumer handle
- *
- * Returns the resistance of the Rid resistor in ohms if successful or errno
- * if an error occurred.
- */
- int bif_ctrl_measure_rid(struct bif_ctrl *ctrl)
- {
- int rc;
- if (IS_ERR_OR_NULL(ctrl)) {
- pr_err("Invalid controller handle.\n");
- return -ENODEV;
- }
- if (!ctrl->bdev->desc->ops->get_battery_rid) {
- pr_err("Cannot measure Rid.\n");
- return -ENXIO;
- }
- bif_ctrl_lock(ctrl);
- rc = ctrl->bdev->desc->ops->get_battery_rid(ctrl->bdev);
- if (rc < 0)
- pr_err("Error during Rid measurement, rc=%d\n", rc);
- bif_ctrl_unlock(ctrl);
- return rc;
- }
- EXPORT_SYMBOL(bif_ctrl_measure_rid);
- /**
- * bif_ctrl_get_bus_period() - get the BIF bus period (tau_bif) in nanoseconds
- * @ctrl: BIF controller consumer handle
- *
- * Returns the currently configured bus period in nanoseconds if successful or
- * errno if an error occurred.
- */
- int bif_ctrl_get_bus_period(struct bif_ctrl *ctrl)
- {
- int rc;
- if (IS_ERR_OR_NULL(ctrl)) {
- pr_err("Invalid controller handle.\n");
- return -ENODEV;
- }
- if (!ctrl->bdev->desc->ops->get_bus_period) {
- pr_err("Cannot get the BIF bus period.\n");
- return -ENXIO;
- }
- rc = ctrl->bdev->desc->ops->get_bus_period(ctrl->bdev);
- if (rc < 0)
- pr_err("Error during bus period retrieval, rc=%d\n", rc);
- return rc;
- }
- EXPORT_SYMBOL(bif_ctrl_get_bus_period);
- /**
- * bif_ctrl_set_bus_period() - set the BIF bus period (tau_bif) in nanoseconds
- * @ctrl: BIF controller consumer handle
- * @period_ns: BIF bus period in nanoseconds to use
- *
- * If the exact period is not supported by the BIF controller hardware, then the
- * next larger supported period will be used.
- *
- * Returns 0 on success or errno if an error occurred.
- */
- int bif_ctrl_set_bus_period(struct bif_ctrl *ctrl, int period_ns)
- {
- int rc;
- if (IS_ERR_OR_NULL(ctrl)) {
- pr_err("Invalid controller handle.\n");
- return -ENODEV;
- }
- if (!ctrl->bdev->desc->ops->set_bus_period) {
- pr_err("Cannot set the BIF bus period.\n");
- return -ENXIO;
- }
- bif_ctrl_lock(ctrl);
- rc = ctrl->bdev->desc->ops->set_bus_period(ctrl->bdev, period_ns);
- if (rc)
- pr_err("Error during bus period configuration, rc=%d\n", rc);
- bif_ctrl_unlock(ctrl);
- return rc;
- }
- EXPORT_SYMBOL(bif_ctrl_set_bus_period);
- /**
- * bif_ctrl_get_bus_state() - get the current state of the BIF bus
- * @ctrl: BIF controller consumer handle
- *
- * Returns a bus state from enum bif_bus_state if successful or errno if an
- * error occurred.
- */
- int bif_ctrl_get_bus_state(struct bif_ctrl *ctrl)
- {
- int rc;
- if (IS_ERR_OR_NULL(ctrl)) {
- pr_err("Invalid controller handle.\n");
- return -ENODEV;
- }
- rc = ctrl->bdev->desc->ops->get_bus_state(ctrl->bdev);
- if (rc < 0)
- pr_err("Error during bus state retrieval, rc=%d\n", rc);
- return rc;
- }
- EXPORT_SYMBOL(bif_ctrl_get_bus_state);
- /**
- * bif_ctrl_set_bus_state() - set the state of the BIF bus
- * @ctrl: BIF controller consumer handle
- * @state: State for the BIF bus to enter
- *
- * Returns 0 on success or errno if an error occurred.
- */
- int bif_ctrl_set_bus_state(struct bif_ctrl *ctrl, enum bif_bus_state state)
- {
- int rc;
- if (IS_ERR_OR_NULL(ctrl)) {
- pr_err("Invalid controller handle.\n");
- return -ENODEV;
- }
- bif_ctrl_lock(ctrl);
- rc = ctrl->bdev->desc->ops->set_bus_state(ctrl->bdev, state);
- if (rc < 0)
- pr_err("Error during bus state configuration, rc=%d\n", rc);
- /*
- * Uncache the selected slave if the new bus state results in the slave
- * becoming unselected.
- */
- if (state == BIF_BUS_STATE_MASTER_DISABLED
- || state == BIF_BUS_STATE_POWER_DOWN
- || state == BIF_BUS_STATE_STANDBY)
- ctrl->bdev->selected_sdev = NULL;
- bif_ctrl_unlock(ctrl);
- return rc;
- }
- EXPORT_SYMBOL(bif_ctrl_set_bus_state);
- /*
- * Check if the specified function is a protocol function and if it is, then
- * instantiate protocol function data for the slave.
- */
- static int bif_initialize_protocol_function(struct bif_slave_dev *sdev,
- struct bif_ddb_l2_data *func)
- {
- int rc = 0;
- u8 buf[4];
- /* Ensure that this is a protocol function. */
- if (func->function_type != BIF_FUNC_PROTOCOL)
- return 0;
- if (sdev->protocol_function) {
- pr_err("Duplicate protocol function found for BIF slave; DEV_ADR=0x%02X\n",
- sdev->slave_addr);
- return -EPERM;
- }
- sdev->protocol_function = kzalloc(sizeof(struct bif_protocol_function),
- GFP_KERNEL);
- if (!sdev->protocol_function) {
- pr_err("out of memory\n");
- return -ENOMEM;
- }
- rc = _bif_slave_read(sdev, func->function_pointer, buf, 4);
- if (rc) {
- pr_err("Protocol function data read failed, rc=%d\n", rc);
- return rc;
- }
- sdev->protocol_function->protocol_pointer = buf[0] << 8 | buf[1];
- sdev->protocol_function->device_id_pointer = buf[2] << 8 | buf[3];
- sdev->protocol_function->l2_entry = func;
- rc = _bif_slave_read(sdev, sdev->protocol_function->device_id_pointer,
- sdev->protocol_function->device_id, BIF_DEVICE_ID_BYTE_LENGTH);
- if (rc) {
- pr_err("Device ID read failed, rc=%d\n", rc);
- return rc;
- }
- /* Check if this slave does not have a UID value stored. */
- if (sdev->unique_id_bits_known == 0) {
- sdev->unique_id_bits_known = BIF_UNIQUE_ID_BIT_LENGTH;
- /* Fill in UID using manufacturer ID and device ID. */
- sdev->unique_id[0] = sdev->l1_data.manufacturer_id >> 8;
- sdev->unique_id[1] = sdev->l1_data.manufacturer_id;
- memcpy(&sdev->unique_id[2],
- sdev->protocol_function->device_id,
- BIF_DEVICE_ID_BYTE_LENGTH);
- }
- return rc;
- }
- /*
- * Check if the specified function is a slave control function and if it is,
- * then instantiate slave control function data for the slave.
- */
- static int bif_initialize_slave_control_function(struct bif_slave_dev *sdev,
- struct bif_ddb_l2_data *func)
- {
- int rc = 0;
- int i;
- u8 buf[3];
- /* Ensure that this is a slave control function. */
- if (func->function_type != BIF_FUNC_SLAVE_CONTROL)
- return 0;
- if (sdev->slave_ctrl_function) {
- pr_err("Duplicate slave control function found for BIF slave; DEV_ADR=0x%02X\n",
- sdev->slave_addr);
- return -EPERM;
- }
- sdev->slave_ctrl_function
- = kzalloc(sizeof(struct bif_protocol_function), GFP_KERNEL);
- if (!sdev->slave_ctrl_function) {
- pr_err("out of memory\n");
- return -ENOMEM;
- }
- rc = _bif_slave_read(sdev, func->function_pointer, buf, 3);
- if (rc) {
- pr_err("Slave control function data read failed, rc=%d\n", rc);
- return rc;
- }
- sdev->slave_ctrl_function->slave_ctrl_pointer = buf[0] << 8 | buf[1];
- sdev->slave_ctrl_function->task_count
- = buf[2] * SLAVE_CTRL_TASKS_PER_SET;
- sdev->slave_ctrl_function->l2_entry = func;
- if (sdev->slave_ctrl_function->task_count > 0) {
- sdev->slave_ctrl_function->irq_notifier_list =
- kzalloc(sizeof(struct blocking_notifier_head)
- * sdev->slave_ctrl_function->task_count,
- GFP_KERNEL);
- if (!sdev->slave_ctrl_function->irq_notifier_list) {
- pr_err("out of memory\n");
- kfree(sdev->slave_ctrl_function);
- return -ENOMEM;
- }
- for (i = 0; i < sdev->slave_ctrl_function->task_count; i++) {
- BLOCKING_INIT_NOTIFIER_HEAD(
- &sdev->slave_ctrl_function->irq_notifier_list[i]);
- }
- }
- return rc;
- }
- /*
- * Check if the specified function is an NVM function and if it is, then
- * instantiate NVM function data for the slave and read all objects.
- */
- static int bif_initialize_nvm_function(struct bif_slave_dev *sdev,
- struct bif_ddb_l2_data *func)
- {
- int rc = 0;
- int data_len, read_size;
- u8 buf[8], object_type;
- struct bif_object *object;
- struct bif_object *temp;
- u16 addr;
- u16 crc;
- /* Ensure that this is an NVM function. */
- if (func->function_type != BIF_FUNC_NVM)
- return 0;
- if (sdev->nvm_function) {
- pr_err("Duplicate NVM function found for BIF slave; DEV_ADR=0x%02X\n",
- sdev->slave_addr);
- return -EPERM;
- }
- sdev->nvm_function
- = kzalloc(sizeof(*sdev->nvm_function), GFP_KERNEL);
- if (!sdev->nvm_function) {
- pr_err("out of memory\n");
- return -ENOMEM;
- }
- rc = _bif_slave_read(sdev, func->function_pointer, buf, 8);
- if (rc) {
- pr_err("NVM function data read failed, rc=%d\n", rc);
- return rc;
- }
- sdev->nvm_function->nvm_pointer = buf[0] << 8 | buf[1];
- sdev->nvm_function->slave_control_channel = buf[2];
- sdev->nvm_function->write_buffer_size = buf[3];
- sdev->nvm_function->nvm_base_address = buf[4] << 8 | buf[5];
- sdev->nvm_function->nvm_size = buf[6] << 8 | buf[7];
- /* Read NVM lock offset */
- rc = _bif_slave_read(sdev, sdev->nvm_function->nvm_pointer, buf, 2);
- if (rc) {
- pr_err("Slave memory read failed, rc=%d\n", rc);
- return rc;
- }
- sdev->nvm_function->nvm_lock_offset = buf[0] << 8 | buf[1];
- INIT_LIST_HEAD(&sdev->nvm_function->object_list);
- /* Read object list */
- addr = sdev->nvm_function->nvm_base_address;
- rc = _bif_slave_read(sdev, addr, &object_type, 1);
- if (rc) {
- pr_err("Slave memory read failed, rc=%d\n", rc);
- return rc;
- }
- while (object_type != BIF_OBJ_END_OF_LIST) {
- object = kzalloc(sizeof(*object), GFP_KERNEL);
- if (!object) {
- pr_err("out of memory\n");
- rc = -ENOMEM;
- goto free_data;
- }
- list_add_tail(&object->list, &sdev->nvm_function->object_list);
- rc = _bif_slave_read(sdev, addr + 1, buf + 1, 5);
- if (rc) {
- pr_err("Slave memory read of object header failed; addr=0x%04X, len=%d, rc=%d\n",
- addr + 1, 5, rc);
- goto free_data;
- }
- object->addr = addr;
- object->type = object_type;
- object->version = buf[1];
- object->manufacturer_id = buf[2] << 8 | buf[3];
- object->length = buf[4] << 8 | buf[5];
- if ((object->addr + object->length)
- > (sdev->nvm_function->nvm_base_address
- + sdev->nvm_function->nvm_size)) {
- pr_warn("warning: BIF slave object is not formatted correctly; NVM base=0x%04X, NVM len=%d, object addr=0x%04X, object len=%d\n",
- sdev->nvm_function->nvm_base_address,
- sdev->nvm_function->nvm_size,
- object->addr,
- object->length);
- /* Limit object size to remaining NVM size. */
- object->length = sdev->nvm_function->nvm_size
- + sdev->nvm_function->nvm_base_address
- - object->addr;
- }
- /* Object header + CRC takes up 8 bytes. */
- data_len = object->length - 8;
- object->data = kmalloc(data_len, GFP_KERNEL);
- if (!object->data) {
- pr_err("out of memory\n");
- rc = -ENOMEM;
- goto free_data;
- }
- rc = _bif_slave_read(sdev, addr + 6, object->data, data_len);
- if (rc) {
- pr_err("Slave memory read of object data failed; addr=0x%04X, len=%d, rc=%d\n",
- addr + 6, data_len, rc);
- goto free_data;
- }
- if ((object->length + addr) >= (sdev->nvm_function->nvm_size
- + sdev->nvm_function->nvm_base_address))
- read_size = 2;
- else
- read_size = 3;
- rc = _bif_slave_read(sdev, addr + 6 + data_len, buf, read_size);
- if (rc) {
- pr_err("Slave memory read of object CRC failed; addr=0x%04X, len=%d, rc=%d\n",
- addr + 6 + data_len, read_size, rc);
- goto free_data;
- }
- object->crc = buf[0] << 8 | buf[1];
- object_type = (read_size == 3) ? buf[2] : BIF_OBJ_END_OF_LIST;
- sdev->nvm_function->object_count++;
- crc = bif_object_crc_ccitt(object);
- if (crc != object->crc)
- pr_info("BIF object at addr=0x%04X has invalid CRC; crc calc=0x%04X, crc exp=0x%04X\n",
- object->addr, crc, object->crc);
- addr += object->length;
- }
- return rc;
- free_data:
- list_for_each_entry_safe(object, temp,
- &sdev->nvm_function->object_list, list) {
- list_del(&object->list);
- kfree(object->data);
- kfree(object);
- }
- kfree(sdev->nvm_function);
- sdev->nvm_function = NULL;
- return rc;
- }
- static int bif_parse_slave_data(struct bif_slave_dev *sdev)
- {
- int rc = 0;
- u8 buf[10];
- u8 *func_buf;
- struct bif_ddb_l2_data *func;
- int function_count, i;
- rc = _bif_slave_read(sdev, BIF_DDB_L1_BASE_ADDR, buf, 10);
- if (rc) {
- pr_err("DDB L1 data read failed, rc=%d\n", rc);
- return rc;
- }
- sdev->l1_data.revision = buf[0];
- sdev->l1_data.level = buf[1];
- sdev->l1_data.device_class = buf[2] << 8 | buf[3];
- sdev->l1_data.manufacturer_id = buf[4] << 8 | buf[5];
- sdev->l1_data.product_id = buf[6] << 8 | buf[7];
- sdev->l1_data.length = buf[8] << 8 | buf[9];
- function_count = sdev->l1_data.length / 4;
- if (sdev->l1_data.length % 4) {
- pr_err("Function directory length=%d is invalid\n",
- sdev->l1_data.length);
- return -EPROTO;
- }
- /* No DDB L2 function directory */
- if (function_count == 0)
- return 0;
- func_buf = kmalloc(sdev->l1_data.length, GFP_KERNEL);
- if (!func_buf) {
- pr_err("out of memory\n");
- return -ENOMEM;
- }
- sdev->function_directory = kzalloc(
- function_count * sizeof(struct bif_ddb_l2_data), GFP_KERNEL);
- if (!sdev->function_directory) {
- pr_err("out of memory\n");
- return -ENOMEM;
- }
- rc = _bif_slave_read(sdev, BIF_DDB_L2_BASE_ADDR, func_buf,
- sdev->l1_data.length);
- if (rc) {
- pr_err("DDB L2 data read failed, rc=%d\n", rc);
- return rc;
- }
- for (i = 0; i < function_count; i++) {
- func = &sdev->function_directory[i];
- func->function_type = func_buf[i * 4];
- func->function_version = func_buf[i * 4 + 1];
- func->function_pointer = func_buf[i * 4 + 2] << 8
- | func_buf[i * 4 + 3];
- rc = bif_initialize_protocol_function(sdev, func);
- if (rc)
- goto done;
- rc = bif_initialize_slave_control_function(sdev, func);
- if (rc)
- goto done;
- rc = bif_initialize_nvm_function(sdev, func);
- if (rc)
- goto done;
- }
- done:
- kfree(func_buf);
- return rc;
- }
- static int bif_add_secondary_slaves(struct bif_slave_dev *primary_slave)
- {
- int rc = 0;
- int data_len, i;
- u16 crc;
- struct bif_slave_dev *sdev;
- struct bif_object *object;
- list_for_each_entry(object, &primary_slave->nvm_function->object_list,
- list) {
- if (object->type != BIF_OBJ_SEC_SLAVE)
- continue;
- data_len = object->length - 8;
- if (data_len % BIF_UNIQUE_ID_BYTE_LENGTH) {
- pr_info("Invalid secondary slave object found, addr=0x%04X, data len=%d\n",
- object->addr, data_len);
- continue;
- }
- crc = bif_object_crc_ccitt(object);
- if (crc != object->crc) {
- pr_info("BIF object at addr=0x%04X has invalid CRC; crc calc=0x%04X, crc exp=0x%04X\n",
- object->addr, crc, object->crc);
- continue;
- }
- for (i = 0; i < data_len / BIF_UNIQUE_ID_BYTE_LENGTH; i++) {
- sdev = bif_add_slave(primary_slave->bdev);
- if (IS_ERR(sdev)) {
- rc = PTR_ERR(sdev);
- pr_err("bif_add_slave failed, rc=%d\n", rc);
- return rc;
- }
- memcpy(sdev->unique_id,
- &object->data[i * BIF_UNIQUE_ID_BYTE_LENGTH],
- BIF_UNIQUE_ID_BYTE_LENGTH);
- sdev->unique_id_bits_known = BIF_UNIQUE_ID_BIT_LENGTH;
- rc = bif_select_slave(sdev);
- if (rc) {
- pr_err("Could not select slave, rc=%d\n", rc);
- goto free_slave;
- }
- rc = bif_is_slave_selected(sdev->bdev);
- if (rc < 0) {
- pr_err("Transaction failed, rc=%d\n", rc);
- goto free_slave;
- } else if (rc == 1) {
- sdev->present = true;
- sdev->bdev->selected_sdev = sdev;
- rc = bif_parse_slave_data(sdev);
- if (rc) {
- pr_err("Failed to parse secondary slave data, rc=%d\n",
- rc);
- goto free_slave;
- }
- } else {
- sdev->present = false;
- sdev->bdev->selected_sdev = NULL;
- }
- }
- }
- return rc;
- free_slave:
- bif_remove_slave(sdev);
- return rc;
- }
- /*
- * Performs UID search to identify all slaves attached to the bus. Assumes that
- * all necessary locks are held.
- */
- static int bif_perform_uid_search(struct bif_ctrl_dev *bdev)
- {
- struct bif_slave_dev *sdev;
- struct bif_slave_dev *new_slave;
- bool resp[2], resp_dilc;
- int i;
- int rc = 0;
- u8 cmd_probe[2] = {BIF_CMD_DIP0, BIF_CMD_DIP1};
- u8 cmd_enter[2] = {BIF_CMD_DIE0, BIF_CMD_DIE1};
- /*
- * Iterate over all partially known UIDs adding new ones as they are
- * found.
- */
- list_for_each_entry(sdev, &bif_sdev_list, list) {
- /* Skip slaves with fully known UIDs. */
- if (sdev->unique_id_bits_known == BIF_UNIQUE_ID_BIT_LENGTH
- || sdev->bdev != bdev)
- continue;
- /* Begin a new UID search. */
- rc = bdev->desc->ops->bus_transaction(bdev, BIF_TRANS_BC,
- BIF_CMD_DISS);
- if (rc) {
- pr_err("bus_transaction failed, rc=%d\n", rc);
- return rc;
- }
- /* Step through all known UID bits (MSB to LSB). */
- for (i = 0; i < sdev->unique_id_bits_known; i++) {
- rc = bdev->desc->ops->bus_transaction(bdev,
- BIF_TRANS_BC,
- cmd_enter[get_uid_bit(sdev->unique_id, i)]);
- if (rc) {
- pr_err("bus_transaction failed, rc=%d\n", rc);
- return rc;
- }
- }
- /* Step through unknown UID bits. */
- for (i = sdev->unique_id_bits_known;
- i < BIF_UNIQUE_ID_BIT_LENGTH; i++) {
- rc = bdev->desc->ops->bus_transaction_query(bdev,
- BIF_TRANS_BC, cmd_probe[0], &resp[0]);
- if (rc) {
- pr_err("bus_transaction failed, rc=%d\n", rc);
- return rc;
- }
- rc = bdev->desc->ops->bus_transaction_query(bdev,
- BIF_TRANS_BC, cmd_probe[1], &resp[1]);
- if (rc) {
- pr_err("bus_transaction failed, rc=%d\n", rc);
- return rc;
- }
- if (resp[0] && resp[1]) {
- /* Create an entry for the new UID branch. */
- new_slave = bif_add_slave(bdev);
- if (IS_ERR(new_slave)) {
- rc = PTR_ERR(sdev);
- pr_err("bif_add_slave failed, rc=%d\n",
- rc);
- return rc;
- }
- memcpy(new_slave->unique_id, sdev->unique_id,
- BIF_UNIQUE_ID_BYTE_LENGTH);
- new_slave->bdev = sdev->bdev;
- set_uid_bit(sdev->unique_id, i, 0);
- sdev->unique_id_bits_known = i + 1;
- set_uid_bit(new_slave->unique_id, i, 1);
- new_slave->unique_id_bits_known = i + 1;
- } else if (resp[0]) {
- set_uid_bit(sdev->unique_id, i, 0);
- sdev->unique_id_bits_known = i + 1;
- } else if (resp[1]) {
- set_uid_bit(sdev->unique_id, i, 1);
- sdev->unique_id_bits_known = i + 1;
- } else {
- pr_debug("no bus query response received\n");
- rc = -ENXIO;
- return rc;
- }
- rc = bdev->desc->ops->bus_transaction(bdev,
- BIF_TRANS_BC, cmd_enter[resp[0] ? 0 : 1]);
- if (rc) {
- pr_err("bus_transaction failed, rc=%d\n", rc);
- return rc;
- }
- }
- rc = bdev->desc->ops->bus_transaction_query(bdev,
- BIF_TRANS_BC, BIF_CMD_DILC, &resp_dilc);
- if (rc) {
- pr_err("bus_transaction failed, rc=%d\n", rc);
- return rc;
- }
- if (resp_dilc) {
- sdev->present = true;
- sdev->bdev->selected_sdev = sdev;
- rc = bif_parse_slave_data(sdev);
- if (rc) {
- pr_err("Failed to parse secondary slave data, rc=%d\n",
- rc);
- return rc;
- }
- } else {
- pr_err("Slave failed to respond to DILC bus command; its UID is thus unverified.\n");
- sdev->unique_id_bits_known = 0;
- rc = -ENXIO;
- return rc;
- }
- }
- return rc;
- }
- /*
- * Removes slaves from the bif_sdev_list which have the same UID as previous
- * slaves in the list.
- */
- static int bif_remove_duplicate_slaves(struct bif_ctrl_dev *bdev)
- {
- struct bif_slave_dev *sdev;
- struct bif_slave_dev *last_slave;
- struct bif_slave_dev *temp;
- list_for_each_entry_safe(last_slave, temp, &bif_sdev_list, list) {
- list_for_each_entry(sdev, &bif_sdev_list, list) {
- if (last_slave == sdev) {
- break;
- } else if (memcmp(last_slave->unique_id,
- sdev->unique_id,
- BIF_UNIQUE_ID_BYTE_LENGTH) == 0) {
- bif_remove_slave(last_slave);
- break;
- }
- }
- }
- return 0;
- }
- static int bif_add_all_slaves(struct bif_ctrl_dev *bdev)
- {
- struct bif_slave_dev *sdev;
- int rc = 0;
- int i;
- bool has_slave = false, is_primary_slave = false;
- mutex_lock(&bif_sdev_list_mutex);
- mutex_lock(&bdev->mutex);
- list_for_each_entry(sdev, &bif_sdev_list, list) {
- if (sdev->bdev == bdev) {
- has_slave = true;
- break;
- }
- }
- if (!has_slave) {
- /* Create a single empty slave to start the search algorithm. */
- sdev = bif_add_slave(bdev);
- if (IS_ERR(sdev)) {
- rc = PTR_ERR(sdev);
- pr_err("bif_add_slave failed, rc=%d\n", rc);
- goto out;
- }
- for (i = 0; i < BIF_TRANSACTION_RETRY_COUNT; i++) {
- /* Attempt to select primary slave in battery pack. */
- rc = bdev->desc->ops->bus_transaction(bdev,
- BIF_TRANS_SDA, BIF_PRIMARY_SLAVE_DEV_ADR);
- if (rc == 0)
- break;
- }
- if (rc) {
- pr_err("BIF bus_transaction failed, rc=%d\n", rc);
- goto out;
- }
- /* Check if a slave is selected. */
- rc = bif_is_slave_selected(bdev);
- if (rc < 0) {
- pr_err("BIF bus_transaction failed, rc=%d\n", rc);
- goto out;
- } else {
- is_primary_slave = rc;
- }
- }
- if (is_primary_slave) {
- pr_debug("Using primary slave at DEV_ADR==0x%02X\n",
- BIF_PRIMARY_SLAVE_DEV_ADR);
- sdev->bdev->selected_sdev = sdev;
- sdev->present = true;
- sdev->slave_addr = BIF_PRIMARY_SLAVE_DEV_ADR;
- rc = bif_parse_slave_data(sdev);
- if (rc) {
- pr_err("Failed to parse primary slave data, rc=%d\n",
- rc);
- goto out;
- }
- rc = bif_add_secondary_slaves(sdev);
- if (rc) {
- pr_err("Failed to add secondary slaves, rc=%d\n", rc);
- goto out;
- }
- } else {
- pr_debug("Falling back on full UID search.\n");
- for (i = 0; i < BIF_TRANSACTION_RETRY_COUNT; i++) {
- rc = bif_perform_uid_search(bdev);
- if (rc == 0)
- break;
- }
- if (rc) {
- pr_debug("BIF UID search failed, rc=%d\n", rc);
- goto out;
- }
- }
- bif_remove_duplicate_slaves(bdev);
- mutex_unlock(&bdev->mutex);
- mutex_unlock(&bif_sdev_list_mutex);
- return rc;
- out:
- mutex_unlock(&bdev->mutex);
- mutex_unlock(&bif_sdev_list_mutex);
- pr_debug("BIF slave search failed, rc=%d\n", rc);
- return rc;
- }
- static int bif_add_known_slave(struct bif_ctrl_dev *bdev, u8 slave_addr)
- {
- struct bif_slave_dev *sdev;
- int rc = 0;
- int i;
- for (i = 0; i < BIF_TRANSACTION_RETRY_COUNT; i++) {
- /* Attempt to select the slave. */
- rc = bdev->desc->ops->bus_transaction(bdev, BIF_TRANS_SDA,
- slave_addr);
- if (rc == 0)
- break;
- }
- if (rc) {
- pr_err("BIF bus_transaction failed, rc=%d\n", rc);
- return rc;
- }
- /* Check if a slave is selected. */
- rc = bif_is_slave_selected(bdev);
- if (rc < 0) {
- pr_err("BIF bus_transaction failed, rc=%d\n", rc);
- return rc;
- }
- sdev = bif_add_slave(bdev);
- if (IS_ERR(sdev)) {
- rc = PTR_ERR(sdev);
- pr_err("bif_add_slave failed, rc=%d\n", rc);
- return rc;
- }
- sdev->bdev->selected_sdev = sdev;
- sdev->present = true;
- sdev->slave_addr = slave_addr;
- rc = bif_parse_slave_data(sdev);
- if (rc) {
- pr_err("Failed to parse slave data, addr=0x%02X, rc=%d\n",
- slave_addr, rc);
- return rc;
- }
- return rc;
- }
- static int bif_add_known_slaves_from_dt(struct bif_ctrl_dev *bdev,
- struct device_node *of_node)
- {
- int len = 0;
- int rc, i;
- u32 addr;
- const __be32 *val;
- mutex_lock(&bif_sdev_list_mutex);
- mutex_lock(&bdev->mutex);
- val = of_get_property(of_node, "qcom,known-device-addresses", &len);
- len /= sizeof(u32);
- if (val && len == 0) {
- pr_err("qcom,known-device-addresses property is invalid\n");
- rc = -EINVAL;
- goto out;
- }
- for (i = 0; i < len; i++) {
- addr = be32_to_cpup(val++);
- if (addr == 0x00 || addr > 0xFF) {
- rc = -EINVAL;
- pr_err("qcom,known-device-addresses property contains invalid address=0x%X\n",
- addr);
- goto out;
- }
- rc = bif_add_known_slave(bdev, addr);
- if (rc) {
- pr_err("bif_add_known_slave() failed, rc=%d\n", rc);
- goto out;
- }
- }
- out:
- if (len > 0)
- bif_remove_duplicate_slaves(bdev);
- mutex_unlock(&bdev->mutex);
- mutex_unlock(&bif_sdev_list_mutex);
- return rc;
- }
- /*
- * Programs a device address for the specified slave in order to simplify
- * slave selection in the future.
- */
- static int bif_assign_slave_dev_addr(struct bif_slave_dev *sdev, u8 dev_addr)
- {
- int rc;
- u16 addr;
- if (!sdev->protocol_function) {
- pr_err("Protocol function not present; cannot set device address.\n");
- return -ENODEV;
- }
- addr = PROTOCOL_FUNC_DEV_ADR_ADDR(
- sdev->protocol_function->protocol_pointer);
- rc = _bif_slave_write(sdev, addr, &dev_addr, 1);
- if (rc)
- pr_err("Failed to set slave device address.\n");
- else
- sdev->slave_addr = dev_addr;
- return rc;
- }
- /* Assigns a unique device address to all slaves which do not have one. */
- static int bif_assign_all_slaves_dev_addr(struct bif_ctrl_dev *bdev)
- {
- struct bif_slave_dev *sdev;
- struct bif_slave_dev *sibling;
- bool duplicate;
- int rc = 0;
- u8 dev_addr, first_dev_addr;
- mutex_lock(&bif_sdev_list_mutex);
- mutex_lock(&bdev->mutex);
- first_dev_addr = next_dev_addr;
- /*
- * Iterate over all partially known UIDs adding new ones as they are
- * found.
- */
- list_for_each_entry(sdev, &bif_sdev_list, list) {
- /*
- * Skip slaves without known UIDs, which already have a device
- * address or which aren't present.
- */
- if (sdev->unique_id_bits_known != BIF_UNIQUE_ID_BIT_LENGTH
- || sdev->slave_addr != 0x00 || !sdev->present)
- continue;
- do {
- dev_addr = next_dev_addr;
- duplicate = false;
- list_for_each_entry(sibling, &bif_sdev_list, list) {
- if (sibling->slave_addr == dev_addr) {
- duplicate = true;
- break;
- }
- }
- next_dev_addr = dev_addr + 1;
- } while (duplicate && (next_dev_addr != first_dev_addr));
- if (next_dev_addr == first_dev_addr) {
- pr_err("No more BIF slave device addresses available.\n");
- rc = -ENODEV;
- goto out;
- }
- rc = bif_assign_slave_dev_addr(sdev, dev_addr);
- if (rc) {
- pr_err("Failed to set slave address.\n");
- goto out;
- }
- }
- mutex_unlock(&bdev->mutex);
- mutex_unlock(&bif_sdev_list_mutex);
- return rc;
- out:
- mutex_unlock(&bdev->mutex);
- mutex_unlock(&bif_sdev_list_mutex);
- pr_err("BIF slave device address setting failed, rc=%d\n", rc);
- return rc;
- }
- /**
- * bdev_get_drvdata() - get the private BIF controller driver data
- * @bdev: BIF controller device pointer
- */
- void *bdev_get_drvdata(struct bif_ctrl_dev *bdev)
- {
- return bdev->driver_data;
- }
- EXPORT_SYMBOL(bdev_get_drvdata);
- static const char * const battery_label[] = {
- "unknown",
- "none",
- "special 1",
- "special 2",
- "special 3",
- "low cost",
- "smart",
- };
- static const char *bif_get_battery_pack_type(int rid_ohm)
- {
- const char *label = battery_label[0];
- if (rid_ohm > BIF_BATT_RID_SMART_MAX)
- label = battery_label[1];
- else if (rid_ohm >= BIF_BATT_RID_SMART_MIN)
- label = battery_label[6];
- else if (rid_ohm >= BIF_BATT_RID_LOW_COST_MIN
- && rid_ohm <= BIF_BATT_RID_LOW_COST_MAX)
- label = battery_label[5];
- else if (rid_ohm >= BIF_BATT_RID_SPECIAL3_MIN
- && rid_ohm <= BIF_BATT_RID_SPECIAL3_MAX)
- label = battery_label[4];
- else if (rid_ohm >= BIF_BATT_RID_SPECIAL2_MIN
- && rid_ohm <= BIF_BATT_RID_SPECIAL2_MAX)
- label = battery_label[3];
- else if (rid_ohm >= BIF_BATT_RID_SPECIAL1_MIN
- && rid_ohm <= BIF_BATT_RID_SPECIAL1_MAX)
- label = battery_label[2];
- return label;
- }
- /**
- * bif_ctrl_register() - register a BIF controller with the BIF framework
- * @bif_desc: Pointer to BIF controller descriptor
- * @dev: Device pointer of the BIF controller
- * @driver_data: Private driver data to associate with the BIF controller
- * @of_node Pointer to the device tree node of the BIF controller
- *
- * Returns a BIF controller device pointer for the controller if registration
- * is successful or an ERR_PTR if an error occurred.
- */
- struct bif_ctrl_dev *bif_ctrl_register(struct bif_ctrl_desc *bif_desc,
- struct device *dev, void *driver_data, struct device_node *of_node)
- {
- struct bif_ctrl_dev *bdev = ERR_PTR(-EINVAL);
- struct bif_slave_dev *sdev;
- bool battery_present = false;
- bool slaves_present = false;
- int rc, rid_ohm;
- if (!bif_desc) {
- pr_err("Invalid bif_desc specified\n");
- return bdev;
- } else if (!bif_desc->name) {
- pr_err("BIF name missing\n");
- return bdev;
- } else if (!bif_desc->ops) {
- pr_err("BIF operations missing\n");
- return bdev;
- } else if (!bif_desc->ops->bus_transaction
- || !bif_desc->ops->bus_transaction_query
- || !bif_desc->ops->bus_transaction_read
- || !bif_desc->ops->get_bus_state
- || !bif_desc->ops->set_bus_state) {
- pr_err("BIF operation callback function(s) missing\n");
- return bdev;
- }
- bdev = kzalloc(sizeof(struct bif_ctrl_dev), GFP_KERNEL);
- if (bdev == NULL) {
- pr_err("Memory allocation failed for bif_ctrl_dev\n");
- return ERR_PTR(-ENOMEM);
- }
- mutex_init(&bdev->mutex);
- INIT_LIST_HEAD(&bdev->list);
- INIT_DELAYED_WORK(&bdev->enter_irq_mode_work, bif_enter_irq_mode_work);
- bdev->desc = bif_desc;
- bdev->ctrl_dev = dev;
- bdev->driver_data = driver_data;
- bdev->irq_mode_delay_jiffies = 2;
- mutex_lock(&bif_ctrl_list_mutex);
- list_add_tail(&bdev->list, &bif_ctrl_list);
- mutex_unlock(&bif_ctrl_list_mutex);
- rc = bif_add_all_slaves(bdev);
- if (rc)
- pr_debug("Search for all slaves failed, rc=%d\n", rc);
- rc = bif_add_known_slaves_from_dt(bdev, of_node);
- if (rc)
- pr_err("Adding slaves based on device tree addressed failed, rc=%d.\n",
- rc);
- rc = bif_assign_all_slaves_dev_addr(bdev);
- if (rc)
- pr_err("Failed to set slave device address, rc=%d\n", rc);
- bif_print_slaves();
- if (bdev->desc->ops->get_battery_presence) {
- rc = bdev->desc->ops->get_battery_presence(bdev);
- if (rc < 0) {
- pr_err("Could not determine battery presence, rc=%d\n",
- rc);
- } else {
- battery_present = rc;
- pr_info("Battery pack present = %c\n", rc ? 'Y' : 'N');
- }
- }
- if (bdev->desc->ops->get_battery_rid) {
- rid_ohm = bdev->desc->ops->get_battery_rid(bdev);
- if (rid_ohm >= 0)
- pr_info("Battery pack type = %s (Rid=%d ohm)\n",
- bif_get_battery_pack_type(rid_ohm), rid_ohm);
- else
- pr_err("Could not read Rid, rc=%d\n", rid_ohm);
- }
- list_for_each_entry(sdev, &bif_sdev_list, list) {
- if (sdev->present) {
- battery_present = true;
- slaves_present = true;
- break;
- }
- }
- BLOCKING_INIT_NOTIFIER_HEAD(&bdev->bus_change_notifier);
- /* Disable the BIF bus master if no slaves are found. */
- if (!slaves_present) {
- rc = bdev->desc->ops->set_bus_state(bdev,
- BIF_BUS_STATE_MASTER_DISABLED);
- if (rc < 0)
- pr_err("Could not disble BIF master, rc=%d\n", rc);
- }
- if (battery_present) {
- bdev->battery_present = true;
- rc = blocking_notifier_call_chain(&bdev->bus_change_notifier,
- BIF_BUS_EVENT_BATTERY_INSERTED, bdev);
- if (rc)
- pr_err("Call chain noification failed, rc=%d\n", rc);
- }
- return bdev;
- }
- EXPORT_SYMBOL(bif_ctrl_register);
- /**
- * bif_ctrl_unregister() - unregisters a BIF controller
- * @bdev: BIF controller device pointer
- */
- void bif_ctrl_unregister(struct bif_ctrl_dev *bdev)
- {
- if (bdev) {
- mutex_lock(&bif_ctrl_list_mutex);
- list_del(&bdev->list);
- mutex_unlock(&bif_ctrl_list_mutex);
- }
- }
- EXPORT_SYMBOL(bif_ctrl_unregister);
|