1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437 |
- /*
- * pt_loader.c
- * Parade TrueTouch(TM) Standard Product FW Loader Module.
- * For use with Parade touchscreen controllers.
- * Supported parts include:
- * TMA5XX
- * TMA448
- * TMA445A
- * TT21XXX
- * TT31XXX
- * TT4XXXX
- * TT7XXX
- * TC3XXX
- *
- * Copyright (C) 2015-2020 Parade Technologies
- *
- * 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.
- *
- * Contact Parade Technologies at www.paradetech.com <[email protected]>
- */
- #include "pt_regs.h"
- #include <linux/firmware.h>
- #define PT_LOADER_NAME "pt_loader"
- #define PT_AUTO_LOAD_FOR_CORRUPTED_FW 1
- #define PT_LOADER_FW_UPGRADE_RETRY_COUNT 3
- #define PT_FW_UPGRADE \
- (defined(CONFIG_TOUCHSCREEN_PARADE_PLATFORM_FW_UPGRADE) \
- || defined(CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE))
- #define PT_TTCONFIG_UPGRADE \
- (defined(CONFIG_TOUCHSCREEN_PARADE_PLATFORM_TTCONFIG_UPGRADE) \
- || defined(CONFIG_TOUCHSCREEN_PARADE_MANUAL_TTCONFIG_UPGRADE))
- /* Timeout values in ms. */
- #define PT_LDR_REQUEST_EXCLUSIVE_TIMEOUT 3000
- #define PT_LDR_SWITCH_TO_APP_MODE_TIMEOUT 300
- #define PT_MAX_STATUS_SIZE 32
- #define PT_DATA_MAX_ROW_SIZE 256
- #define PT_DATA_ROW_SIZE 128
- #define PT_ARRAY_ID_OFFSET 0
- #define PT_ROW_NUM_OFFSET 1
- #define PT_ROW_SIZE_OFFSET 3
- #define PT_ROW_DATA_OFFSET 5
- #define PT_POST_TT_CFG_CRC_MASK 0x2
- static inline struct pt_loader_data *pt_get_loader_data(
- struct device *dev);
- static struct pt_core_commands *cmd;
- #define PIP2_LAUNCH_APP_DELAY 400
- struct pip2_file_read {
- s8 para_num;
- u8 file_handle;
- int file_offset;
- int file_max_size;
- int file_read_size;
- int file_print_size;
- u8 *file_print_buf;
- int file_print_left;
- };
- #ifdef TTDL_DIAGNOSTICS
- struct pip2_file_crc {
- s8 para_num;
- u8 file_handle;
- int file_offset;
- int file_max_size;
- int file_read_size;
- };
- #endif
- struct pip2_loader_data {
- struct device *dev;
- struct completion pip2_fw_upgrade_complete; /* mutex for loader */
- u8 pip2_file_handle;
- };
- struct pt_loader_data {
- struct device *dev;
- struct pt_sysinfo *si;
- u8 status_buf[PT_MAX_STATUS_SIZE];
- struct completion int_running;
- struct completion calibration_complete;
- #ifdef CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE
- int builtin_bin_fw_status;
- bool is_manual_upgrade_enabled;
- #endif
- struct work_struct fw_and_config_upgrade;
- struct work_struct calibration_work;
- struct pt_loader_platform_data *loader_pdata;
- #ifdef CONFIG_TOUCHSCREEN_PARADE_MANUAL_TTCONFIG_UPGRADE
- struct mutex config_lock;
- u8 *config_data;
- int config_size;
- bool config_loading;
- #endif
- struct pip2_loader_data *pip2_data;
- u8 pip2_load_file_no;
- bool pip2_load_builtin;
- u8 pip2_file_erase_file_no;
- struct pip2_file_read pip2_file_data;
- #ifdef TTDL_DIAGNOSTICS
- struct pip2_file_crc pip2_fcrc;
- #endif
- #ifdef CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE
- struct work_struct bl_from_file;
- struct work_struct pip2_bl_from_file;
- #endif
- };
- static u8 update_fw_status;
- static int pip2_erase_status;
- static int pip2_erase_rc;
- /* PIP2 update fw status codes. 1-99% are "active" */
- enum UPDATE_FW_STATUS {
- UPDATE_FW_IDLE = 0,
- UPDATE_FW_ACTIVE_10 = 10,
- UPDATE_FW_ACTIVE_90 = 90,
- UPDATE_FW_ACTIVE_99 = 99,
- UPDATE_FW_COMPLETE = 100,
- UPDATE_FW_GENERAL_ERROR = 200,
- UPDATE_FW_PIP_VERSION_ERROR = 201,
- UPDATE_FW_VERSION_ERROR = 202,
- UPDATE_FW_ERASE_ERROR = 203,
- UPDATE_FW_FILE_CLOSE_ERROR = 204,
- UPDATE_FW_WRITE_ERROR = 205,
- UPDATE_FW_EXECUTE_ERROR = 206,
- UPDATE_FW_RESET_ERROR = 207,
- UPDATE_FW_MODE_ERROR = 208,
- UPDATE_FW_ENTER_BL_ERROR = 209,
- UPDATE_FW_FILE_OPEN_ERROR = 210,
- UPDATE_FW_SENTINEL_NOT_SEEN = 211,
- UPDATE_FW_EXCLUSIVE_ACCESS_ERROR = 212,
- UPDATE_FW_NO_FW_PROVIDED = 213,
- UPDATE_FW_INVALID_FW_IMAGE = 214,
- UPDATE_FW_MISALIGN_FW_IMAGE = 230,
- UPDATE_FW_SYSTEM_NOMEM = 231,
- UPDATE_FW_INIT_BL_ERROR = 232,
- UPDATE_FW_PARSE_ROW_ERROR = 233,
- UPDATE_FW_PROGRAM_ROW_ERROR = 234,
- UPDATE_FW_EXIT_BL_ERROR = 235,
- UPDATE_FW_CHECK_SUM_ERROR = 236,
- UPDATE_FW_NO_PLATFORM_DATA = 237,
- UPDATE_FW_UNDEFINED_ERROR = 255,
- };
- enum PIP2_FILE_ERASE_STATUS {
- PIP2_FILE_ERASE_STATUS_DUT_BUSY = 101,
- PIP2_FILE_ERASE_STATUS_ENTER_BL_ERROR = 102,
- };
- struct pt_dev_id {
- u32 silicon_id;
- u8 rev_id;
- u32 bl_ver;
- };
- struct pt_hex_image {
- u8 array_id;
- u16 row_num;
- u16 row_size;
- u8 row_data[PT_DATA_ROW_SIZE];
- } __packed;
- #ifdef CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE
- static int pt_pip2_upgrade_firmware_from_builtin(struct device *dev);
- #endif
- typedef int (*PIP2_SEND_CMD)(struct device *, int,
- u8, u8 *, u16, u8 *, u16 *);
- static struct pt_module loader_module;
- /*******************************************************************************
- * FUNCTION: pt_get_loader_data
- *
- * SUMMARY: Inline function to get pt_loader_data pointer from loader module.
- *
- * RETURN:
- * pointer to pt_loader_data structure
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- ******************************************************************************/
- static inline struct pt_loader_data *pt_get_loader_data(
- struct device *dev)
- {
- return pt_get_module_data(dev, &loader_module);
- }
- #if PT_FW_UPGRADE || PT_TTCONFIG_UPGRADE
- /*******************************************************************************
- * FUNCTION: pt_calibrate_idacs
- *
- * SUMMARY: Calibrate idac for mutual-cap,buttons,self-cap by called functions.
- * It needs stop panel scan during calibration.
- *
- * PARAMETERS:
- * *calibration_work - pointer to work_struct structure
- ******************************************************************************/
- static void pt_calibrate_idacs(struct work_struct *calibration_work)
- {
- struct pt_loader_data *ld = container_of(calibration_work,
- struct pt_loader_data, calibration_work);
- struct device *dev = ld->dev;
- struct pt_cal_ext_data cal_data = {0};
- u8 dut_gen = cmd->request_dut_generation(dev);
- u8 mode;
- u8 status;
- int rc;
- pt_debug(dev, DL_INFO, "Entering %s\n", __func__);
- rc = cmd->request_exclusive(dev, PT_LDR_REQUEST_EXCLUSIVE_TIMEOUT);
- if (rc < 0)
- goto exit;
- rc = cmd->nonhid_cmd->suspend_scanning(dev, 0);
- if (rc < 0)
- goto release;
- if (dut_gen == DUT_PIP1_ONLY) {
- for (mode = 0; mode < 3; mode++) {
- rc = cmd->nonhid_cmd->calibrate_idacs(dev, 0, mode,
- &status);
- if (rc < 0) {
- pt_debug(dev, DL_ERROR,
- "%s: calibrate idac error, rc = %d\n",
- __func__, rc);
- break;
- }
- }
- } else {
- /*
- * Manual calibration is not need after fw 3.4.932110.
- * Therefore, PT_LOADER_FLAG_NONE should be used to avoid
- * manual calibration if the FW is newer than 3.4.932110.
- */
- memset(&cal_data, 0, sizeof(struct pt_cal_ext_data));
- rc = cmd->nonhid_cmd->calibrate_ext(dev, 0, &cal_data,
- &status);
- if (rc < 0) {
- pt_debug(dev, DL_ERROR,
- "%s: extended calibrate error, rc = %d\n",
- __func__, rc);
- }
- }
- rc = cmd->nonhid_cmd->resume_scanning(dev, 0);
- if (rc < 0)
- goto release;
- pt_debug(dev, DL_WARN, "%s: Calibration Done\n", __func__);
- release:
- cmd->release_exclusive(dev);
- exit:
- complete(&ld->calibration_complete);
- }
- /*******************************************************************************
- * FUNCTION: pt_calibration_attention
- *
- * SUMMARY: Wrapper function to schedule calibration work used to subscribe into
- * TTDL attention list.Once called will unsubscribe from attention list.
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- ******************************************************************************/
- static int pt_calibration_attention(struct device *dev)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- int rc = 0;
- schedule_work(&ld->calibration_work);
- cmd->unsubscribe_attention(dev, PT_ATTEN_STARTUP, PT_LOADER_NAME,
- pt_calibration_attention, 0);
- return rc;
- }
- #endif /* PT_FW_UPGRADE || PT_TTCONFIG_UPGRADE */
- #if PT_FW_UPGRADE \
- || defined(CONFIG_TOUCHSCREEN_PARADE_PLATFORM_TTCONFIG_UPGRADE)
- /*******************************************************************************
- * FUNCTION: pt_get_panel_id
- *
- * SUMMARY: Get panel id from core data.
- *
- * RETURN:
- * panel id
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- ******************************************************************************/
- static u8 pt_get_panel_id(struct device *dev)
- {
- struct pt_core_data *cd = dev_get_drvdata(dev);
- return cd->pid_for_loader;
- }
- #endif
- #if (PT_FW_UPGRADE || PT_TTCONFIG_UPGRADE)
- /*******************************************************************************
- * FUNCTION: pt_check_firmware_version
- *
- * SUMMARY: Compare fw's version and revision control number with fw image's.
- *
- * RETURN:
- * -1: Do not upgrade firmware
- * 0: Version info same, let caller decide
- * 1: Do a firmware upgrade
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * fw_ver_new - firmware version
- * fw_revctrl_new - firmware revision control number
- ******************************************************************************/
- static int pt_check_firmware_version(struct device *dev,
- u32 fw_ver_new, u32 fw_revctrl_new)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- u32 fw_ver_img;
- u32 fw_revctrl_img;
- fw_ver_img = ld->si->ttdata.fw_ver_major << 8;
- fw_ver_img += ld->si->ttdata.fw_ver_minor;
- pt_debug(dev, DL_WARN,
- "%s: Current FW ver:0x%04X New FW ver:0x%04X\n", __func__,
- fw_ver_img, fw_ver_new);
- if (fw_ver_new > fw_ver_img) {
- pt_debug(dev, DL_WARN,
- "%s: Image is newer, will upgrade\n", __func__);
- return 1;
- }
- if (fw_ver_new < fw_ver_img) {
- pt_debug(dev, DL_WARN,
- "%s: Image is older, will NOT upgrade\n", __func__);
- return -EPERM;
- }
- fw_revctrl_img = ld->si->ttdata.revctrl;
- pt_debug(dev, DL_WARN,
- "%s: Current FW rev:%d New FW rev:%d\n",
- __func__, fw_revctrl_img, fw_revctrl_new);
- if (fw_revctrl_new > fw_revctrl_img) {
- pt_debug(dev, DL_WARN,
- "%s: Image is newer, will upgrade\n", __func__);
- return 1;
- }
- if (fw_revctrl_new < fw_revctrl_img) {
- pt_debug(dev, DL_WARN,
- "%s: Image is older, will NOT upgrade\n", __func__);
- return -EPERM;
- }
- return 0;
- }
- #endif /* PT_FW_UPGRADE || PT_TTCONFIG_UPGRADE */
- #if PT_FW_UPGRADE
- /*******************************************************************************
- * FUNCTION: pt_get_row_
- *
- * SUMMARY: Copy the image data to the "row_buf".
- *
- * RETURN:
- * pointer to image buffer plus copy size
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *row_buf - pointer to written buffer to program chip
- * *image_buf - pointer to image buffer
- * size - size of written data
- ******************************************************************************/
- static u8 *pt_get_row_(struct device *dev, u8 *row_buf,
- u8 *image_buf, int size)
- {
- memcpy(row_buf, image_buf, size);
- return image_buf + size;
- }
- /*******************************************************************************
- * FUNCTION: pt_ldr_enter_
- *
- * SUMMARY: Enter bootloader state and update device id(silicon id, rev id,
- * bootloader version).
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *dev_id - pointer to device id
- ******************************************************************************/
- static int pt_ldr_enter_(struct device *dev, struct pt_dev_id *dev_id)
- {
- int rc;
- u8 return_data[8];
- u8 mode = PT_MODE_OPERATIONAL;
- dev_id->silicon_id = 0;
- dev_id->rev_id = 0;
- dev_id->bl_ver = 0;
- /*
- * Reset to get to a known state, sleep to allow sentinel processing.
- *
- * NOTE: This msleep MUST be greater than the auto launch timeout
- * that is built into the FW.
- */
- cmd->request_reset(dev, PT_CORE_CMD_UNPROTECTED);
- msleep(20);
- rc = cmd->request_get_mode(dev, 0, &mode);
- pt_debug(dev, DL_INFO, "%s:request_get_mode rc=%d mode=%d\n",
- __func__, rc, mode);
- if (rc)
- return rc;
- if (mode == PT_MODE_UNKNOWN)
- return -EINVAL;
- if (mode == PT_MODE_OPERATIONAL) {
- rc = cmd->nonhid_cmd->start_bl(dev, PT_CORE_CMD_UNPROTECTED);
- pt_debug(dev, DL_INFO, "%s:start_bl rc=%d\n", __func__, rc);
- if (rc)
- return rc;
- rc = cmd->request_get_mode(dev, 0, &mode);
- pt_debug(dev, DL_INFO, "%s:request_get_mode rc=%d mode=%d\n",
- __func__, rc, mode);
- if (rc)
- return rc;
- if (mode != PT_MODE_BOOTLOADER)
- return -EINVAL;
- }
- rc = cmd->nonhid_cmd->get_bl_info(dev,
- PT_CORE_CMD_UNPROTECTED, return_data);
- pt_debug(dev, DL_INFO, "%s:get_bl_info rc=%d\n", __func__, rc);
- if (rc)
- return rc;
- dev_id->silicon_id = get_unaligned_le32(&return_data[0]);
- dev_id->rev_id = return_data[4];
- dev_id->bl_ver = return_data[5] + (return_data[6] << 8)
- + (return_data[7] << 16);
- return 0;
- }
- /*******************************************************************************
- * FUNCTION: pt_ldr_init_
- *
- * SUMMARY: Erase the entire TrueTouch application, Configuration Data block,
- * and Design Data block in flash and enables the host to execute the Program
- * and Verify Row command to bootload the application image and data.
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *pt_hex_image - pointer to hex image structure
- ******************************************************************************/
- static int pt_ldr_init_(struct device *dev,
- struct pt_hex_image *row_image)
- {
- return cmd->nonhid_cmd->initiate_bl(dev, 0, 8,
- (u8 *)pt_data_block_security_key, row_image->row_size,
- row_image->row_data);
- }
- /*******************************************************************************
- * FUNCTION: pt_ldr_parse_row_
- *
- * SUMMARY: Parse and copy the row buffer data to hex image structure.
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *row_buf - pointer to row buffer
- * *row_image - pointer to hex image structure
- ******************************************************************************/
- static int pt_ldr_parse_row_(struct device *dev, u8 *row_buf,
- struct pt_hex_image *row_image)
- {
- int rc = 0;
- row_image->array_id = row_buf[PT_ARRAY_ID_OFFSET];
- row_image->row_num = get_unaligned_be16(&row_buf[PT_ROW_NUM_OFFSET]);
- row_image->row_size = get_unaligned_be16(&row_buf[PT_ROW_SIZE_OFFSET]);
- if (row_image->row_size > ARRAY_SIZE(row_image->row_data)) {
- pt_debug(dev, DL_ERROR,
- "%s: row data buffer overflow\n", __func__);
- rc = -EOVERFLOW;
- goto pt_ldr_parse_row_exit;
- }
- memcpy(row_image->row_data, &row_buf[PT_ROW_DATA_OFFSET],
- row_image->row_size);
- pt_ldr_parse_row_exit:
- return rc;
- }
- /*******************************************************************************
- * FUNCTION: pt_ldr_prog_row_
- *
- * SUMMARY: Program one row that the hex image structure data to the chip.
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *row_image - pointer to hex image structure
- ******************************************************************************/
- static int pt_ldr_prog_row_(struct device *dev,
- struct pt_hex_image *row_image)
- {
- int rc = 0;
- u16 length = row_image->row_size + 3;
- u8 *data = NULL;
- u8 offset = 0;
- if (length > PT_DATA_MAX_ROW_SIZE)
- return -EINVAL;
- data = kzalloc(length, GFP_KERNEL);
- if (!data)
- return -ENOMEM;
- data[offset++] = row_image->array_id;
- data[offset++] = LOW_BYTE(row_image->row_num);
- data[offset++] = HI_BYTE(row_image->row_num);
- memcpy(data + 3, row_image->row_data, row_image->row_size);
- rc = cmd->nonhid_cmd->prog_and_verify(dev, 0, length, data);
- kfree(data);
- return rc;
- }
- /*******************************************************************************
- * FUNCTION: pt_ldr_verify_chksum_
- *
- * SUMMARY: Perform a full verification of the application integrity by
- * calculating the CRC of the TrueTouch application image in flash and
- * comparing it to the expected CRC stored in the TrueTouch application CRC
- * value stored in the Metadata row.
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- ******************************************************************************/
- static int pt_ldr_verify_chksum_(struct device *dev)
- {
- u8 result;
- int rc;
- rc = cmd->nonhid_cmd->verify_app_integrity(dev, 0, &result);
- if (rc)
- return rc;
- /* fail */
- if (result == 0)
- return -EINVAL;
- return 0;
- }
- /*******************************************************************************
- * FUNCTION: pt_ldr_exit_
- *
- * SUMMARY: Launch the application from bootloader.
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- ******************************************************************************/
- static int pt_ldr_exit_(struct device *dev)
- {
- return cmd->nonhid_cmd->launch_app(dev, 0);
- }
- #define PT_NO_INC 0
- /*******************************************************************************
- * FUNCTION: _pt_pip2_update_bl_status
- *
- * SUMMARY: Update the value in the bl_status global by either setting to a
- * specific value or incrementing it ensuring we don't go out of bounds.
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * value - Value to force, if 0 then ignore.
- * inc - Value to increment, if 0 then ignore.
- ******************************************************************************/
- static u8 _pt_pip2_update_bl_status(struct device *dev, u8 value, u8 inc)
- {
- pt_debug(dev, DL_DEBUG,
- "%s: fw_status = %d, request val=%d, request inc=%d\n",
- __func__, update_fw_status, value, inc);
- /* Reset status if both value and inc are 0 */
- if (value == UPDATE_FW_IDLE && inc == 0) {
- update_fw_status = value;
- pt_debug(dev, DL_WARN, "%s: ATM - Reset BL Status to %d\n",
- __func__, value);
- return update_fw_status;
- }
- /* Set to value if valid */
- if (value > UPDATE_FW_IDLE && value < UPDATE_FW_UNDEFINED_ERROR) {
- if (value <= UPDATE_FW_COMPLETE && value > update_fw_status) {
- update_fw_status = value;
- } else if (value >= UPDATE_FW_GENERAL_ERROR) {
- update_fw_status = value;
- pt_debug(dev, DL_WARN,
- "%s: BL Status set to error code %d\n",
- __func__, value);
- }
- return update_fw_status;
- }
- if (inc > 0 && update_fw_status + inc <= UPDATE_FW_COMPLETE)
- update_fw_status += inc;
- else
- pt_debug(dev, DL_ERROR,
- "%s: Inc Request out of bounds: status=%d inc=%d\n",
- __func__, update_fw_status, inc);
- return update_fw_status;
- }
- /*******************************************************************************
- * FUNCTION: pt_load_app_
- *
- * SUMMARY: Program the firmware image to the chip.
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *fw - pointer to the firmware
- * fw_size - size of firmware
- * update_status - store the update status of firmware
- ******************************************************************************/
- static int pt_load_app_(struct device *dev, const u8 *fw, int fw_size,
- u8 *update_status)
- {
- struct pt_core_data *cd = dev_get_drvdata(dev);
- struct pt_dev_id *dev_id;
- struct pt_hex_image *row_image;
- u8 *row_buf;
- size_t image_rec_size;
- size_t row_buf_size = PT_DATA_MAX_ROW_SIZE;
- int row_count = 0;
- u8 *p;
- u8 *last_row;
- int rc;
- int rc_tmp;
- int percent_cmplt;
- int total_row_count;
- if (update_status == NULL) {
- rc = -EINVAL;
- pt_debug(dev, DL_ERROR,
- "%s: update_status is NULL pointer %d\n",
- __func__, rc);
- return rc;
- } else if (*update_status > UPDATE_FW_ACTIVE_10) {
- pt_debug(dev, DL_WARN,
- "%s: update_status is illegal = %d, fixed to %d\n",
- __func__, *update_status, UPDATE_FW_ACTIVE_10);
- *update_status = UPDATE_FW_ACTIVE_10;
- }
- image_rec_size = sizeof(struct pt_hex_image);
- if (fw_size % image_rec_size != 0) {
- pt_debug(dev, DL_ERROR,
- "%s: Firmware image is misaligned\n", __func__);
- *update_status = UPDATE_FW_MISALIGN_FW_IMAGE;
- rc = -EINVAL;
- goto _pt_load_app_error;
- }
- *update_status += 1;
- total_row_count = fw_size / image_rec_size - 1;
- pt_debug(dev, DL_INFO, "%s: start load app\n", __func__);
- #ifdef TTHE_TUNER_SUPPORT
- cmd->request_tthe_print(dev, NULL, 0, "start load app");
- #endif
- row_buf = kzalloc(row_buf_size, GFP_KERNEL);
- row_image = kzalloc(sizeof(struct pt_hex_image), GFP_KERNEL);
- dev_id = kzalloc(sizeof(struct pt_dev_id), GFP_KERNEL);
- if (!row_buf || !row_image || !dev_id) {
- *update_status = UPDATE_FW_SYSTEM_NOMEM;
- rc = -ENOMEM;
- goto _pt_load_app_exit;
- }
- *update_status += 1;
- cmd->request_stop_wd(dev);
- pt_debug(dev, DL_INFO, "%s: Send BL Loader Enter\n", __func__);
- #ifdef TTHE_TUNER_SUPPORT
- cmd->request_tthe_print(dev, NULL, 0, "Send BL Loader Enter");
- #endif
- rc = pt_ldr_enter_(dev, dev_id);
- if (rc) {
- *update_status = UPDATE_FW_ENTER_BL_ERROR;
- pt_debug(dev, DL_ERROR, "%s: Error cannot start Loader (ret=%d)\n",
- __func__, rc);
- goto _pt_load_app_exit;
- }
- pt_debug(dev, DL_INFO,
- "%s: dev: silicon id=%08X rev=%02X bl=%08X\n", __func__,
- dev_id->silicon_id, dev_id->rev_id, dev_id->bl_ver);
- *update_status += 1;
- /*
- * since start loader is successful, firmware mode can be assumed
- * at bl mode directly. Updating this variable is helpful to detect
- * firmware entered application mode.
- */
- cd->mode = PT_MODE_BOOTLOADER;
- /* get last row */
- last_row = (u8 *)fw + fw_size - image_rec_size;
- pt_get_row_(dev, row_buf, last_row, image_rec_size);
- pt_ldr_parse_row_(dev, row_buf, row_image);
- /* initialise bootloader */
- rc = pt_ldr_init_(dev, row_image);
- if (rc) {
- *update_status = UPDATE_FW_ERASE_ERROR;
- pt_debug(dev, DL_ERROR, "%s: Error cannot init Loader (ret=%d)\n",
- __func__, rc);
- goto _pt_load_app_exit;
- }
- *update_status += 5;
- pt_debug(dev, DL_INFO,
- "%s: Send BL Loader Blocks\n", __func__);
- #ifdef TTHE_TUNER_SUPPORT
- cmd->request_tthe_print(dev, NULL, 0, "Send BL Loader Blocks");
- #endif
- p = (u8 *)fw;
- while (p < last_row) {
- /* Get row */
- row_count += 1;
- pt_debug(dev, DL_INFO, "%s: read row=%d\n",
- __func__, row_count);
- memset(row_buf, 0, row_buf_size);
- p = pt_get_row_(dev, row_buf, p, image_rec_size);
- /* Don't update BL status on every pass */
- if (row_count / 8 * 8 == row_count) {
- /* Calculate % complete for update_status sysfs */
- percent_cmplt = row_count * 100 / total_row_count;
- if (percent_cmplt > UPDATE_FW_ACTIVE_99)
- percent_cmplt = UPDATE_FW_ACTIVE_99;
- *update_status = (percent_cmplt > *update_status) ?
- percent_cmplt : *update_status;
- #ifdef TTDL_DIAGNOSTICS
- pt_debug(dev, DL_INFO,
- "Wrote row num %d of total %d\n",
- row_count, total_row_count);
- #endif
- }
- /* Parse row */
- pt_debug(dev, DL_INFO, "%s: p=%p buf=%p buf[0]=%02X\n",
- __func__, p, row_buf, row_buf[0]);
- rc = pt_ldr_parse_row_(dev, row_buf, row_image);
- pt_debug(dev, DL_INFO,
- "%s: array_id=%02X row_num=%04X(%d) row_size=%04X(%d)\n",
- __func__, row_image->array_id,
- row_image->row_num, row_image->row_num,
- row_image->row_size, row_image->row_size);
- if (rc) {
- *update_status = UPDATE_FW_PARSE_ROW_ERROR;
- pt_debug(dev, DL_ERROR,
- "%s: Parse Row Error (a=%d r=%d ret=%d\n",
- __func__, row_image->array_id,
- row_image->row_num, rc);
- goto _pt_load_app_exit;
- } else {
- pt_debug(dev, DL_INFO,
- "%s: Parse Row (a=%d r=%d ret=%d\n",
- __func__, row_image->array_id,
- row_image->row_num, rc);
- }
- /* program row */
- rc = pt_ldr_prog_row_(dev, row_image);
- if (rc) {
- *update_status = UPDATE_FW_PROGRAM_ROW_ERROR;
- pt_debug(dev, DL_ERROR,
- "%s: Prog Row Error (array=%d row=%d ret=%d)\n",
- __func__, row_image->array_id,
- row_image->row_num, rc);
- goto _pt_load_app_exit;
- }
- pt_debug(dev, DL_INFO,
- "%s: array=%d row_cnt=%d row_num=%04X\n",
- __func__, row_image->array_id, row_count,
- row_image->row_num);
- }
- /* exit loader */
- pt_debug(dev, DL_INFO, "%s: Send BL Loader Terminate\n", __func__);
- #ifdef TTHE_TUNER_SUPPORT
- cmd->request_tthe_print(dev, NULL, 0, "Send BL Loader Terminate");
- #endif
- rc = pt_ldr_exit_(dev);
- if (rc) {
- *update_status = UPDATE_FW_EXIT_BL_ERROR;
- pt_debug(dev, DL_ERROR, "%s: Error on exit Loader (ret=%d)\n",
- __func__, rc);
- /* verify app checksum */
- rc_tmp = pt_ldr_verify_chksum_(dev);
- if (rc_tmp) {
- *update_status = UPDATE_FW_CHECK_SUM_ERROR;
- pt_debug(dev, DL_ERROR,
- "%s: ldr_verify_chksum fail r=%d\n",
- __func__, rc_tmp);
- } else
- pt_debug(dev, DL_INFO,
- "%s: APP Checksum Verified\n", __func__);
- } else
- *update_status = UPDATE_FW_ACTIVE_99;
- _pt_load_app_exit:
- kfree(row_buf);
- kfree(row_image);
- kfree(dev_id);
- _pt_load_app_error:
- return rc;
- }
- /*******************************************************************************
- * FUNCTION: pt_upgrade_firmware
- *
- * SUMMARY: Program the firmware image and set call back for start up.
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *fw_img - pointer to the firmware
- * fw_size - size of firmware
- * *update_status - store the update status of firmware
- ******************************************************************************/
- static int pt_upgrade_firmware(struct device *dev, const u8 *fw_img,
- int fw_size, u8 *update_status)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- struct pt_core_data *cd = dev_get_drvdata(dev);
- int retry = PT_LOADER_FW_UPGRADE_RETRY_COUNT;
- bool wait_for_calibration_complete = false;
- int rc;
- int t;
- _pt_pip2_update_bl_status(dev, UPDATE_FW_IDLE, PT_NO_INC);
- if (update_status == NULL) {
- rc = -EINVAL;
- pt_debug(dev, DL_ERROR,
- "%s: update_status is NULL pointer %d\n",
- __func__, rc);
- return rc;
- } else if (*update_status > UPDATE_FW_ACTIVE_10) {
- pt_debug(dev, DL_WARN,
- "%s: update_status is illegal = %d, fixed to %d\n",
- __func__, *update_status, UPDATE_FW_ACTIVE_10);
- *update_status = UPDATE_FW_ACTIVE_10;
- }
- /* Ensure no enum task is pending */
- pt_debug(dev, DL_WARN, "%s: Cancel enum work thread\n", __func__);
- cancel_work_sync(&cd->enum_work);
- pm_runtime_get_sync(dev);
- *update_status += 1;
- rc = cmd->request_exclusive(dev, PT_LDR_REQUEST_EXCLUSIVE_TIMEOUT);
- if (rc < 0) {
- *update_status = UPDATE_FW_EXCLUSIVE_ACCESS_ERROR;
- goto exit;
- }
- *update_status += 1;
- t = *update_status;
- while (retry--) {
- /* Restore the update_status */
- *update_status = t;
- rc = pt_load_app_(dev, fw_img, fw_size, update_status);
- if (rc < 0)
- pt_debug(dev, DL_ERROR,
- "%s: Firmware update failed rc=%d, retry:%d\n",
- __func__, rc, retry);
- else
- break;
- msleep(20);
- }
- if (rc < 0) {
- pt_debug(dev, DL_ERROR,
- "%s: Firmware update failed with error code %d\n",
- __func__, rc);
- } else if (ld->loader_pdata &&
- (ld->loader_pdata->flags
- & PT_LOADER_FLAG_CALIBRATE_AFTER_FW_UPGRADE)) {
- #if (KERNEL_VERSION(3, 13, 0) <= LINUX_VERSION_CODE)
- reinit_completion(&ld->calibration_complete);
- #else
- INIT_COMPLETION(ld->calibration_complete);
- #endif
- /* set up call back for startup */
- pt_debug(dev, DL_INFO,
- "%s: Adding callback for calibration\n", __func__);
- rc = cmd->subscribe_attention(dev, PT_ATTEN_STARTUP,
- PT_LOADER_NAME, pt_calibration_attention, 0);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Failed adding callback for calibration\n",
- __func__);
- pt_debug(dev, DL_ERROR,
- "%s: No calibration will be performed\n",
- __func__);
- rc = 0;
- } else
- wait_for_calibration_complete = true;
- }
- cmd->release_exclusive(dev);
- exit:
- if (!rc) {
- cmd->request_enum(dev, true);
- /*
- * Wait for FW reset sentinel from reset or execute for up
- * to 500ms
- */
- t = wait_event_timeout(cd->wait_q,
- (cd->startup_status >=
- STARTUP_STATUS_FW_RESET_SENTINEL) &&
- (cd->mode == PT_MODE_OPERATIONAL),
- msecs_to_jiffies(PT_BL_WAIT_FOR_SENTINEL));
- if (IS_TMO(t)) {
- pt_debug(dev, DL_WARN,
- "%s: 0x%04X Timeout waiting for FW sentinel",
- __func__, cd->startup_status);
- }
- /* Double verify DUT is alive and well in Application mode */
- if (!(cd->startup_status & STARTUP_STATUS_FW_RESET_SENTINEL)) {
- pt_debug(dev, DL_ERROR,
- "%s FW sentinel not seen\n", __func__);
- *update_status = UPDATE_FW_SENTINEL_NOT_SEEN;
- } else if (cd->mode != PT_MODE_OPERATIONAL) {
- *update_status = UPDATE_FW_MODE_ERROR;
- pt_debug(dev, DL_ERROR,
- "%s ERROR: Not in App mode as expected\n",
- __func__);
- } else {
- *update_status = UPDATE_FW_COMPLETE;
- pt_debug(dev, DL_INFO,
- "%s == PIP1 FW upgrade finished ==\n",
- __func__);
- }
- } else if (*update_status < UPDATE_FW_COMPLETE) {
- *update_status = UPDATE_FW_UNDEFINED_ERROR;
- pt_debug(dev, DL_ERROR, "%s undefined error!\n", __func__);
- }
- pm_runtime_put_sync(dev);
- if (wait_for_calibration_complete)
- wait_for_completion(&ld->calibration_complete);
- return rc;
- }
- #endif /* PT_FW_UPGRADE */
- #ifdef CONFIG_TOUCHSCREEN_PARADE_PLATFORM_FW_UPGRADE
- /*******************************************************************************
- * FUNCTION: pt_check_firmware_version_platform
- *
- * SUMMARY: The caller of function pt_check_firmware_version() to determine
- * whether to load firmware from touch_firmware structure.
- *
- * RETURN:
- * 0: Don't upgrade
- * 1: Upgrade
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *fw - pointer to the touch_firmware structure
- ******************************************************************************/
- static int pt_check_firmware_version_platform(struct device *dev,
- struct pt_touch_firmware *fw)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- u32 fw_ver_new;
- u32 fw_revctrl_new;
- int upgrade;
- if (!ld->si) {
- pt_debug(dev, DL_WARN,
- "%s: No firmware info found, DUT FW may be corrupted\n",
- __func__);
- return PT_AUTO_LOAD_FOR_CORRUPTED_FW;
- }
- fw_ver_new = get_unaligned_be16(fw->ver + 2);
- /* 4 middle bytes are not used */
- fw_revctrl_new = get_unaligned_be32(fw->ver + 8);
- pt_debug(dev, DL_WARN, "%s: Built-in FW version 0x%04x rev %d\n",
- __func__, fw_ver_new, fw_revctrl_new);
- upgrade = pt_check_firmware_version(dev, fw_ver_new,
- fw_revctrl_new);
- if (upgrade > 0)
- return 1;
- return 0;
- }
- /*******************************************************************************
- * FUNCTION: pt_get_platform_firmware
- *
- * SUMMARY: To get the pointer of right touch_firmware structure by panel id.
- *
- * RETURN:
- * pointer to touch_firmware structure or null pointer if fail
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- ******************************************************************************/
- static struct pt_touch_firmware *pt_get_platform_firmware(
- struct device *dev)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- struct pt_touch_firmware **fws;
- struct pt_touch_firmware *fw;
- u8 panel_id;
- panel_id = pt_get_panel_id(dev);
- if (panel_id == PANEL_ID_NOT_ENABLED) {
- pt_debug(dev, DL_WARN,
- "%s: Panel ID not enabled, using legacy firmware\n",
- __func__);
- return ld->loader_pdata->fw;
- }
- fws = ld->loader_pdata->fws;
- if (!fws) {
- pt_debug(dev, DL_ERROR,
- "%s: No firmwares provided\n", __func__);
- return NULL;
- }
- /* Find FW according to the Panel ID */
- while ((fw = *fws++)) {
- if (fw->panel_id == panel_id) {
- pt_debug(dev, DL_WARN,
- "%s: Found matching fw:%p with Panel ID: 0x%02X\n",
- __func__, fw, fw->panel_id);
- return fw;
- }
- pt_debug(dev, DL_WARN,
- "%s: Found mismatching fw:%p with Panel ID: 0x%02X\n",
- __func__, fw, fw->panel_id);
- }
- return NULL;
- }
- /*******************************************************************************
- * FUNCTION: upgrade_firmware_from_platform
- *
- * SUMMARY: Get touch_firmware structure and perform upgrade if pass the
- * firmware version check.
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * forced - flag to force upgrade(1:force to upgrade)
- ******************************************************************************/
- static int upgrade_firmware_from_platform(struct device *dev,
- bool forced)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- struct pt_core_data *cd = dev_get_drvdata(dev);
- struct pt_touch_firmware *fw;
- int rc = -ENODEV;
- int upgrade;
- int retry = 3;
- retry_bl:
- if (!ld->loader_pdata) {
- _pt_pip2_update_bl_status(dev, UPDATE_FW_NO_PLATFORM_DATA,
- PT_NO_INC);
- pt_debug(dev, DL_ERROR,
- "%s: No loader platform data\n", __func__);
- return rc;
- }
- fw = pt_get_platform_firmware(dev);
- if (!fw || !fw->img || !fw->size) {
- _pt_pip2_update_bl_status(dev, UPDATE_FW_NO_FW_PROVIDED,
- PT_NO_INC);
- pt_debug(dev, DL_ERROR,
- "%s: No platform firmware\n", __func__);
- return rc;
- }
- if (!fw->ver || !fw->vsize) {
- _pt_pip2_update_bl_status(dev, UPDATE_FW_INVALID_FW_IMAGE,
- PT_NO_INC);
- pt_debug(dev, DL_ERROR, "%s: No platform firmware version\n",
- __func__);
- return rc;
- }
- if (forced)
- upgrade = forced;
- else
- upgrade = pt_check_firmware_version_platform(dev, fw);
- if (upgrade) {
- rc = pt_upgrade_firmware(dev,
- fw->img, fw->size, &update_fw_status);
- /* An extra BL may be needed if default PID was wrong choice */
- if ((cd->panel_id_support & PT_PANEL_ID_BY_SYS_INFO) &&
- !rc && !ld->si && retry--) {
- pt_debug(dev, DL_WARN, "%s: ATM - An extra BL may be needed\n",
- __func__);
- /* Panel_ID coming from sysinfo, ensure we have it */
- ld->si = cmd->request_sysinfo(dev);
- goto retry_bl;
- }
- }
- return rc;
- }
- #endif /* CONFIG_TOUCHSCREEN_PARADE_PLATFORM_FW_UPGRADE */
- #ifdef CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE
- /*******************************************************************************
- * FUNCTION: _pt_pip1_bl_from_file
- *
- * SUMMARY: Wrapper function for _pt_firmware_cont() to perform bl with an
- * image file from userspace.
- *
- * PARAMETERS:
- * *fw - pointer to firmware structure
- * forced - flag to force upgrade(1:force to upgrade)
- ******************************************************************************/
- static int _pt_pip1_bl_from_file(struct device *dev)
- {
- struct pt_core_data *cd = dev_get_drvdata(dev);
- int fw_size = 0;
- int rc = 0;
- u8 *fw_img = NULL;
- u8 header_size = 0;
- _pt_pip2_update_bl_status(dev, UPDATE_FW_IDLE, PT_NO_INC);
- fw_img = kzalloc(PT_PIP2_MAX_FILE_SIZE, GFP_KERNEL);
- if (!fw_img) {
- _pt_pip2_update_bl_status(dev, UPDATE_FW_SYSTEM_NOMEM,
- PT_NO_INC);
- rc = -ENOMEM;
- goto exit;
- }
- rc = cmd->nonhid_cmd->read_us_file(dev, cd->pip2_us_file_path,
- fw_img, &fw_size);
- if (rc) {
- pt_debug(dev, DL_ERROR, "%s: No firmware provided to load\n",
- __func__);
- _pt_pip2_update_bl_status(dev, UPDATE_FW_NO_FW_PROVIDED,
- PT_NO_INC);
- goto exit;
- }
- if (!fw_img || !fw_size) {
- pt_debug(dev, DL_ERROR,
- "%s: No firmware received\n", __func__);
- _pt_pip2_update_bl_status(dev, UPDATE_FW_INVALID_FW_IMAGE,
- PT_NO_INC);
- goto exit;
- }
- header_size = fw_img[0];
- if (header_size >= (fw_size + 1)) {
- pt_debug(dev, DL_ERROR,
- "%s: Firmware format is invalid\n", __func__);
- _pt_pip2_update_bl_status(dev, UPDATE_FW_INVALID_FW_IMAGE,
- PT_NO_INC);
- goto exit;
- }
- pt_upgrade_firmware(dev, &(fw_img[header_size + 1]),
- fw_size - (header_size + 1), &update_fw_status);
- exit:
- kfree(fw_img);
- return rc;
- }
- /*******************************************************************************
- * FUNCTION: _pt_firmware_cont
- *
- * SUMMARY: Firmware upgrade continue function that verifies the firmware size
- * in the firmware class and then upgrades the firmware.
- *
- * PARAMETERS:
- * *fw - pointer to firmware structure
- * forced - flag to force upgrade(1:force to upgrade)
- ******************************************************************************/
- static void _pt_firmware_cont(const struct firmware *fw, void *context)
- {
- struct device *dev = context;
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- u8 header_size = 0;
- _pt_pip2_update_bl_status(dev, UPDATE_FW_IDLE, PT_NO_INC);
- if (!fw) {
- pt_debug(dev, DL_ERROR, "%s: No firmware\n", __func__);
- _pt_pip2_update_bl_status(dev, UPDATE_FW_NO_FW_PROVIDED,
- PT_NO_INC);
- goto pt_firmware_cont_exit;
- }
- if (!fw->data || !fw->size) {
- pt_debug(dev, DL_ERROR,
- "%s: No firmware received\n", __func__);
- _pt_pip2_update_bl_status(dev, UPDATE_FW_INVALID_FW_IMAGE,
- PT_NO_INC);
- goto pt_firmware_cont_release_exit;
- }
- header_size = fw->data[0];
- if (header_size >= (fw->size + 1)) {
- pt_debug(dev, DL_ERROR,
- "%s: Firmware format is invalid\n", __func__);
- _pt_pip2_update_bl_status(dev, UPDATE_FW_INVALID_FW_IMAGE,
- PT_NO_INC);
- goto pt_firmware_cont_release_exit;
- }
- pt_upgrade_firmware(dev, &(fw->data[header_size + 1]),
- fw->size - (header_size + 1), &update_fw_status);
- pt_firmware_cont_release_exit:
- if (fw)
- release_firmware(fw);
- pt_firmware_cont_exit:
- ld->is_manual_upgrade_enabled = 0;
- }
- /*******************************************************************************
- * FUNCTION: pt_check_firmware_config_version
- *
- * SUMMARY: Compare fw's config version with fw image's. If they are differnt
- * report a FW upgrade is needed.
- *
- * RETURN:
- * -1: Do not upgrade firmware
- * 0: Version info same, let caller decide
- * 1: Do a firmware upgrade
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * image_config_ver - Image's firmware config version
- ******************************************************************************/
- static int pt_check_firmware_config_version(struct device *dev,
- u16 image_config_ver)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- u16 fw_config_ver;
- fw_config_ver = ld->si->ttdata.fw_ver_conf;
- pt_debug(dev, DL_WARN,
- "%s: Current config ver:0x%04X New config ver:0x%04X\n",
- __func__, fw_config_ver, image_config_ver);
- if (image_config_ver != fw_config_ver) {
- pt_debug(dev, DL_WARN,
- "%s: Image config ver is different, will upgrade\n",
- __func__);
- return 1;
- }
- if (image_config_ver == fw_config_ver) {
- pt_debug(dev, DL_WARN,
- "%s: Image config ver is the same, will NOT upgrade\n",
- __func__);
- return 0;
- }
- return -EPERM;
- }
- /*******************************************************************************
- * FUNCTION: pt_check_firmware_version_builtin
- *
- * SUMMARY: The caller of function pt_check_firmware_version() to determine
- * whether to load built-in firmware.
- *
- * RETURN:
- * 0: Don't upgrade
- * 1: Upgrade
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *fw - pointer to the firmware structure
- ******************************************************************************/
- static int pt_check_firmware_version_builtin(struct device *dev,
- const struct firmware *fw)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- u16 fw_config_ver_new;
- u32 fw_ver_new;
- u32 fw_revctrl_new;
- int upgrade;
- if (!ld->si) {
- pt_debug(dev, DL_WARN,
- "%s: No firmware info found, DUT FW may be corrupted\n",
- __func__);
- return PT_AUTO_LOAD_FOR_CORRUPTED_FW;
- }
- fw_ver_new = get_unaligned_be16(fw->data + 3);
- /* 4 middle bytes are not used */
- fw_revctrl_new = get_unaligned_be32(fw->data + 9);
- /* Offset 17,18 is the TT Config version*/
- fw_config_ver_new = get_unaligned_be16(fw->data + 17);
- pt_debug(dev, DL_WARN,
- "%s: Built-in FW version=0x%04x rev=%d config=0x%04X\n",
- __func__, fw_ver_new, fw_revctrl_new, fw_config_ver_new);
- upgrade = pt_check_firmware_version(dev, fw_ver_new,
- fw_revctrl_new);
- /* Only check config version if FW version was an exact match */
- if (upgrade == 0)
- upgrade = pt_check_firmware_config_version(dev,
- fw_config_ver_new);
- if (upgrade > 0)
- return 1;
- return 0;
- }
- /*******************************************************************************
- * FUNCTION: _pt_firmware_cont_builtin
- *
- * SUMMARY: Perform upgrade if pass the firmware version check.
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * forced - flag to force upgrade(1:force to upgrade)
- ******************************************************************************/
- static void _pt_firmware_cont_builtin(const struct firmware *fw,
- void *context)
- {
- struct device *dev = context;
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- int upgrade;
- if (!fw) {
- pt_debug(dev, DL_INFO,
- "%s: No builtin firmware\n", __func__);
- goto _pt_firmware_cont_builtin_exit;
- }
- if (!fw->data || !fw->size) {
- pt_debug(dev, DL_ERROR,
- "%s: Invalid builtin firmware\n", __func__);
- goto _pt_firmware_cont_builtin_exit;
- }
- pt_debug(dev, DL_WARN, "%s: Found firmware\n", __func__);
- upgrade = pt_check_firmware_version_builtin(dev, fw);
- if (upgrade) {
- _pt_firmware_cont(fw, dev);
- ld->builtin_bin_fw_status = 0;
- return;
- }
- _pt_firmware_cont_builtin_exit:
- if (fw)
- release_firmware(fw);
- ld->builtin_bin_fw_status = -EINVAL;
- }
- /*******************************************************************************
- * FUNCTION: upgrade_firmware_from_class
- *
- * SUMMARY: Create the firmware class but don't actually load any FW to the
- * DUT. This creates all the sysfs nodes needed for a user to bootload
- * the DUT with their own bin file.
- *
- * RETURN:
- * 0 = success
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- ******************************************************************************/
- static int upgrade_firmware_from_class(struct device *dev)
- {
- int retval;
- pt_debug(dev, DL_INFO,
- "%s: Enabling firmware class loader\n", __func__);
- retval = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
- dev_name(dev), dev, GFP_KERNEL, dev,
- _pt_firmware_cont);
- if (retval < 0) {
- pt_debug(dev, DL_ERROR,
- "%s: Fail request firmware class file load\n",
- __func__);
- return retval;
- }
- return 0;
- }
- #define FILENAME_LEN_MAX 64
- /*******************************************************************************
- * FUNCTION: generate_firmware_filename
- *
- * SUMMARY: Generate firmware file name by panel id. Generates binary FW
- * filename as following:
- * - Panel ID not enabled: tt_fw.bin
- * - Panel ID enabled: tt_fw_pidXX.bin
- *
- * RETURN:
- * pointer to file name or null pointer if fail
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- ******************************************************************************/
- static char *generate_firmware_filename(struct device *dev)
- {
- char *filename;
- u8 panel_id;
- filename = kzalloc(FILENAME_LEN_MAX, GFP_KERNEL);
- if (!filename)
- return NULL;
- panel_id = pt_get_panel_id(dev);
- if (panel_id == PANEL_ID_NOT_ENABLED)
- snprintf(filename, FILENAME_LEN_MAX, "%s", PT_FW_FILE_NAME);
- else
- snprintf(filename, FILENAME_LEN_MAX, "%s_pid%02X%s",
- PT_FW_FILE_PREFIX, panel_id, PT_FW_FILE_SUFFIX);
- pt_debug(dev, DL_INFO, "%s: Filename: %s\n",
- __func__, filename);
- return filename;
- }
- /*******************************************************************************
- * FUNCTION: generate_silicon_id_firmware_filename
- *
- * SUMMARY: Generate firmware file name with the HW version prefix followed by
- * panel id. Generates binary FW filename as following (where XXXX is the
- * silicon ID):
- * - Panel ID not enabled: XXXX_tt_fw.bin
- * - Panel ID enabled: XXXX_tt_fw_pidXX.bin
- *
- * RETURN:
- * pointer to file name or null pointer if fail
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- ******************************************************************************/
- static char *generate_silicon_id_firmware_filename(struct device *dev)
- {
- struct pt_core_data *cd = dev_get_drvdata(dev);
- char *filename;
- char si_id[5] = "DEAD";
- u8 panel_id;
- filename = kzalloc(FILENAME_LEN_MAX, GFP_KERNEL);
- if (!filename)
- return NULL;
- panel_id = pt_get_panel_id(dev);
- memcpy(si_id, cd->hw_version, 4);
- if (panel_id == PANEL_ID_NOT_ENABLED)
- snprintf(filename, FILENAME_LEN_MAX, "%s_%s", si_id,
- PT_FW_FILE_NAME);
- else
- snprintf(filename, FILENAME_LEN_MAX, "%s_%s_pid%02X%s",
- si_id, PT_FW_FILE_PREFIX, panel_id, PT_FW_FILE_SUFFIX);
- pt_debug(dev, DL_INFO, "%s: Filename: %s\n", __func__, filename);
- return filename;
- }
- #define MAX_FILE_NAMES 2
- /*******************************************************************************
- * FUNCTION: upgrade_firmware_from_builtin
- *
- * SUMMARY: Create the firmware class load FW by searching the name of built-in
- * file. Then perform upgrade after getting the file.
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- ******************************************************************************/
- static int upgrade_firmware_from_builtin(struct device *dev)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- struct pt_core_data *cd = dev_get_drvdata(dev);
- char *filename[MAX_FILE_NAMES];
- int index = 0;
- int retval;
- const struct firmware *fw_entry = NULL;
- int retry = 3;
- retry_bl:
- pt_debug(dev, DL_WARN,
- "%s: Enabling firmware class loader built-in\n",
- __func__);
- /* Load the supported file names in the search order */
- /* 0 = Flash file name with optional PID "pt_fw<_PIDX>.bin" */
- filename[0] = generate_firmware_filename(dev);
- if (!filename[0]) {
- pt_debug(dev, DL_ERROR,
- "%s: ERROR - Could not generate filename\n", __func__);
- return -ENOMEM;
- }
- /*
- * 1 = Flash file name with Silicon ID prefix and optional PID
- * "XXXX_pt_fw<_PIDX>.bin"
- */
- filename[1] = generate_silicon_id_firmware_filename(dev);
- if (!filename[1]) {
- pt_debug(dev, DL_ERROR,
- "%s: ERROR - Could not generate filename\n", __func__);
- return -ENOMEM;
- }
- mutex_lock(&cd->firmware_class_lock);
- while (index < MAX_FILE_NAMES) {
- pt_debug(dev, DL_WARN, "%s: Request FW file %s\n", __func__,
- filename[index]);
- #if (KERNEL_VERSION(3, 13, 0) > LINUX_VERSION_CODE)
- retval = request_firmware(&fw_entry, filename[index], dev);
- #else
- retval = request_firmware_direct(&fw_entry,
- filename[index], dev);
- #endif
- if (retval < 0) {
- pt_debug(dev, DL_WARN, "%s: Fail request FW %s load\n",
- __func__, filename[index]);
- } else {
- pt_debug(dev, DL_WARN, "%s: FW %s class file loading\n",
- __func__, filename[index]);
- break;
- }
- index++;
- }
- /* Proceed with the BL if a matching file was found */
- if (index != MAX_FILE_NAMES) {
- _pt_firmware_cont_builtin(fw_entry, dev);
- /* An extra BL may be needed if default PID was wrong choice */
- if ((cd->panel_id_support & PT_PANEL_ID_BY_SYS_INFO) &&
- !ld->si && retry--) {
- pt_debug(dev, DL_WARN, "%s: ATM - An extra BL may be needed\n",
- __func__);
- /* Free allocated memory */
- index = 0;
- while (index < MAX_FILE_NAMES)
- kfree(filename[index++]);
- /* Reset index to 0 */
- index = 0;
- mutex_unlock(&cd->firmware_class_lock);
- /* Panel_ID coming from sysinfo, ensure we have it */
- ld->si = cmd->request_sysinfo(dev);
- goto retry_bl;
- }
- retval = ld->builtin_bin_fw_status;
- }
- index = 0;
- while (index < MAX_FILE_NAMES)
- kfree(filename[index++]);
- mutex_unlock(&cd->firmware_class_lock);
- return retval;
- }
- #endif /* CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE */
- #if PT_TTCONFIG_UPGRADE
- /*******************************************************************************
- * FUNCTION: pt_write_config_row_
- *
- * SUMMARY: Allow to program the data block area that includes configuration
- * data, manufacturing data, design data.
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * ebid - block id to determine the block name(configuration,etc)
- * row_number - row number if written block
- * row_size - row size of written data
- * *data - pointer to the data to write
- ******************************************************************************/
- static int pt_write_config_row_(struct device *dev, u8 ebid,
- u16 row_number, u16 row_size, u8 *data)
- {
- int rc;
- u16 actual_write_len;
- rc = cmd->nonhid_cmd->write_data_block(dev, row_number,
- row_size, ebid, data, (u8 *)pt_data_block_security_key,
- &actual_write_len);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Fail Put EBID=%d row=%d cmd fail r=%d\n",
- __func__, ebid, row_number, rc);
- return rc;
- }
- if (actual_write_len != row_size) {
- pt_debug(dev, DL_ERROR,
- "%s: Fail Put EBID=%d row=%d wrong write size=%d\n",
- __func__, ebid, row_number, actual_write_len);
- rc = -EINVAL;
- }
- return rc;
- }
- /*******************************************************************************
- * FUNCTION: pt_upgrade_ttconfig
- *
- * SUMMARY: Program ttconfig_data with following steps:
- * 1) Suspend scanning
- * 2) Write data to the data block
- * 3) Verify the crc for data block
- * 4) Resume scanning
- * 5) Set up call back for calibration if required
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *ttconfig_data - pointer to the config data to write to data block
- * ttconfig_size - size of config data to write
- ******************************************************************************/
- static int pt_upgrade_ttconfig(struct device *dev,
- const u8 *ttconfig_data, int ttconfig_size)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- bool wait_for_calibration_complete = false;
- u8 ebid = PT_TCH_PARM_EBID;
- u16 row_size = PT_DATA_ROW_SIZE;
- u16 table_size;
- u16 row_count;
- u16 residue;
- u8 *row_buf;
- u8 verify_crc_status;
- u16 calculated_crc;
- u16 stored_crc;
- int rc = 0;
- int i;
- table_size = ttconfig_size;
- row_count = table_size / row_size;
- row_buf = (u8 *)ttconfig_data;
- pt_debug(dev, DL_INFO, "%s: size:%d row_size=%d row_count=%d\n",
- __func__, table_size, row_size, row_count);
- pm_runtime_get_sync(dev);
- rc = cmd->request_exclusive(dev, PT_LDR_REQUEST_EXCLUSIVE_TIMEOUT);
- if (rc < 0)
- goto exit;
- rc = cmd->nonhid_cmd->suspend_scanning(dev, 0);
- if (rc < 0)
- goto release;
- for (i = 0; i < row_count; i++) {
- pt_debug(dev, DL_INFO, "%s: row=%d size=%d\n",
- __func__, i, row_size);
- rc = pt_write_config_row_(dev, ebid, i, row_size,
- row_buf);
- if (rc) {
- pt_debug(dev, DL_ERROR, "%s: Fail put row=%d r=%d\n",
- __func__, i, rc);
- break;
- }
- row_buf += row_size;
- }
- if (!rc) {
- residue = table_size % row_size;
- pt_debug(dev, DL_WARN, "%s: row=%d size=%d\n",
- __func__, i, residue);
- rc = pt_write_config_row_(dev, ebid, i, residue,
- row_buf);
- row_count++;
- if (rc)
- pt_debug(dev, DL_ERROR, "%s: Fail put row=%d r=%d\n",
- __func__, i, rc);
- }
- if (!rc)
- pt_debug(dev, DL_WARN,
- "%s: TT_CFG updated: rows:%d bytes:%d\n",
- __func__, row_count, table_size);
- rc = cmd->nonhid_cmd->verify_cfg_block_crc(dev, 0, ebid,
- &verify_crc_status, &calculated_crc, &stored_crc);
- if (rc || verify_crc_status)
- pt_debug(dev, DL_ERROR,
- "%s: CRC Failed, ebid=%d, status=%d, scrc=%X ccrc=%X\n",
- __func__, ebid, verify_crc_status,
- calculated_crc, stored_crc);
- else
- pt_debug(dev, DL_INFO,
- "%s: CRC PASS, ebid=%d, status=%d, scrc=%X ccrc=%X\n",
- __func__, ebid, verify_crc_status,
- calculated_crc, stored_crc);
- rc = cmd->nonhid_cmd->resume_scanning(dev, 0);
- if (rc < 0)
- goto release;
- if (ld->loader_pdata &&
- (ld->loader_pdata->flags
- & PT_LOADER_FLAG_CALIBRATE_AFTER_TTCONFIG_UPGRADE)) {
- #if (KERNEL_VERSION(3, 13, 0) <= LINUX_VERSION_CODE)
- reinit_completion(&ld->calibration_complete);
- #else
- INIT_COMPLETION(ld->calibration_complete);
- #endif
- /* set up call back for startup */
- pt_debug(dev, DL_INFO, "%s: Adding callback for calibration\n",
- __func__);
- rc = cmd->subscribe_attention(dev, PT_ATTEN_STARTUP,
- PT_LOADER_NAME, pt_calibration_attention, 0);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Failed adding callback for calibration\n",
- __func__);
- pt_debug(dev, DL_ERROR,
- "%s: No calibration will be performed\n",
- __func__);
- rc = 0;
- } else
- wait_for_calibration_complete = true;
- }
- release:
- cmd->release_exclusive(dev);
- exit:
- if (!rc)
- cmd->request_enum(dev, true);
- pm_runtime_put_sync(dev);
- if (wait_for_calibration_complete)
- wait_for_completion(&ld->calibration_complete);
- return rc;
- }
- #endif /* PT_TTCONFIG_UPGRADE */
- #ifdef CONFIG_TOUCHSCREEN_PARADE_PLATFORM_TTCONFIG_UPGRADE
- /*******************************************************************************
- * FUNCTION: pt_get_ttconfig_crc
- *
- * SUMMARY: Get crc from ttconfig data.
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *ttconfig_data - pointer to the config data
- * ttconfig_size - size of config data
- * *crc - pointer to the crc of configure to be stored
- ******************************************************************************/
- static int pt_get_ttconfig_crc(struct device *dev,
- const u8 *ttconfig_data, int ttconfig_size, u16 *crc)
- {
- u16 crc_loc;
- crc_loc = get_unaligned_le16(&ttconfig_data[2]);
- if (ttconfig_size < crc_loc + 2)
- return -EINVAL;
- *crc = get_unaligned_le16(&ttconfig_data[crc_loc]);
- return 0;
- }
- /*******************************************************************************
- * FUNCTION: pt_get_ttconfig_version
- *
- * SUMMARY: Get version number from ttconfig data.
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *ttconfig_data - pointer to the config data
- * ttconfig_size - size of config data
- * *version - pointer to the version of configure to be stored
- ******************************************************************************/
- static int pt_get_ttconfig_version(struct device *dev,
- const u8 *ttconfig_data, int ttconfig_size, u16 *version)
- {
- if (ttconfig_size < PT_TTCONFIG_VERSION_OFFSET
- + PT_TTCONFIG_VERSION_SIZE)
- return -EINVAL;
- *version = get_unaligned_le16(
- &ttconfig_data[PT_TTCONFIG_VERSION_OFFSET]);
- return 0;
- }
- /*******************************************************************************
- * FUNCTION: pt_check_ttconfig_version
- *
- * SUMMARY: Check the configure version and crc value to determine whether to
- * upgrade,the upgrade conditions as following:
- * 1) To upgrade if the config version is newer than current config, but
- * this check is based on the flag in loader plarform data.
- * 2) To upgrade if config CRC is different.
- * 3) Don't upgrade when can't match any of above conditions.
- *
- * RETURN:
- * 0: Don't upgrade
- * 1: Upgrade
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *ttconfig_data - pointer to the config data
- * ttconfig_size - size of config data
- ******************************************************************************/
- static int pt_check_ttconfig_version(struct device *dev,
- const u8 *ttconfig_data, int ttconfig_size)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- u16 cfg_crc_new;
- int rc;
- if (!ld->si)
- return 0;
- /* Check for config version */
- if (ld->loader_pdata->flags &
- PT_LOADER_FLAG_CHECK_TTCONFIG_VERSION) {
- u16 cfg_ver_new;
- rc = pt_get_ttconfig_version(dev, ttconfig_data,
- ttconfig_size, &cfg_ver_new);
- if (rc)
- return 0;
- pt_debug(dev, DL_INFO, "%s: img_ver:0x%04X new_ver:0x%04X\n",
- __func__, ld->si->ttdata.fw_ver_conf, cfg_ver_new);
- /* Check if config version is newer */
- if (cfg_ver_new > ld->si->ttdata.fw_ver_conf) {
- pt_debug(dev, DL_WARN,
- "%s: Config version newer, will upgrade\n", __func__);
- return 1;
- }
- pt_debug(dev, DL_WARN,
- "%s: Config version is identical or older, will NOT upgrade\n",
- __func__);
- /* Check for config CRC */
- } else {
- rc = pt_get_ttconfig_crc(dev, ttconfig_data,
- ttconfig_size, &cfg_crc_new);
- if (rc)
- return 0;
- pt_debug(dev, DL_INFO, "%s: img_crc:0x%04X new_crc:0x%04X\n",
- __func__, ld->si->ttconfig.crc, cfg_crc_new);
- if (cfg_crc_new != ld->si->ttconfig.crc) {
- pt_debug(dev, DL_WARN,
- "%s: Config CRC different, will upgrade\n",
- __func__);
- return 1;
- }
- pt_debug(dev, DL_WARN,
- "%s: Config CRC equal, will NOT upgrade\n", __func__);
- }
- return 0;
- }
- /*******************************************************************************
- * FUNCTION: pt_check_ttconfig_version_platform
- *
- * SUMMARY: To call the function pt_check_ttconfig_version() to determine
- * whether to load config if the firmware version match with current firmware.
- *
- * RETURN:
- * 0: Don't upgrade
- * 1: Upgrade
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *ttconfig - pointer to touch_config structure
- ******************************************************************************/
- static int pt_check_ttconfig_version_platform(struct device *dev,
- struct pt_touch_config *ttconfig)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- u32 fw_ver_config;
- u32 fw_revctrl_config;
- if (!ld->si) {
- pt_debug(dev, DL_INFO,
- "%s: No firmware info found, DUT FW may be corrupted\n",
- __func__);
- return 0;
- }
- fw_ver_config = get_unaligned_be16(ttconfig->fw_ver + 2);
- /* 4 middle bytes are not used */
- fw_revctrl_config = get_unaligned_be32(ttconfig->fw_ver + 8);
- /* FW versions should match */
- if (pt_check_firmware_version(dev, fw_ver_config,
- fw_revctrl_config)) {
- pt_debug(dev, DL_ERROR,
- "%s: FW versions mismatch\n", __func__);
- return 0;
- }
- /* Check PowerOn Self Test, TT_CFG CRC bit */
- if ((ld->si->ttdata.post_code & PT_POST_TT_CFG_CRC_MASK) == 0) {
- pt_debug(dev, DL_ERROR,
- "%s: POST, TT_CFG failed (%X), will upgrade\n",
- __func__, ld->si->ttdata.post_code);
- return 1;
- }
- return pt_check_ttconfig_version(dev, ttconfig->param_regs->data,
- ttconfig->param_regs->size);
- }
- /*******************************************************************************
- * FUNCTION: pt_get_platform_ttconfig
- *
- * SUMMARY: To get the pointer of right touch_config structure by panel id.
- *
- * RETURN:
- * pointer to touch_config structure or null pointer if fail
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- ******************************************************************************/
- static struct pt_touch_config *pt_get_platform_ttconfig(
- struct device *dev)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- struct pt_touch_config **ttconfigs;
- struct pt_touch_config *ttconfig;
- u8 panel_id;
- panel_id = pt_get_panel_id(dev);
- if (panel_id == PANEL_ID_NOT_ENABLED) {
- /* TODO: Make debug message */
- pt_debug(dev, DL_INFO,
- "%s: Panel ID not enabled, using legacy ttconfig\n",
- __func__);
- return ld->loader_pdata->ttconfig;
- }
- ttconfigs = ld->loader_pdata->ttconfigs;
- if (!ttconfigs)
- return NULL;
- /* Find TT config according to the Panel ID */
- while ((ttconfig = *ttconfigs++)) {
- if (ttconfig->panel_id == panel_id) {
- /* TODO: Make debug message */
- pt_debug(dev, DL_INFO,
- "%s: Found matching ttconfig:%p with Panel ID: 0x%02X\n",
- __func__, ttconfig, ttconfig->panel_id);
- return ttconfig;
- }
- pt_debug(dev, DL_ERROR,
- "%s: Found mismatching ttconfig:%p with Panel ID: 0x%02X\n",
- __func__, ttconfig, ttconfig->panel_id);
- }
- return NULL;
- }
- /*******************************************************************************
- * FUNCTION: upgrade_ttconfig_from_platform
- *
- * SUMMARY: Get touch_firmware structure and perform upgrade if pass the
- * firmware version check.
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * forced - flag to force upgrade(1:force to upgrade)
- ******************************************************************************/
- static int upgrade_ttconfig_from_platform(struct device *dev)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- struct pt_touch_config *ttconfig;
- struct touch_settings *param_regs;
- int rc = -ENODEV;
- int upgrade;
- if (!ld->loader_pdata) {
- pt_debug(dev, DL_ERROR,
- "%s: No loader platform data\n", __func__);
- return rc;
- }
- ttconfig = pt_get_platform_ttconfig(dev);
- if (!ttconfig) {
- pt_debug(dev, DL_ERROR, "%s: No ttconfig data\n", __func__);
- return rc;
- }
- param_regs = ttconfig->param_regs;
- if (!param_regs) {
- pt_debug(dev, DL_ERROR, "%s: No touch parameters\n",
- __func__);
- return rc;
- }
- if (!param_regs->data || !param_regs->size) {
- pt_debug(dev, DL_ERROR,
- "%s: Invalid touch parameters\n", __func__);
- return rc;
- }
- if (!ttconfig->fw_ver || !ttconfig->fw_vsize) {
- pt_debug(dev, DL_ERROR,
- "%s: Invalid FW version for touch parameters\n",
- __func__);
- return rc;
- }
- upgrade = pt_check_ttconfig_version_platform(dev, ttconfig);
- if (upgrade)
- return pt_upgrade_ttconfig(dev, param_regs->data,
- param_regs->size);
- return rc;
- }
- #endif /* CONFIG_TOUCHSCREEN_PARADE_PLATFORM_TTCONFIG_UPGRADE */
- #ifdef CONFIG_TOUCHSCREEN_PARADE_MANUAL_TTCONFIG_UPGRADE
- /*******************************************************************************
- * FUNCTION: pt_config_data_write
- *
- * SUMMARY: The write method for the config_data sysfs node. The passed
- * in data (config file) is written to the config_data buffer.
- *
- * RETURN: Size of passed in buffer is success
- *
- * PARAMETERS:
- * *filp - pointer to file structure
- * *kobj - pointer to kobject structure
- * *bin_attr - pointer to bin_attribute structure
- * buf - pointer to cmd input buffer
- * offset - offset index to store input buffer
- * count - size of data in buffer
- ******************************************************************************/
- static ssize_t pt_config_data_write(struct file *filp,
- struct kobject *kobj, struct bin_attribute *bin_attr,
- char *buf, loff_t offset, size_t count)
- {
- struct device *dev = container_of(kobj, struct device, kobj);
- struct pt_loader_data *data = pt_get_loader_data(dev);
- u8 *p;
- pt_debug(dev, DL_INFO, "%s: offset:%lld count:%zu\n",
- __func__, offset, count);
- mutex_lock(&data->config_lock);
- if (!data->config_loading) {
- mutex_unlock(&data->config_lock);
- return -ENODEV;
- }
- p = krealloc(data->config_data, offset + count, GFP_KERNEL);
- if (!p) {
- kfree(data->config_data);
- data->config_data = NULL;
- mutex_unlock(&data->config_lock);
- return -ENOMEM;
- }
- data->config_data = p;
- memcpy(&data->config_data[offset], buf, count);
- data->config_size += count;
- mutex_unlock(&data->config_lock);
- return count;
- }
- static struct bin_attribute bin_attr_config_data = {
- .attr = {
- .name = "config_data",
- .mode = 0200,
- },
- .size = 0,
- .write = pt_config_data_write,
- };
- /*******************************************************************************
- * FUNCTION: pt_verify_ttconfig_binary
- *
- * SUMMARY: Perform a simple size check if the firmware version match.And
- * calculate the start pointer of config data to write and the size to write.
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *bin_config_data - pointer to binary config data
- * bin_config_size - size of binary config data
- * **start - double pointer to config data where to be written
- * *len - pointer to the size of config data to store
- ******************************************************************************/
- static int pt_verify_ttconfig_binary(struct device *dev,
- u8 *bin_config_data, int bin_config_size, u8 **start, int *len)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- int header_size;
- u16 config_size;
- u32 fw_ver_config;
- u32 fw_revctrl_config;
- if (!ld->si) {
- pt_debug(dev, DL_ERROR,
- "%s: No firmware info found, DUT FW may be corrupted\n",
- __func__);
- return -ENODEV;
- }
- /*
- * We need 11 bytes for FW version control info and at
- * least 6 bytes in config (Length + Max Length + CRC)
- */
- header_size = bin_config_data[0] + 1;
- if (header_size < 11 || header_size >= bin_config_size - 6) {
- pt_debug(dev, DL_ERROR,
- "%s: Invalid header size %d\n", __func__,
- header_size);
- return -EINVAL;
- }
- fw_ver_config = get_unaligned_be16(&bin_config_data[1]);
- /* 4 middle bytes are not used */
- fw_revctrl_config = get_unaligned_be32(&bin_config_data[7]);
- /* FW versions should match */
- if (pt_check_firmware_version(dev, fw_ver_config,
- fw_revctrl_config)) {
- pt_debug(dev, DL_ERROR,
- "%s: FW versions mismatch\n", __func__);
- return -EINVAL;
- }
- config_size = get_unaligned_le16(&bin_config_data[header_size]);
- /* Perform a simple size check (2 bytes for CRC) */
- if (config_size != bin_config_size - header_size - 2) {
- pt_debug(dev, DL_ERROR,
- "%s: Config size invalid\n", __func__);
- return -EINVAL;
- }
- *start = &bin_config_data[header_size];
- *len = bin_config_size - header_size;
- return 0;
- }
- /*
- * 1: Start loading TT Config
- * 0: End loading TT Config and perform upgrade
- *-1: Exit loading
- */
- /*******************************************************************************
- * FUNCTION: pt_config_loading_store
- *
- * SUMMARY: The store method for the config_loading sysfs node. The
- * passed in value controls if config loading is performed.
- *
- * RETURN: Size of passed in buffer is success
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *attr - pointer to device attributes
- * *buf - pointer to buffer that hold the command parameters
- * size - size of buf
- ******************************************************************************/
- static ssize_t pt_config_loading_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- long value;
- u8 *start;
- int length;
- int rc;
- rc = kstrtol(buf, 10, &value);
- if (rc < 0 || value < -1 || value > 1) {
- pt_debug(dev, DL_ERROR, "%s: Invalid value\n", __func__);
- return size;
- }
- mutex_lock(&ld->config_lock);
- if (value == 1)
- ld->config_loading = true;
- else if (value == -1)
- ld->config_loading = false;
- else if (value == 0 && ld->config_loading) {
- ld->config_loading = false;
- if (ld->config_size == 0) {
- pt_debug(dev, DL_ERROR,
- "%s: No config data\n", __func__);
- goto exit_free;
- }
- rc = pt_verify_ttconfig_binary(dev,
- ld->config_data, ld->config_size,
- &start, &length);
- if (rc)
- goto exit_free;
- rc = pt_upgrade_ttconfig(dev, start, length);
- }
- exit_free:
- kfree(ld->config_data);
- ld->config_data = NULL;
- ld->config_size = 0;
- mutex_unlock(&ld->config_lock);
- if (rc)
- return rc;
- return size;
- }
- static DEVICE_ATTR(config_loading, 0200,
- NULL, pt_config_loading_store);
- #endif /* CONFIG_TOUCHSCREEN_PARADE_MANUAL_TTCONFIG_UPGRADE */
- #ifdef CONFIG_TOUCHSCREEN_PARADE_PLATFORM_FW_UPGRADE
- /*******************************************************************************
- * FUNCTION: pt_forced_upgrade_store
- *
- * SUMMARY: The store method for the forced_upgrade sysfs node. The firmware
- * loading is forced to performed with platform upgrade strategy.
- *
- * RETURN: Size of passed in buffer is success
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *attr - pointer to device attributes
- * *buf - pointer to buffer that hold the command parameters
- * size - size of buf
- ******************************************************************************/
- static ssize_t pt_forced_upgrade_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
- {
- int rc = upgrade_firmware_from_platform(dev, true);
- if (rc)
- return rc;
- return size;
- }
- static DEVICE_ATTR(forced_upgrade, 0200,
- NULL, pt_forced_upgrade_store);
- #endif
- #ifdef CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE
- /*******************************************************************************
- * FUNCTION: pt_manual_upgrade_store
- *
- * SUMMARY: The store method for the forced_upgrade sysfs node that it is
- * caller for function upgrade_firmware_from_class() to allow upgrade firmware
- * manually.
- *
- * RETURN: Size of passed in buffer is success
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *attr - pointer to device attributes
- * *buf - pointer to buffer that hold the command parameters
- * size - size of buf
- ******************************************************************************/
- static ssize_t pt_manual_upgrade_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- u32 input_data[2] = {0};
- int length;
- int rc = 0;
- length = cmd->parse_sysfs_input(dev, buf, size, input_data,
- ARRAY_SIZE(input_data));
- if (length != 1) {
- pt_debug(dev, DL_WARN, "%s: Invalid number of arguments\n",
- __func__);
- rc = -EINVAL;
- goto exit;
- }
- if (input_data[0] < 0 || input_data[0] > 1) {
- pt_debug(dev, DL_WARN, "%s: Invalid arguments\n", __func__);
- rc = -EINVAL;
- goto exit;
- }
- _pt_pip2_update_bl_status(dev, UPDATE_FW_IDLE, PT_NO_INC);
- if (ld->is_manual_upgrade_enabled) {
- rc = -EBUSY;
- goto exit;
- }
- ld->is_manual_upgrade_enabled = 1;
- rc = upgrade_firmware_from_class(ld->dev);
- if (rc < 0)
- ld->is_manual_upgrade_enabled = 0;
- exit:
- if (rc)
- return rc;
- return size;
- }
- static DEVICE_ATTR(manual_upgrade, 0200, NULL, pt_manual_upgrade_store);
- #endif /* CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE */
- /*******************************************************************************
- * FUNCTION: pt_fw_and_config_upgrade
- *
- * SUMMARY: Perform all methods for firmware upgrade and config upgrade
- * according to the definition of macro.
- *
- * PARAMETERS:
- * *work_struct - pointer to work_struct structure
- ******************************************************************************/
- static void pt_fw_and_config_upgrade(
- struct work_struct *fw_and_config_upgrade)
- {
- struct pt_loader_data *ld = container_of(fw_and_config_upgrade,
- struct pt_loader_data, fw_and_config_upgrade);
- struct device *dev = ld->dev;
- struct pt_core_data *cd = dev_get_drvdata(dev);
- int retry = 200;
- #if PT_FW_UPGRADE \
- || defined(CONFIG_TOUCHSCREEN_PARADE_PLATFORM_TTCONFIG_UPGRADE)
- u8 dut_gen = cmd->request_dut_generation(dev);
- #endif
- /*
- * Since the resume_scan command in pt_probe_complete() has
- * no protection,it may cause problem for the commands in fw
- * upgrade process during probe. Waiting for the probe to
- * complete before performing fw upgrade can avoid this failure.
- */
- while (!cd->core_probe_complete && retry--)
- msleep(20);
- ld->si = cmd->request_sysinfo(dev);
- if (!ld->si)
- pt_debug(dev, DL_ERROR,
- "%s: Fail get sysinfo pointer from core\n",
- __func__);
- #if !PT_FW_UPGRADE
- pt_debug(dev, DL_INFO,
- "%s: No FW upgrade method selected!\n", __func__);
- #endif
- #ifdef CONFIG_TOUCHSCREEN_PARADE_PLATFORM_FW_UPGRADE
- if (dut_gen == DUT_PIP1_ONLY) {
- if (!upgrade_firmware_from_platform(dev, false))
- return;
- }
- #endif
- #ifdef CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE
- if (dut_gen == DUT_PIP2_CAPABLE) {
- if (!pt_pip2_upgrade_firmware_from_builtin(dev))
- return;
- pt_debug(dev, DL_WARN, "%s: Builtin FW upgrade failed\n",
- __func__);
- } else {
- if (!upgrade_firmware_from_builtin(dev))
- return;
- }
- #endif
- #ifdef CONFIG_TOUCHSCREEN_PARADE_PLATFORM_TTCONFIG_UPGRADE
- if (dut_gen == DUT_PIP1_ONLY) {
- if (!upgrade_ttconfig_from_platform(dev))
- return;
- }
- #endif
- }
- #ifdef CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE
- #ifdef TTDL_DIAGNOSTICS
- /*******************************************************************************
- * FUNCTION: _pt_pip2_get_flash_info
- *
- * SUMMARY: Sends a FLASH_INFO command to the DUT logging the results to kmsg
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *read_buf - pointer to the read buffer array to store the response
- ******************************************************************************/
- static void _pt_pip2_get_flash_info(struct device *dev,
- u8 *read_buf)
- {
- u16 actual_read_len;
- int ret;
- /* Get flash info for debugging information */
- ret = cmd->nonhid_cmd->pip2_send_cmd(dev,
- PT_CORE_CMD_UNPROTECTED, PIP2_CMD_ID_FLASH_INFO,
- NULL, 0, read_buf, &actual_read_len);
- if (!ret) {
- pt_debug(dev, DL_DEBUG,
- "%s --- FLASH Information ---\n", __func__);
- pt_debug(dev, DL_DEBUG,
- "%s Manufacturer ID: 0x%02x\n",
- __func__, read_buf[PIP2_RESP_BODY_OFFSET]);
- pt_debug(dev, DL_DEBUG,
- "%s Memory Type : 0x%02x\n",
- __func__, read_buf[PIP2_RESP_BODY_OFFSET + 1]);
- pt_debug(dev, DL_DEBUG,
- "%s Num Sectors : 0x%02x%02x%02x%02x\n",
- __func__, read_buf[PIP2_RESP_BODY_OFFSET + 2],
- read_buf[PIP2_RESP_BODY_OFFSET + 3],
- read_buf[PIP2_RESP_BODY_OFFSET + 4],
- read_buf[PIP2_RESP_BODY_OFFSET + 5]);
- pt_debug(dev, DL_DEBUG,
- "%s Sectors Size : 0x%02x%02x%02x%02x\n",
- __func__, read_buf[PIP2_RESP_BODY_OFFSET + 6],
- read_buf[PIP2_RESP_BODY_OFFSET + 7],
- read_buf[PIP2_RESP_BODY_OFFSET + 8],
- read_buf[PIP2_RESP_BODY_OFFSET + 9]);
- pt_debug(dev, DL_DEBUG,
- "%s Page Size : 0x%02x%02x%02x%02x\n",
- __func__, read_buf[PIP2_RESP_BODY_OFFSET + 10],
- read_buf[PIP2_RESP_BODY_OFFSET + 11],
- read_buf[PIP2_RESP_BODY_OFFSET + 12],
- read_buf[PIP2_RESP_BODY_OFFSET + 13]);
- if (actual_read_len > 21) {
- pt_debug(dev, DL_DEBUG,
- "%s Status Reg1 : 0x%02x\n",
- __func__,
- read_buf[PIP2_RESP_BODY_OFFSET + 14]);
- pt_debug(dev, DL_DEBUG,
- "%s Status Reg2 : 0x%02x\n",
- __func__,
- read_buf[PIP2_RESP_BODY_OFFSET + 15]);
- }
- }
- }
- #endif /* TTDL_DIAGNOSTICS */
- /*******************************************************************************
- * FUNCTION: _pt_pip2_log_last_error
- *
- * SUMMARY: Sends a STATUS command to the DUT logging the results until all
- * errors are cleared. Also sends a GET_LAST_ERRNO to get any Boot errors.
- * This must be sent after the STATUS flush in order not to have this
- * command cause another error.
- *
- * NOTE: This function support No Interrupt Solution and switch "pip2_send_cmd"
- * function according to the global variable "bl_with_no_int".
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *read_buf - pointer to the read buffer array to store the response
- ******************************************************************************/
- static int _pt_pip2_log_last_error(struct device *dev,
- u8 *read_buf)
- {
- u16 actual_read_len;
- u8 loop = 5;
- u8 info = 0xFF;
- u8 error = 0xFF;
- int ret;
- PIP2_SEND_CMD pip2_send_cmd;
- struct pt_core_data *cd = dev_get_drvdata(dev);
- if (cd->bl_with_no_int)
- pip2_send_cmd = cmd->nonhid_cmd->pip2_send_cmd_no_int;
- else
- pip2_send_cmd = cmd->nonhid_cmd->pip2_send_cmd;
- /*
- * Send the STATUS command until no errors are found.
- * The BL will store an error code for each layer of the stack,
- * and each read will return one error.
- */
- while (loop > 0 && error) {
- ret = pip2_send_cmd(dev,
- PT_CORE_CMD_UNPROTECTED, PIP2_CMD_ID_STATUS,
- NULL, 0, read_buf, &actual_read_len);
- if (!ret) {
- info = (u8)read_buf[PIP2_RESP_BODY_OFFSET];
- error = (u8)read_buf[PIP2_RESP_BODY_OFFSET + 1];
- pt_debug(dev, DL_ERROR,
- "%s: STATUS: Status=0x%02X BOOT=%d BUSY=%d INT=%d ERR_PHY=%d ERR_REG=%d ERROR=0x%02X",
- __func__,
- (u8)read_buf[PIP2_RESP_STATUS_OFFSET],
- info & 0x01,
- (info & 0x02) >> 1,
- (info & 0x04) >> 2,
- (info & 0x18) >> 3,
- (info & 0xE0) >> 5,
- error);
- }
- loop--;
- }
- /* Send the GET_LAST_ERROR command to get the last BL startup error */
- ret = pip2_send_cmd(dev,
- PT_CORE_CMD_UNPROTECTED, PIP2_CMD_ID_GET_LAST_ERRNO,
- NULL, 0, read_buf, &actual_read_len);
- if (!ret) {
- pt_debug(dev, DL_ERROR,
- "%s: GET_LAST_ERR: Status=0x%02X ERRNO=0x%02X BOOTMODE=%d\n",
- __func__,
- (u8)read_buf[PIP2_RESP_STATUS_OFFSET],
- (u8)read_buf[PIP2_RESP_BODY_OFFSET],
- (u8)read_buf[PIP2_RESP_BODY_OFFSET + 1]);
- }
- return ret;
- }
- /*******************************************************************************
- * FUNCTION: _pt_pip2_check_fw_ver
- *
- * SUMMARY: Compare the FW version in the bin file to the current FW. If the
- * FW version in the bin file is greater an upgrade should be done.
- *
- * RETURN:
- * -1: Do not upgrade firmware
- * 0: Version info same, let caller decide
- * 1: Do a firmware upgrade
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *fw - pointer to the new FW image to load
- * *hdr - pointer to the PIP2 bin file hdr structure
- ******************************************************************************/
- static int _pt_pip2_check_fw_ver(struct device *dev,
- const struct firmware *fw, struct pt_bin_file_hdr *hdr)
- {
- u8 img_app_major_ver = fw->data[3];
- u8 img_app_minor_ver = fw->data[4];
- u32 img_app_rev_ctrl = fw->data[9]<<24 | fw->data[10]<<16 |
- fw->data[11]<<8 | fw->data[12];
- pt_debug(dev, DL_WARN,
- "%s ATM - BL Image Version: %02x.%02x.%d\n",
- __func__, img_app_major_ver, img_app_minor_ver,
- img_app_rev_ctrl);
- pt_debug(dev, DL_WARN,
- "%s ATM - Current FW Version: %02X.%02X.%d\n",
- __func__, hdr->fw_major, hdr->fw_minor, hdr->fw_rev_ctrl);
- if ((256 * img_app_major_ver + img_app_minor_ver) >
- (256 * hdr->fw_major + hdr->fw_minor)) {
- pt_debug(dev, DL_WARN,
- "ATM - bin file version > FW, will upgrade FW");
- return 1;
- }
- if ((256 * img_app_major_ver + img_app_minor_ver) <
- (256 * hdr->fw_major + hdr->fw_minor)) {
- pt_debug(dev, DL_WARN,
- "ATM - bin file version < FW, will NOT upgrade FW");
- return -EPERM;
- }
- if (img_app_rev_ctrl > hdr->fw_rev_ctrl) {
- pt_debug(dev, DL_WARN,
- "bin file rev ctrl > FW, will upgrade FW");
- return 1;
- }
- if (img_app_rev_ctrl < hdr->fw_rev_ctrl) {
- pt_debug(dev, DL_WARN,
- "bin file rev ctrl > FW, will NOT upgrade FW");
- return -EPERM;
- }
- return 0;
- }
- /*******************************************************************************
- * FUNCTION: _pt_pip2_check_config_ver
- *
- * SUMMARY: Compare the Config version in the bin file to the current FW. If the
- * config version in the bin file is greater an upgrade should be done.
- *
- * RETURN:
- * -1: Do not upgrade firmware
- * 0: Version info same, let caller decide
- * 1: Do a firmware upgrade
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *fw - pointer to the new FW image to load
- * *hdr - pointer to the PIP2 bin file hdr structure
- ******************************************************************************/
- static int _pt_pip2_check_config_ver(struct device *dev,
- const struct firmware *fw, struct pt_bin_file_hdr *hdr)
- {
- u16 fw_config_ver_new;
- /* Offset 17,18 is the TT Config version*/
- fw_config_ver_new = get_unaligned_be16(fw->data + 17);
- pt_debug(dev, DL_WARN,
- "%s ATM - BL Image Config Version: %d\n",
- __func__, fw_config_ver_new);
- pt_debug(dev, DL_WARN,
- "%s ATM - Current Config Version: %d\n",
- __func__, hdr->config_ver);
- if (fw_config_ver_new > hdr->config_ver) {
- pt_debug(dev, DL_WARN,
- "ATM - bin file Config version > FW, will upgrade FW");
- return 1;
- } else
- pt_debug(dev, DL_WARN,
- "ATM - bin file Config version <= FW, will NOT upgrade FW");
- return 0;
- }
- /*******************************************************************************
- * FUNCTION: _pt_pip2_need_upgrade_due_to_fw_ver
- *
- * SUMMARY: Compare the FW version in the bin file to the current FW. If the
- * FW version in the bin file is greater an upgrade should be done.
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *fw - pointer to the new FW image to load
- ******************************************************************************/
- static u8 _pt_pip2_need_upgrade_due_to_fw_ver(struct device *dev,
- const struct firmware *fw)
- {
- int ret;
- u8 should_upgrade = 0;
- struct pt_bin_file_hdr hdr = {0};
- ret = cmd->request_pip2_bin_hdr(dev, &hdr);
- if (ret != 0 || hdr.fw_major == 0xFF) {
- pt_debug(dev, DL_WARN,
- "App ver info not available, will upgrade FW");
- should_upgrade = 1;
- goto exit;
- }
- ret = _pt_pip2_check_fw_ver(dev, fw, &hdr);
- if (ret == 0)
- ret = _pt_pip2_check_config_ver(dev, fw, &hdr);
- if (ret > 0)
- should_upgrade = 1;
- exit:
- return should_upgrade;
- }
- /*******************************************************************************
- * FUNCTION: _pt_calibrate_flashless_dut
- *
- * SUMMARY: On a flashless DUT the FW would need to re-calibrate on every power
- * cycle, so to speed up the BL process the FW does the calibraiton on the
- * first power up and TTDL will read and store it in RAM to be able to
- * restore it on subsequent resets of the DUT.
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- ******************************************************************************/
- static int _pt_calibrate_flashless_dut(struct device *dev)
- {
- u8 rc = 0;
- u8 cal_status = 1;
- u16 cal_size = 0;
- struct pt_cal_ext_data cal_data = {0};
- struct pt_core_data *cd = dev_get_drvdata(dev);
- struct pt_ttdata *ttdata = &cd->sysinfo.ttdata;
- unsigned short cache_chip_id = 0;
- unsigned short active_chip_id = 0;
- cmd->nonhid_cmd->manage_cal_data(dev, PT_CAL_DATA_INFO, &cal_size,
- &cache_chip_id);
- pt_debug(dev, DL_WARN, "%s: Stored CAL ID=0x%04X size=%d\n",
- __func__, cache_chip_id, cal_size);
- active_chip_id = cmd->nonhid_cmd->calc_crc((u8 *)&ttdata->chip_rev,
- 4 + PT_UID_SIZE);
- pt_debug(dev, DL_WARN, "%s: Current Chip ID=0x%04X\n",
- __func__, active_chip_id);
- if (cal_size == 0 || active_chip_id != cache_chip_id) {
- memset(&cal_data, 0, sizeof(struct pt_cal_ext_data));
- /* Calibrate_ext will also save CAL Data in TTDL cache */
- rc = cmd->nonhid_cmd->calibrate_ext(dev, 0, &cal_data,
- &cal_status);
- pt_debug(dev, DL_INFO,
- "%s: Calibration Finished rc=%d\n", __func__, rc);
- /* Afer successful calibration read the stored size */
- if (!rc && cal_status == 0) {
- rc = cmd->nonhid_cmd->manage_cal_data(dev,
- PT_CAL_DATA_INFO, &cal_size, &cache_chip_id);
- if (!rc) {
- pt_debug(dev, DL_WARN,
- "%s: First BL, Read %d Bytes of CAL\n",
- __func__, cal_size);
- } else {
- pt_debug(dev, DL_ERROR,
- "%s: First BL, Failed to read CAL\n",
- __func__);
- }
- } else {
- pt_debug(dev, DL_ERROR,
- "%s: First BL, Calibration failed rc=%d\n",
- __func__, rc);
- }
- rc = cmd->nonhid_cmd->resume_scanning(dev, 0);
- if (rc)
- pt_debug(dev, DL_ERROR,
- "%s: First BL, Resume Scan failed rc=%d\n",
- __func__, rc);
- } else {
- rc = cmd->nonhid_cmd->manage_cal_data(dev, PT_CAL_DATA_RESTORE,
- &cal_size, &cache_chip_id);
- if (!rc)
- pt_debug(dev, DL_WARN, "%s: Restored CAL %d Bytes\n",
- __func__, cal_size);
- else
- pt_debug(dev, DL_ERROR, "%s: Failed to restore CAL\n",
- __func__);
- rc = cmd->nonhid_cmd->resume_scanning(dev, 0);
- if (rc)
- pt_debug(dev, DL_ERROR,
- "%s: Resume Scan failed rc=%d\n",
- __func__, rc);
- }
- return rc;
- }
- /*******************************************************************************
- * FUNCTION: _pt_pip2_firmware_cont
- *
- * SUMMARY: Bootload the DUT with a FW image using the PIP2 protocol. This
- * includes getting the DUT into BL mode, writing the file to either SRAM
- * or FLASH, and launching the application directly in SRAM or by resetting
- * the DUT without the hostmode pin asserted.
- *
- * NOTE: Special care must be taken to support a DUT communicating in
- * PIP2.0 where the length field is defined differently.
- * NOTE: The write packet len is set so that the overall packet size is
- * less than 255. The overhead is 9 bytes: 2 byte address (0101),
- * 4 byte header, 1 byte file no. 2 byte CRC
- *
- * PARAMETERS:
- * *fw - pointer to the new FW image to load
- * *context - pointer to the device
- ******************************************************************************/
- static void _pt_pip2_firmware_cont(const struct firmware *fw,
- void *context)
- {
- u8 read_buf[PT_MAX_PIP2_MSG_SIZE];
- u8 buf[PT_MAX_PIP2_MSG_SIZE];
- u8 *fw_img = NULL;
- u16 write_len;
- u8 mode = PT_MODE_UNKNOWN;
- u8 retry_packet = 0;
- u8 us_fw_used = 0;
- u16 actual_read_len;
- u16 status = 0;
- u16 packet_size;
- int fw_size = 0;
- int remain_bytes;
- int ret = 0;
- int percent_cmplt;
- int t;
- int erase_status;
- u32 max_file_size;
- bool wait_for_calibration_complete = false;
- PIP2_SEND_CMD pip2_send_cmd;
- struct device *dev = context;
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- struct pip2_loader_data *pip2_data = ld->pip2_data;
- struct pt_core_data *cd = dev_get_drvdata(dev);
- pt_debug(dev, DL_WARN, "%s: ATM - Begin BL\n", __func__);
- _pt_pip2_update_bl_status(dev, UPDATE_FW_IDLE, PT_NO_INC);
- if (cd->bus_ops->bustype == BUS_I2C)
- packet_size = PIP2_BL_I2C_FILE_WRITE_LEN_PER_PACKET;
- else
- packet_size = PIP2_BL_SPI_FILE_WRITE_LEN_PER_PACKET;
- ret = cmd->request_exclusive(dev, PT_LDR_REQUEST_EXCLUSIVE_TIMEOUT);
- if (ret < 0) {
- pt_debug(dev, DL_ERROR,
- "%s: Failed to aquire exclusive access\n", __func__);
- update_fw_status = UPDATE_FW_EXCLUSIVE_ACCESS_ERROR;
- goto exit;
- }
- _pt_pip2_update_bl_status(dev, 0, 1);
- if (!fw) {
- if (ld->pip2_load_builtin) {
- pt_debug(dev, DL_ERROR,
- "%s: No builtin firmware\n", __func__);
- ld->builtin_bin_fw_status = -EINVAL;
- pt_debug(dev, DL_ERROR, "%s: Exit BL\n", __func__);
- _pt_pip2_update_bl_status(dev,
- UPDATE_FW_NO_FW_PROVIDED, PT_NO_INC);
- goto exit;
- } else {
- fw_img = kzalloc(PT_PIP2_MAX_FILE_SIZE, GFP_KERNEL);
- us_fw_used = 1;
- ret = cmd->nonhid_cmd->read_us_file(dev,
- cd->pip2_us_file_path, fw_img, &fw_size);
- if (ret) {
- pt_debug(dev, DL_ERROR,
- "%s: No firmware provided to load\n",
- __func__);
- pt_debug(dev, DL_ERROR, "%s: Exit BL\n",
- __func__);
- _pt_pip2_update_bl_status(dev,
- UPDATE_FW_NO_FW_PROVIDED, PT_NO_INC);
- goto exit;
- }
- }
- } else {
- fw_img = (u8 *)&(fw->data[0]);
- fw_size = fw->size;
- }
- if (!fw_img || !fw_size) {
- pt_debug(dev, DL_ERROR,
- "%s: Invalid fw or file size=%d\n", __func__,
- (int)fw_size);
- _pt_pip2_update_bl_status(dev, UPDATE_FW_INVALID_FW_IMAGE,
- PT_NO_INC);
- goto exit;
- }
- if (ld->pip2_load_file_no == PIP2_FW_FILE) {
- if (fw_img[0] >= (fw_size + 1)) {
- pt_debug(dev, DL_ERROR,
- "%s: Firmware format is invalid\n", __func__);
- _pt_pip2_update_bl_status(dev,
- UPDATE_FW_INVALID_FW_IMAGE, PT_NO_INC);
- goto exit;
- }
- }
- cd->fw_updating = true;
- wake_up(&cd->wait_q);
- _pt_pip2_update_bl_status(dev, 0, 1);
- pt_debug(dev, DL_INFO,
- "%s: Found file of size: %d bytes\n", __func__, (int)fw_size);
- pm_runtime_get_sync(dev);
- _pt_pip2_update_bl_status(dev, 0, 1);
- /* Wait for completion of FW upgrade thread before continuing */
- if (!ld->pip2_load_builtin)
- init_completion(&pip2_data->pip2_fw_upgrade_complete);
- _pt_pip2_update_bl_status(dev, 0, 1);
- cmd->request_stop_wd(dev);
- if (cd->flashless_dut) {
- cd->bl_pip_ver_ready = false;
- cd->app_pip_ver_ready = false;
- }
- /*
- * 'mode' is used below, if DUT was already in BL before attempting to
- * enter the BL, there was either no FW to run or the FW was corrupt
- * so either way force a BL
- */
- ret = cmd->request_pip2_enter_bl(dev, &mode, NULL);
- if (ret) {
- pt_debug(dev, DL_ERROR, "%s: Failed to enter BL\n",
- __func__);
- _pt_pip2_update_bl_status(dev, UPDATE_FW_ENTER_BL_ERROR,
- PT_NO_INC);
- goto exit;
- }
- _pt_pip2_update_bl_status(dev, 0, 1);
- /* Only compare FW ver or previous mode when doing a built-in upgrade */
- if (ld->pip2_load_builtin) {
- if (_pt_pip2_need_upgrade_due_to_fw_ver(dev, fw) ||
- mode == PT_MODE_BOOTLOADER) {
- _pt_pip2_update_bl_status(dev, 0, 1);
- } else {
- _pt_pip2_update_bl_status(dev,
- UPDATE_FW_VERSION_ERROR, PT_NO_INC);
- goto exit;
- }
- }
- pt_debug(dev, DL_INFO, "%s OPEN File %d for write\n",
- __func__, ld->pip2_load_file_no);
- ret = cmd->nonhid_cmd->pip2_file_open(dev, ld->pip2_load_file_no);
- if (ret < 0) {
- pt_debug(dev, DL_ERROR, "%s Open file %d failed\n",
- __func__, ld->pip2_load_file_no);
- _pt_pip2_update_bl_status(dev, UPDATE_FW_FILE_OPEN_ERROR,
- PT_NO_INC);
- goto exit;
- }
- pip2_data->pip2_file_handle = ret;
- _pt_pip2_update_bl_status(dev, 0, 1);
- /* Regarding to TC3315, the size of RAM_FILE is less than fw image */
- if (ld->pip2_load_file_no != PIP2_RAM_FILE) {
- ret = cmd->nonhid_cmd->pip2_file_get_stats(dev,
- ld->pip2_load_file_no, NULL, &max_file_size);
- if (ret) {
- pt_debug(dev, DL_ERROR,
- "%s: Failed to get_file_state ret=%d\n",
- __func__, ret);
- goto exit_close_file;
- }
- if (fw_size > max_file_size) {
- pt_debug(dev, DL_ERROR,
- "%s: Firmware image(%d) is over size(%d)\n",
- __func__, fw_size, max_file_size);
- _pt_pip2_update_bl_status(dev,
- UPDATE_FW_INVALID_FW_IMAGE, PT_NO_INC);
- goto exit_close_file;
- }
- #ifdef TTDL_DIAGNOSTICS
- /* Log the Flash part info */
- if (cd->debug_level >= DL_DEBUG)
- _pt_pip2_get_flash_info(dev, read_buf);
- #endif
- /* Erase file before loading */
- ret = cmd->nonhid_cmd->pip2_file_erase(dev,
- ld->pip2_load_file_no, &erase_status);
- if (ret < 0) {
- pt_debug(dev, DL_ERROR,
- "%s: File erase failed rc=%d status=%d\n",
- __func__, ret, erase_status);
- _pt_pip2_update_bl_status(dev,
- UPDATE_FW_ERASE_ERROR, PT_NO_INC);
- goto exit_close_file;
- }
- _pt_pip2_update_bl_status(dev, 0, 5);
- }
- remain_bytes = fw_size;
- buf[0] = pip2_data->pip2_file_handle;
- pt_debug(dev, DL_WARN,
- "%s: ATM - Writing %d bytes of firmware data now\n",
- __func__, fw_size);
- /*
- * No IRQ function is used to BL to reduce BL time due to any IRQ
- * latency.
- */
- if (cd->bl_with_no_int) {
- pip2_send_cmd = cmd->nonhid_cmd->pip2_send_cmd_no_int;
- disable_irq_nosync(cd->irq);
- } else
- pip2_send_cmd = cmd->nonhid_cmd->pip2_send_cmd;
- /* Continue writing while data remains */
- while (remain_bytes > packet_size) {
- write_len = packet_size;
- /* Don't update BL status on every pass */
- if (remain_bytes % 2000 < packet_size) {
- /* Calculate % complete for update_fw_status sysfs */
- percent_cmplt = (fw_size - remain_bytes) *
- 100 / fw_size;
- if (percent_cmplt > 0 &&
- percent_cmplt > UPDATE_FW_ACTIVE_90)
- percent_cmplt = UPDATE_FW_ACTIVE_90;
- _pt_pip2_update_bl_status(dev, percent_cmplt,
- PT_NO_INC);
- #ifdef TTDL_DIAGNOSTICS
- pt_debug(dev, DL_INFO,
- "Wrote %d bytes with %d bytes remaining\n",
- fw_size - remain_bytes - write_len,
- remain_bytes);
- #endif
- }
- if (retry_packet > 0) {
- #ifdef TTDL_DIAGNOSTICS
- cd->bl_retry_packet_count++;
- cmd->request_toggle_err_gpio(dev,
- PT_ERR_GPIO_BL_RETRY_PACKET);
- pt_debug(dev, DL_WARN,
- "%s: === Retry Packet #%d ===\n",
- __func__, retry_packet);
- #endif
- /* Get and log the last error(s) */
- _pt_pip2_log_last_error(dev, read_buf);
- }
- memcpy(&buf[1], fw_img, write_len);
- ret = pip2_send_cmd(dev,
- PT_CORE_CMD_UNPROTECTED, PIP2_CMD_ID_FILE_WRITE,
- buf, write_len + 1, read_buf, &actual_read_len);
- status = read_buf[PIP2_RESP_STATUS_OFFSET];
- /* Write cmd successful with a fail status */
- if (!ret && status) {
- /*
- * The last time through the loop when remain_bytes =
- * write_len, no partial payload will remain, the last
- * successful write (when writing to RAM) will respond
- * with EOF status, writing to FLASH will respond with a
- * standard success status of 0x00
- */
- if ((ld->pip2_load_file_no == PIP2_RAM_FILE) &&
- (status == PIP2_RSP_ERR_END_OF_FILE) &&
- (remain_bytes == write_len)) {
- pt_debug(dev, DL_WARN,
- "%s Last write, ret = 0x%02x\n",
- __func__, status);
- /* Drop out of the while loop */
- break;
- }
- _pt_pip2_update_bl_status(dev,
- UPDATE_FW_WRITE_ERROR, PT_NO_INC);
- pt_debug(dev, DL_ERROR,
- "%s file write failure, status = 0x%02x\n",
- __func__, status);
- if (retry_packet >= 3) {
- /* Tripple retry error - break */
- remain_bytes = 0;
- pt_debug(dev, DL_ERROR,
- "%s %d - Packet status error - Break\n",
- __func__, status);
- } else {
- retry_packet++;
- }
- } else if (ret) {
- /* Packet write failed - retry 3x */
- if (retry_packet >= 3) {
- remain_bytes = 0;
- pt_debug(dev, DL_ERROR,
- "%s %d - Packet cmd error - Break\n",
- __func__, ret);
- }
- retry_packet++;
- } else {
- /* Cmd success and status success */
- retry_packet = 0;
- }
- if (retry_packet == 0) {
- fw_img += write_len;
- remain_bytes -= write_len;
- }
- }
- /* Write the remaining bytes if any remain */
- if (remain_bytes > 0 && retry_packet == 0) {
- pt_debug(dev, DL_INFO,
- "Write last %d bytes to File = 0x%02x\n",
- remain_bytes, pip2_data->pip2_file_handle);
- memcpy(&buf[1], fw_img, remain_bytes);
- while (remain_bytes > 0 && retry_packet <= 3) {
- ret = pip2_send_cmd(dev, PT_CORE_CMD_UNPROTECTED,
- PIP2_CMD_ID_FILE_WRITE, buf, remain_bytes + 1,
- read_buf, &actual_read_len);
- status = read_buf[PIP2_RESP_STATUS_OFFSET];
- if (ret || status) {
- /*
- * Any non zero status when writing to FLASH is
- * an error. Only when writing to RAM, the last
- * packet must respond with an EOF status
- */
- if ((ld->pip2_load_file_no >= PIP2_FW_FILE) ||
- (ld->pip2_load_file_no == PIP2_RAM_FILE &&
- status != PIP2_RSP_ERR_END_OF_FILE)) {
- _pt_pip2_update_bl_status(dev,
- UPDATE_FW_WRITE_ERROR,
- PT_NO_INC);
- pt_debug(dev, DL_ERROR,
- "%s Write Fail-status=0x%02x\n",
- __func__, status);
- retry_packet++;
- } else if (ld->pip2_load_file_no ==
- PIP2_RAM_FILE &&
- status == PIP2_RSP_ERR_END_OF_FILE) {
- /* Special case EOF writing to SRAM */
- remain_bytes = 0;
- status = 0;
- }
- } else {
- remain_bytes = 0;
- }
- }
- }
- if (cd->bl_with_no_int)
- enable_irq(cd->irq);
- if (remain_bytes == 0 && retry_packet == 0)
- _pt_pip2_update_bl_status(dev, UPDATE_FW_ACTIVE_99, PT_NO_INC);
- if (retry_packet >= 3) {
- /* A packet write failure occurred 3x */
- pt_debug(dev, DL_ERROR,
- "%s: BL terminated due to consecutive write errors\n",
- __func__);
- _pt_pip2_update_bl_status(dev, UPDATE_FW_WRITE_ERROR,
- PT_NO_INC);
- } else if (status) {
- ret = status;
- pt_debug(dev, DL_ERROR,
- "%s: File write failed with status=%d\n",
- __func__, status);
- _pt_pip2_update_bl_status(dev, UPDATE_FW_WRITE_ERROR,
- PT_NO_INC);
- } else
- pt_debug(dev, DL_INFO,
- "%s: BIN file write finished successfully\n", __func__);
- ret = cmd->nonhid_cmd->pip2_file_close(dev, ld->pip2_load_file_no);
- if (ret != ld->pip2_load_file_no) {
- pt_debug(dev, DL_ERROR,
- "%s file close failure\n", __func__);
- _pt_pip2_update_bl_status(dev, UPDATE_FW_FILE_CLOSE_ERROR,
- PT_NO_INC);
- goto exit;
- }
- /* When updating non FW files, stay in BL */
- if (ld->pip2_load_file_no >= PIP2_CONFIG_FILE)
- goto exit;
- if ((ld->pip2_load_file_no == PIP2_RAM_FILE) &&
- (update_fw_status < UPDATE_FW_COMPLETE)) {
- /* When writing to RAM don't reset, just launch application */
- pt_debug(dev, DL_INFO,
- "%s Sending execute command now...\n", __func__);
- cd->startup_status = STARTUP_STATUS_START;
- ret = cmd->nonhid_cmd->pip2_send_cmd(dev,
- PT_CORE_CMD_UNPROTECTED, PIP2_CMD_ID_EXECUTE,
- NULL, 0, read_buf, &actual_read_len);
- status = read_buf[PIP2_RESP_STATUS_OFFSET];
- if (ret || status) {
- pt_debug(dev, DL_ERROR,
- "%s Execute command failure\n", __func__);
- _pt_pip2_update_bl_status(dev,
- UPDATE_FW_EXECUTE_ERROR, PT_NO_INC);
- goto exit;
- }
- } else if (ld->pip2_load_file_no == PIP2_FW_FILE &&
- update_fw_status < UPDATE_FW_COMPLETE) {
- pt_debug(dev, DL_INFO,
- "%s Toggle TP_XRES now...\n", __func__);
- cmd->request_reset(dev, PT_CORE_CMD_UNPROTECTED);
- }
- pt_debug(dev, DL_INFO, "%s: APP launched\n", __func__);
- /* If any error occurred simply close the file and exit */
- if (update_fw_status > UPDATE_FW_COMPLETE)
- goto exit_close_file;
- /* Wait for FW reset sentinel from reset or execute for up to 500ms */
- t = wait_event_timeout(cd->wait_q,
- (cd->startup_status >= STARTUP_STATUS_FW_RESET_SENTINEL),
- msecs_to_jiffies(PT_BL_WAIT_FOR_SENTINEL));
- if (IS_TMO(t)) {
- pt_debug(dev, DL_WARN,
- "%s: 0x%04X Timeout waiting for FW sentinel",
- __func__, cd->startup_status);
- }
- /* Double verify DUT is alive and well in Application mode */
- if (cd->startup_status & STARTUP_STATUS_FW_RESET_SENTINEL) {
- ret = cmd->request_pip2_get_mode_sysmode(dev,
- PT_CORE_CMD_UNPROTECTED, &mode, NULL);
- pt_debug(dev, DL_WARN, "%s: mode = %d (Expected 2)",
- __func__, mode);
- if (mode != PT_MODE_OPERATIONAL) {
- pt_debug(dev, DL_ERROR,
- "%s ERROR: Not in App mode as expected\n",
- __func__);
- _pt_pip2_update_bl_status(dev, UPDATE_FW_MODE_ERROR,
- PT_NO_INC);
- goto exit;
- }
- } else {
- pt_debug(dev, DL_ERROR, "%s: FW sentinel not seen 0x%04X\n",
- __func__, cd->startup_status);
- _pt_pip2_log_last_error(dev, read_buf);
- _pt_pip2_update_bl_status(dev, UPDATE_FW_SENTINEL_NOT_SEEN,
- PT_NO_INC);
- goto exit;
- }
- /* On a Flashless DUT save or restore the CAL data */
- if (cd->cal_cache_in_host == PT_FEATURE_ENABLE)
- _pt_calibrate_flashless_dut(dev);
- /* Subscribe calibration task if calibration flag is set */
- if (ld->loader_pdata
- && (ld->loader_pdata->flags
- & PT_LOADER_FLAG_CALIBRATE_AFTER_FW_UPGRADE)
- && (cd->cal_cache_in_host == PT_FEATURE_DISABLE)) {
- #if (KERNEL_VERSION(3, 13, 0) <= LINUX_VERSION_CODE)
- reinit_completion(&ld->calibration_complete);
- #else
- INIT_COMPLETION(ld->calibration_complete);
- #endif
- /* set up call back for startup */
- pt_debug(dev, DL_INFO, "%s: Adding callback for calibration\n",
- __func__);
- ret = cmd->subscribe_attention(dev, PT_ATTEN_STARTUP,
- PT_LOADER_NAME, pt_calibration_attention, 0);
- if (ret) {
- pt_debug(dev, DL_ERROR,
- "%s: Failed adding callback for calibration\n",
- __func__);
- ret = 0;
- } else
- wait_for_calibration_complete = true;
- }
- pt_debug(dev, DL_INFO, "%s: == PIP2 FW upgrade finished ==\n",
- __func__);
- goto exit;
- exit_close_file:
- ret = cmd->nonhid_cmd->pip2_file_close(dev, ld->pip2_load_file_no);
- if (ret < 0) {
- pt_debug(dev, DL_ERROR,
- "%s file close failure\n", __func__);
- _pt_pip2_update_bl_status(dev, UPDATE_FW_FILE_CLOSE_ERROR,
- PT_NO_INC);
- }
- exit:
- cd->fw_updating = false;
- if (us_fw_used)
- kfree(fw_img);
- if (ld->pip2_load_file_no > PIP2_FW_FILE)
- goto exit_staying_in_bl;
- cmd->release_exclusive(dev);
- pm_runtime_put_sync(dev);
- if (fw)
- release_firmware(fw);
- /*
- * For built-in FW update, it should not warn builtin_bin_fw_status
- * for each bootup since update_fw_status would be
- * UPDATE_FW_VERSION_ERROR in most situations because firmware
- * should have been up to date.
- */
- if (ld->pip2_load_builtin) {
- if ((update_fw_status == UPDATE_FW_ACTIVE_99) ||
- (update_fw_status == UPDATE_FW_VERSION_ERROR))
- ld->builtin_bin_fw_status = 0;
- else
- ld->builtin_bin_fw_status = -EINVAL;
- }
- if ((update_fw_status == UPDATE_FW_ACTIVE_99) ||
- (update_fw_status == UPDATE_FW_VERSION_ERROR)) {
- pt_debug(dev, DL_WARN, "%s: Queue ENUM\n", __func__);
- cmd->request_enum(dev, true);
- }
- if (update_fw_status < UPDATE_FW_COMPLETE)
- _pt_pip2_update_bl_status(dev, UPDATE_FW_COMPLETE, PT_NO_INC);
- if (wait_for_calibration_complete)
- wait_for_completion(&ld->calibration_complete);
- pt_debug(dev, DL_INFO, "%s: Starting watchdog\n", __func__);
- ret = cmd->request_start_wd(dev);
- /*
- * When in No-Flash mode allow auto BL after any BL.
- * There is an issue where setting flashless mode via drv_debug
- * can happen in the middle of pt_pip2_enter_bl() which will revert
- * the flashless_auto_bl value back to what it was when the function
- * started.
- */
- if (cd->flashless_dut)
- cd->flashless_auto_bl = PT_ALLOW_AUTO_BL;
- return;
- exit_staying_in_bl:
- /* When updating a non FW file, a restart is not wanted. Stay in BL */
- _pt_pip2_update_bl_status(dev, UPDATE_FW_COMPLETE, PT_NO_INC);
- cmd->release_exclusive(dev);
- pm_runtime_put_sync(dev);
- if (fw)
- release_firmware(fw);
- }
- #define PIP2_MAX_FILE_NAMES 3
- /*******************************************************************************
- * FUNCTION: pt_pip2_upgrade_firmware_from_builtin
- *
- * SUMMARY: Bootload the DUT with a built in firmware binary image.
- * Load either a SRAM image "ttdl_fw_RAM.bin" or a FLASH image
- * "ttdl_fw.bin" with the priority being the SRAM image.
- *
- * PARAMETERS:
- * *dev - pointer to the device structure
- ******************************************************************************/
- static int pt_pip2_upgrade_firmware_from_builtin(struct device *dev)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- struct pt_core_data *cd = dev_get_drvdata(dev);
- const struct firmware *fw_entry = NULL;
- int retval;
- int rc = 0;
- int read_size = 16;
- u8 image[16];
- int index = 0;
- int file_count = 0;
- char *filename[PIP2_MAX_FILE_NAMES];
- /*
- * Load the supported filenames in the correct search order
- * 0 - "tt_fw<_PIDX>.bin"
- * 1 - "XXXX_tt_fw<_PIDX>.bin" where XXXX = Silicon ID
- * 2 - "tt_fw.bin", default FW name
- */
- filename[file_count++] = generate_firmware_filename(dev);
- filename[file_count++] = generate_silicon_id_firmware_filename(dev);
- if (pt_get_panel_id(dev) != PANEL_ID_NOT_ENABLED) {
- filename[file_count] =
- kzalloc(sizeof(PT_FW_FILE_NAME), GFP_KERNEL);
- memcpy(filename[file_count++], PT_FW_FILE_NAME,
- sizeof(PT_FW_FILE_NAME));
- }
- for (index = 0; index < file_count; index++) {
- if (!filename[index])
- return -ENOMEM;
- }
- if (cd->flashless_dut) {
- pt_debug(dev, DL_INFO,
- "%s: Proceed to BL flashless DUT\n", __func__);
- ld->pip2_load_file_no = PIP2_RAM_FILE;
- if (cd->pip2_us_file_path[0] == '\0') {
- ld->pip2_load_builtin = true;
- pt_debug(dev, DL_WARN,
- "%s: US Path not defined, BL from built-in\n",
- __func__);
- } else {
- /* Read a few bytes to see if file exists */
- rc = cmd->nonhid_cmd->read_us_file(dev,
- cd->pip2_us_file_path, image, &read_size);
- if (!rc) {
- ld->pip2_load_builtin = false;
- pt_debug(dev, DL_WARN,
- "%s: %s Found, BL from US\n",
- __func__, cd->pip2_us_file_path);
- goto ready;
- } else {
- ld->pip2_load_builtin = true;
- pt_debug(dev, DL_WARN,
- "%s: ATM - %s NOT Found, BL from built-in\n",
- __func__, cd->pip2_us_file_path);
- }
- }
- } else {
- ld->pip2_load_file_no = PIP2_FW_FILE;
- ld->pip2_load_builtin = true;
- }
- /* Look for any FW file name match and request the FW */
- mutex_lock(&cd->firmware_class_lock);
- index = 0;
- while (index < file_count) {
- pt_debug(dev, DL_INFO, "%s: Request FW class file: %s\n",
- __func__, filename[index]);
- retval = request_firmware_direct(&fw_entry,
- filename[index], dev);
- if (retval < 0) {
- pt_debug(dev, DL_WARN, "%s: ATM - Fail request FW %s load\n",
- __func__, filename[index]);
- } else {
- pt_debug(dev, DL_INFO, "%s: FW %s class file loading\n",
- __func__, filename[index]);
- break;
- }
- index++;
- }
- /* No matching file names found */
- if (index == file_count) {
- pt_debug(dev, DL_WARN, "%s: No FW is found\n", __func__);
- goto exit;
- }
- ready:
- _pt_pip2_firmware_cont(fw_entry, dev);
- retval = ld->builtin_bin_fw_status;
- exit:
- mutex_unlock(&cd->firmware_class_lock);
- index = 0;
- while (index < file_count)
- kfree(filename[index++]);
- return retval;
- }
- /*******************************************************************************
- * FUNCTION: pt_pip2_create_fw_class
- *
- * SUMMARY: Create the firmware class but don't actually laod any FW to the
- * DUT. This creates all the sysfs nodes needed for a user to bootload
- * the DUT with their own bin file.
- *
- * PARAMETERS:
- * *pip2_data - pointer to the PIP2 loader data structure
- ******************************************************************************/
- static int pt_pip2_create_fw_class(struct pip2_loader_data *pip2_data)
- {
- int ret = 0;
- struct device *dev = pip2_data->dev;
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- /*
- * The file name dev_name(dev) is tied with bus name and usually
- * it is "x-0024". This name is wanted to keep consistency
- * (e.g. /sys/class/firmware/x-0024/) for the path of fw class
- * nodes with different kernel release. Also it is an invalid bin
- * file name used intentionally because request_firmware_nowait
- * will not find the file which is what we want and then simply
- * create the fw class nodes.
- */
- ld->pip2_load_builtin = false;
- pt_debug(dev, DL_INFO, "%s: Request FW Class", __func__);
- ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_NOHOTPLUG,
- dev_name(dev), dev, GFP_KERNEL, dev,
- _pt_pip2_firmware_cont);
- if (ret) {
- pt_debug(dev, DL_ERROR,
- "%s: ERROR requesting firmware class\n", __func__);
- }
- return ret;
- }
- /*******************************************************************************
- * FUNCTION: pt_pip2_bl_from_file_work
- *
- * SUMMARY: The work function to schedule the BL work for PIP2 only.
- *
- * PARAMETERS:
- * *bl_from_file - pointer to work_struct structure
- ******************************************************************************/
- static void pt_pip2_bl_from_file_work(struct work_struct *pip2_bl_from_file)
- {
- struct pt_loader_data *ld = container_of(pip2_bl_from_file,
- struct pt_loader_data, pip2_bl_from_file);
- struct device *dev = ld->dev;
- const struct firmware *fw_entry = NULL;
- _pt_pip2_firmware_cont(fw_entry, dev);
- }
- /*******************************************************************************
- * FUNCTION: pt_bl_from_file_work
- *
- * SUMMARY: The work function to schedule the BL work for PIP2 or PIP1
- * according to the active_dut_generation in core data.
- *
- * PARAMETERS:
- * *bl_from_file - pointer to work_struct structure
- ******************************************************************************/
- static void pt_bl_from_file_work(struct work_struct *bl_from_file)
- {
- struct pt_loader_data *ld = container_of(bl_from_file,
- struct pt_loader_data, bl_from_file);
- struct device *dev = ld->dev;
- const struct firmware *fw_entry = NULL;
- u8 dut_gen = cmd->request_dut_generation(dev);
- if (dut_gen == DUT_PIP2_CAPABLE)
- _pt_pip2_firmware_cont(fw_entry, dev);
- else if (dut_gen == DUT_PIP1_ONLY)
- _pt_pip1_bl_from_file(dev);
- }
- /*******************************************************************************
- * FUNCTION: pt_pip2_bl_from_file_show
- *
- * SUMMARY: The show method for the "pip2_bl_from_file" sysfs node. The
- * scheduled work will perform PIP2 BL.
- *
- * NOTE: Since this function doesn't set pip2_load_file_no, it will use the
- * value what has been stored there.
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *attr - pointer to device attributes structure
- * *buf - pointer to print output buffer
- ******************************************************************************/
- static ssize_t pt_pip2_bl_from_file_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- struct pt_core_data *cd = dev_get_drvdata(dev);
- int rc = 0;
- int read_size = 2;
- u8 image[2];
- mutex_lock(&cd->firmware_class_lock);
- ld->pip2_load_builtin = false;
- mutex_unlock(&cd->firmware_class_lock);
- /* Read a few bytes to see if file exists */
- rc = cmd->nonhid_cmd->read_us_file(dev,
- cd->pip2_us_file_path, image, &read_size);
- if (!rc) {
- schedule_work(&ld->pip2_bl_from_file);
- return scnprintf(buf, PT_MAX_PRBUF_SIZE,
- "Status: %d\n"
- "BL File: %s\n",
- rc, cd->pip2_us_file_path);
- } else {
- return scnprintf(buf, PT_MAX_PRBUF_SIZE,
- "Status: %d\n"
- "BL File: '%s' - Does not exist\n",
- rc, cd->pip2_us_file_path);
- }
- }
- /*******************************************************************************
- * FUNCTION: pt_bl_from_file_show
- *
- * SUMMARY: The show method for the "pt_bl_from_file" sysfs node. The scheduled
- * work can perform either PIP1 BL and PIP2 BL according to the
- * active_dut_generation of core data.
- *
- * NOTE: Since this function doesn't set pip2_load_file_no, it will use the
- * value what has been stored there.
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *attr - pointer to device attributes structure
- * *buf - pointer to print output buffer
- ******************************************************************************/
- static ssize_t pt_bl_from_file_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- struct pt_core_data *cd = dev_get_drvdata(dev);
- int rc = 0;
- int read_size = 2;
- u8 dut_gen = cmd->request_dut_generation(dev);
- u8 image[2];
- mutex_lock(&cd->firmware_class_lock);
- ld->pip2_load_builtin = false;
- mutex_unlock(&cd->firmware_class_lock);
- /* Read a few bytes to see if file exists */
- rc = cmd->nonhid_cmd->read_us_file(dev,
- cd->pip2_us_file_path, image, &read_size);
- if (dut_gen == DUT_UNKNOWN) {
- rc = -EINVAL;
- return scnprintf(buf, PT_MAX_PRBUF_SIZE,
- "Status: %d\n"
- "BL File: '%s' - Failed, DUT Generation could not be determined\n",
- rc, cd->pip2_us_file_path);
- } else if (!rc) {
- schedule_work(&ld->bl_from_file);
- return scnprintf(buf, PT_MAX_PRBUF_SIZE,
- "Status: %d\n"
- "BL File: %s\n",
- rc, cd->pip2_us_file_path);
- } else {
- return scnprintf(buf, PT_MAX_PRBUF_SIZE,
- "Status: %d\n"
- "BL File: '%s' - Does not exist\n",
- rc, cd->pip2_us_file_path);
- }
- }
- /*******************************************************************************
- * FUNCTION: pt_pip2_bl_from_file_store
- *
- * SUMMARY: The store method for the "pip2_bl_from_file" and "pt_bl_from_file"
- * sysfs node. Used to allow any file path[necessary] and file_no[optional] to
- * be used to BL, for example: "echo /data/pt_fw 1 > pip2_bl_from_file", and
- * do the "cat" will perform FW loader process.
- *
- * NOTE: the last char of file path in buf which is a '\n' is not copied.
- * NOTE: the default file_no is PIP2_RAM_FILE.
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *attr - pointer to device attributes
- * *buf - pointer to output buffer
- * size - size of data in buffer
- ******************************************************************************/
- static ssize_t pt_pip2_bl_from_file_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- struct pt_core_data *cd = dev_get_drvdata(dev);
- const char *deli_space = " ", *deli_comma = ",";
- char name_space[PT_MAX_PATH_SIZE];
- char *ptr_left = NULL, *ptr_right = name_space;
- u8 file_no = PIP2_RAM_FILE;
- u32 input_data[2];
- int length;
- bool file_no_set = false;
- memset(name_space, 0, PT_MAX_PATH_SIZE);
- memset(cd->pip2_us_file_path, 0, PT_MAX_PATH_SIZE);
- if (size <= PT_MAX_PATH_SIZE) {
- memcpy(name_space, buf, size);
- ptr_left = strsep(&ptr_right, deli_space);
- if (ptr_right == NULL) {
- ptr_right = name_space;
- ptr_left = strsep(&ptr_right, deli_comma);
- }
- if (ptr_right != NULL) {
- length = cmd->parse_sysfs_input(
- dev, ptr_right, strlen(ptr_right), input_data,
- ARRAY_SIZE(input_data));
- if (length <= 0) {
- pt_debug(dev, DL_ERROR,
- "%s: Input format error!\n", __func__);
- return -EINVAL;
- }
- file_no_set = true;
- file_no = input_data[0];
- }
- pt_debug(dev, DL_WARN, "%s:Path=%s, File_no=%s(%d)\n", __func__,
- ptr_left, ptr_right, file_no);
- if ((file_no_set) &&
- ((file_no < PIP2_RAM_FILE) || (file_no > PIP2_FILE_MAX))) {
- pt_debug(dev, DL_WARN, "%s:Invalid File_no = %d\n",
- __func__, file_no);
- return -EINVAL;
- }
- mutex_lock(&cd->firmware_class_lock);
- ld->pip2_load_file_no = file_no;
- mutex_unlock(&cd->firmware_class_lock);
- if (ptr_left[strlen(ptr_left) - 1] == '\n')
- memcpy(cd->pip2_us_file_path, ptr_left,
- strlen(ptr_left) - 1);
- else
- memcpy(cd->pip2_us_file_path, ptr_left,
- strlen(ptr_left));
- }
- return size;
- }
- static DEVICE_ATTR(pip2_bl_from_file, 0644,
- pt_pip2_bl_from_file_show, pt_pip2_bl_from_file_store);
- static DEVICE_ATTR(pt_bl_from_file, 0644,
- pt_bl_from_file_show, pt_pip2_bl_from_file_store);
- /*******************************************************************************
- * FUNCTION: pt_pip2_manual_upgrade_store
- *
- * SUMMARY: Store method for the pip2_manual_upgrade sysfs node. Allows
- * sysfs control of bootloading a new FW image to FLASH.
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *attr - pointer to device attributes
- * *buf - pointer to output buffer
- * size - size of data in buffer
- ******************************************************************************/
- static ssize_t pt_pip2_manual_upgrade_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- u32 input_data[2] = {0};
- int length;
- int rc = 0;
- length = cmd->parse_sysfs_input(dev, buf, size, input_data,
- ARRAY_SIZE(input_data));
- if (length != 1) {
- pt_debug(dev, DL_WARN, "%s: Invalid number of arguments\n",
- __func__);
- rc = -EINVAL;
- goto exit;
- }
- if (input_data[0] < 0 || input_data[0] > 1) {
- pt_debug(dev, DL_WARN, "%s: Invalid arguments\n", __func__);
- rc = -EINVAL;
- goto exit;
- }
- _pt_pip2_update_bl_status(dev, UPDATE_FW_IDLE, PT_NO_INC);
- if (ld->is_manual_upgrade_enabled) {
- pt_debug(dev, DL_ERROR,
- "%s: ERROR - Manual upgrade busy\n", __func__);
- rc = -EBUSY;
- goto exit;
- }
- ld->pip2_load_file_no = PIP2_FW_FILE;
- pt_debug(dev, DL_DEBUG, "%s: ATM - File number is %d\n",
- __func__, ld->pip2_load_file_no);
- ld->is_manual_upgrade_enabled = 1;
- rc = pt_pip2_create_fw_class(ld->pip2_data);
- ld->is_manual_upgrade_enabled = 0;
- if (rc < 0)
- pt_debug(dev, DL_ERROR,
- "%s: ERROR - FLASH Upgrade failed\n", __func__);
- exit:
- if (rc)
- return rc;
- return size;
- }
- static DEVICE_ATTR(pip2_manual_upgrade, 0200,
- NULL, pt_pip2_manual_upgrade_store);
- /*******************************************************************************
- * FUNCTION: pt_pip2_manual_ram_upgrade_store
- *
- * SUMMARY: Store method for the pip2_manual_ram_upgrade sysfs node. Allows
- * sysfs control of bootloading a new FW image to SRAM.
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *attr - pointer to device attributes
- * *buf - pointer to output buffer
- * size - size of data in buffer
- ******************************************************************************/
- static ssize_t pt_pip2_manual_ram_upgrade_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- u32 input_data[2] = {0};
- int length;
- int rc = 0;
- length = cmd->parse_sysfs_input(dev, buf, size, input_data,
- ARRAY_SIZE(input_data));
- if (length != 1) {
- pt_debug(dev, DL_WARN, "%s: Invalid number of arguments\n",
- __func__);
- rc = -EINVAL;
- goto exit;
- }
- if (input_data[0] < 0 || input_data[0] > 1) {
- pt_debug(dev, DL_WARN, "%s: Invalid arguments\n", __func__);
- rc = -EINVAL;
- goto exit;
- }
- _pt_pip2_update_bl_status(dev, UPDATE_FW_IDLE, PT_NO_INC);
- if (ld->is_manual_upgrade_enabled) {
- pt_debug(dev, DL_ERROR,
- "%s: ERROR - Manual upgrade busy\n", __func__);
- rc = -EBUSY;
- goto exit;
- }
- ld->pip2_load_file_no = PIP2_RAM_FILE;
- pt_debug(dev, DL_DEBUG, "%s: ATM - File number is %d\n",
- __func__, ld->pip2_load_file_no);
- ld->is_manual_upgrade_enabled = 1;
- rc = pt_pip2_create_fw_class(ld->pip2_data);
- ld->is_manual_upgrade_enabled = 0;
- if (rc < 0)
- pt_debug(dev, DL_ERROR,
- "%s: ERROR - RAM Upgrade failed\n", __func__);
- exit:
- if (rc)
- return rc;
- return size;
- }
- static DEVICE_ATTR(pip2_manual_ram_upgrade, 0200,
- NULL, pt_pip2_manual_ram_upgrade_store);
- /*******************************************************************************
- * FUNCTION: pt_pip2_file_write_store
- *
- * SUMMARY: Store method for the pip2_file_write sysfs node. Allows
- * sysfs control to "load" data into any file.
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *attr - pointer to device attributes
- * *buf - pointer to output buffer
- * size - size of data in buffer
- ******************************************************************************/
- static ssize_t pt_pip2_file_write_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- int rc;
- u32 input_data[3];
- int length;
- if (ld->is_manual_upgrade_enabled) {
- pt_debug(dev, DL_ERROR,
- "%s: ERROR - Manual upgrade busy\n", __func__);
- rc = -EBUSY;
- goto exit;
- }
- length = cmd->parse_sysfs_input(dev, buf, size, input_data,
- ARRAY_SIZE(input_data));
- if (length <= 0 || length > 2) {
- pt_debug(dev, DL_ERROR, "%s: Invalid number of arguments\n",
- __func__);
- ld->pip2_file_data.para_num = 0;
- rc = -EINVAL;
- goto exit;
- }
- if (input_data[0] < PIP2_FW_FILE || input_data[0] > PIP2_FILE_MAX) {
- pt_debug(dev, DL_ERROR, "%s: Invalid file handle\n", __func__);
- ld->pip2_file_data.para_num = 0;
- rc = -EINVAL;
- goto exit;
- }
- ld->pip2_load_file_no = input_data[0];
- if (length == 2)
- ld->pip2_file_data.file_offset = input_data[1];
- ld->is_manual_upgrade_enabled = 1;
- rc = pt_pip2_create_fw_class(ld->pip2_data);
- ld->is_manual_upgrade_enabled = 0;
- if (rc < 0)
- pt_debug(dev, DL_ERROR,
- "%s: ERROR - RAM Upgrade failed\n", __func__);
- exit:
- if (rc)
- return rc;
- return size;
- }
- static DEVICE_ATTR(pip2_file_write, 0200, NULL, pt_pip2_file_write_store);
- /*******************************************************************************
- * FUNCTION: pt_update_fw_store
- *
- * SUMMARY: Store method for the update_fw sysfs node. This node is required
- * by ChromeOS to first determine if loading is available and then perform
- * the loading if required. This function is simply a wrapper to call:
- * pt_pip2_manual_upgrade_store - for the TC3XXX or TT7XXX parts
- * pt_manual_upgrade_store - for the legacy Gen5/6 devices.
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *attr - pointer to device attributes
- * *buf - pointer to output buffer
- * size - size of data in buffer
- ******************************************************************************/
- static ssize_t pt_update_fw_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
- {
- u8 dut_gen = cmd->request_dut_generation(dev);
- if (dut_gen == DUT_PIP2_CAPABLE)
- size = pt_pip2_manual_upgrade_store(dev, attr, buf, size);
- else if (dut_gen == DUT_PIP1_ONLY)
- size = pt_manual_upgrade_store(dev, attr, buf, size);
- return size;
- }
- static DEVICE_ATTR(update_fw, 0200, NULL, pt_update_fw_store);
- #endif /* CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE */
- #ifdef TTDL_DIAGNOSTICS
- /*******************************************************************************
- * FUNCTION: pt_pip2_file_read_show
- *
- * SUMMARY: The read method for the pip2_file_read sysfs node. Allows to
- * perform flash read action according to stored value. This function will
- * re-enter always until it returns:
- * 0: No data to be written to sysfs node
- * <0: Error happens
- * (For kernel version large than 3.11(not tested), if the function returns
- * non-zero value in previous chunk, to return 0 once can not stop re-enter.
- * It needs one more time to stop read action by returned value <= 0. But for
- * older version, read action will stop when returned value <= 0 once).
- *
- * NOTE: Up to PIP2_FILE_WRITE_LEN_PER_PACKET(245) bytes of data are read for
- * each enter. When last package is read, pip2_file_data.para_num is assigned
- * as negatie value(-1), then next enter can return 0 to indicate the read
- * method can be finished.
- *
- * RETURN: Size of data written to sysfs node
- *
- * PARAMETERS:
- * *filp - pointer to file structure
- * *kobj - pointer to kobject structure
- * *bin_attr - pointer to bin_attribute structure
- * buf - pointer to cmd input buffer
- * offset - offset index to store input buffer
- * count - size of data in buffer
- ******************************************************************************/
- static ssize_t pt_pip2_file_read_show(struct file *filp,
- struct kobject *kobj, struct bin_attribute *bin_attr,
- char *buf, loff_t offset, size_t count)
- {
- struct device *dev = container_of(kobj, struct device, kobj);
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- struct pt_core_data *cd = dev_get_drvdata(dev);
- int rc = 0;
- u8 file_handle = ld->pip2_file_data.file_handle;
- u8 *pr_buf = ld->pip2_file_data.file_print_buf;
- int print_idx = 0, read_size = 0, i;
- u8 read_buf[PT_MAX_PIP2_MSG_SIZE];
- u8 read_len;
- u32 address, file_size;
- if (ld->pip2_file_data.file_print_left) {
- pt_debug(dev, DL_INFO, "%s: print left=%d, count=%zu\n",
- __func__, ld->pip2_file_data.file_print_left, count);
- print_idx = ld->pip2_file_data.file_print_left;
- if (count < print_idx) {
- memcpy(buf, pr_buf, count);
- ld->pip2_file_data.file_print_left = print_idx - count;
- for (i = 0; i < ld->pip2_file_data.file_print_left; i++)
- pr_buf[i] = pr_buf[i+count];
- print_idx = count;
- } else {
- memcpy(buf, pr_buf, print_idx);
- ld->pip2_file_data.file_print_left = 0;
- }
- return print_idx;
- }
- if (ld->pip2_file_data.para_num == 0) {
- /*
- * When offset != 0, it means the extra call for splice out,
- * don't need a warning.
- */
- if (offset != 0)
- return 0;
- print_idx += scnprintf(buf, count, "Status: %d\n"
- "No input!\n", -EINVAL);
- pt_debug(dev, DL_ERROR, "%s: Invalid para_num = %d!\n",
- __func__, ld->pip2_file_data.para_num);
- return print_idx;
- } else if (ld->pip2_file_data.para_num == -1) {
- ld->pip2_file_data.para_num = 0;
- pt_debug(dev, DL_INFO, "%s: flash read finish!\n",
- __func__);
- rc = 0;
- goto exit_release;
- } else if (ld->pip2_file_data.para_num < -1) {
- ld->pip2_file_data.para_num = 0;
- pt_debug(dev, DL_ERROR, "%s: Exit directly due to errors!\n",
- __func__);
- return 0;
- } else if (ld->pip2_file_data.para_num > 3) {
- ld->pip2_file_data.para_num = 0;
- pt_debug(dev, DL_ERROR,
- "%s: Exit directly due to invalid parameter!\n",
- __func__);
- return 0;
- }
- if (offset == 0) {
- ld->pip2_file_data.file_print_buf = kzalloc(PIPE_BUF,
- GFP_KERNEL);
- if (!ld->pip2_file_data.file_print_buf) {
- rc = -ENOMEM;
- goto exit;
- }
- /* This functionality is only available in the BL */
- if (cd->mode != PT_MODE_BOOTLOADER) {
- rc = -EPERM;
- goto exit_free;
- }
- pr_buf = ld->pip2_file_data.file_print_buf;
- rc = cmd->request_exclusive(dev,
- PT_LDR_REQUEST_EXCLUSIVE_TIMEOUT);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Failed to request exclusive rc=%d\n",
- __func__, rc);
- goto exit_free;
- }
- rc = cmd->nonhid_cmd->pip2_file_open(dev, file_handle);
- if (rc < 0) {
- pt_debug(dev, DL_ERROR,
- "%s: Failed to file_open rc=%d\n",
- __func__, rc);
- goto exit_release;
- }
- rc = cmd->nonhid_cmd->pip2_file_get_stats(dev, file_handle,
- &address, &file_size);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Failed to get_file_state rc=%d\n",
- __func__, rc);
- goto exit_file_close;
- }
- ld->pip2_file_data.file_print_size = 0;
- ld->pip2_file_data.file_max_size = file_size;
- ld->pip2_file_data.file_print_left = 0;
- print_idx += scnprintf(pr_buf, PIPE_BUF, "ROM_DATA:");
- if (ld->pip2_file_data.para_num == 1)
- ld->pip2_file_data.file_read_size = file_size;
- else if (ld->pip2_file_data.para_num == 2) {
- if (ld->pip2_file_data.file_offset < file_size)
- ld->pip2_file_data.file_read_size = file_size -
- ld->pip2_file_data.file_offset;
- else {
- rc = -EINVAL;
- pt_debug(dev, DL_ERROR,
- "%s: File read out of bounds rc=%d\n",
- __func__, rc);
- goto exit_file_close;
- }
- } else if (ld->pip2_file_data.para_num == 3) {
- if ((ld->pip2_file_data.file_read_size +
- ld->pip2_file_data.file_offset) > file_size) {
- rc = -EINVAL;
- pt_debug(dev, DL_ERROR,
- "%s: File read out of bounds rc=%d\n",
- __func__, rc);
- goto exit_file_close;
- }
- } else {
- pt_debug(dev, DL_ERROR,
- "%s: Invalid number of parameters!\n",
- __func__);
- goto exit_file_close;
- }
- }
- offset = ld->pip2_file_data.file_print_size +
- ld->pip2_file_data.file_offset;
- if ((offset >= ld->pip2_file_data.file_max_size) ||
- (ld->pip2_file_data.file_print_size >=
- ld->pip2_file_data.file_read_size))
- goto exit_file_close;
- else if ((ld->pip2_file_data.file_print_size +
- PIP2_FILE_WRITE_LEN_PER_PACKET) >=
- ld->pip2_file_data.file_read_size)
- read_len = ld->pip2_file_data.file_read_size -
- ld->pip2_file_data.file_print_size;
- else
- read_len = PIP2_FILE_WRITE_LEN_PER_PACKET;
- rc = cmd->nonhid_cmd->pip2_file_seek_offset(dev,
- file_handle, offset, 0);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Failed to seek file offset rc=%d\n",
- __func__, rc);
- goto exit_file_close;
- }
- read_size = cmd->nonhid_cmd->pip2_file_read(dev,
- file_handle, read_len, read_buf);
- if (read_size < 0) {
- pt_debug(dev, DL_ERROR, "%s: Failed to read file rc=%d\n",
- __func__, read_size);
- goto exit_file_close;
- }
- for (i = 0; i < read_size; i++)
- print_idx += scnprintf(pr_buf + print_idx,
- PIPE_BUF - print_idx,
- "%02X ", read_buf[i + PIP2_RESP_BODY_OFFSET]);
- ld->pip2_file_data.file_print_size += read_size;
- if (count < print_idx) {
- memcpy(buf, pr_buf, count);
- ld->pip2_file_data.file_print_left = print_idx - count;
- for (i = 0; i < ld->pip2_file_data.file_print_left; i++)
- pr_buf[i] = pr_buf[i+count];
- print_idx = count;
- } else {
- memcpy(buf, pr_buf, print_idx);
- }
- goto exit_for_next_read;
- exit_file_close:
- if (rc)
- print_idx += scnprintf(pr_buf + print_idx,
- PIPE_BUF - print_idx, "(READ ERROR)\n");
- else if (ld->pip2_file_data.file_print_size)
- print_idx += scnprintf(pr_buf + print_idx,
- PIPE_BUF - print_idx,
- ":(%d bytes)\n",
- ld->pip2_file_data.file_print_size);
- else
- print_idx += scnprintf(pr_buf + print_idx,
- PIPE_BUF - print_idx, "No Data\n");
- if (count < print_idx) {
- memcpy(buf, pr_buf, count);
- ld->pip2_file_data.file_print_left = print_idx - count;
- for (i = 0; i < ld->pip2_file_data.file_print_left; i++)
- pr_buf[i] = pr_buf[i+count];
- print_idx = count;
- } else {
- memcpy(buf, pr_buf, print_idx);
- }
- rc = cmd->nonhid_cmd->pip2_file_close(dev, file_handle);
- if (file_handle != rc)
- pt_debug(dev, DL_ERROR,
- "%s Failed to close file %d, rc = %d\n", __func__,
- file_handle, rc);
- /*
- * Mark para_num as negative value to finish read method during
- * next enter.
- */
- ld->pip2_file_data.para_num = -1;
- exit_for_next_read:
- pt_debug(dev, DL_INFO,
- "%s: %s=%d, %s=%d, %s=%d, %s=%d, %s=%d\n",
- __func__,
- "para_num", ld->pip2_file_data.para_num,
- "handle", ld->pip2_file_data.file_handle,
- "offset", ld->pip2_file_data.file_offset,
- "read", ld->pip2_file_data.file_read_size,
- "print", ld->pip2_file_data.file_print_size);
- return print_idx;
- exit_release:
- cmd->release_exclusive(dev);
- exit_free:
- kfree(ld->pip2_file_data.file_print_buf);
- exit:
- if (rc) {
- ld->pip2_file_data.para_num = -2;
- print_idx = scnprintf(buf, count, "Status: %d\n", rc);
- return print_idx;
- } else
- return 0;
- }
- /*******************************************************************************
- * FUNCTION: pt_pip2_file_read_store
- *
- * SUMMARY: The write method for the pip2_file_read node. The passed
- * in data is needed by read method.
- *
- * RETURN: Size of passed in buffer is success
- *
- * PARAMETERS:
- * *filp - pointer to file structure
- * *kobj - pointer to kobject structure
- * *bin_attr - pointer to bin_attribute structure
- * buf - pointer to cmd input buffer
- * offset - offset index to store input buffer
- * count - size of data in buffer
- ******************************************************************************/
- static ssize_t pt_pip2_file_read_store(struct file *filp,
- struct kobject *kobj, struct bin_attribute *bin_attr,
- char *buf, loff_t offset, size_t count)
- {
- int rc = 0;
- int length;
- struct device *dev = container_of(kobj, struct device, kobj);
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- int ic_buffer[4] = {0};
- length = cmd->parse_sysfs_input(dev, buf, count, ic_buffer,
- ARRAY_SIZE(ic_buffer));
- if (length <= 0 || length > 3) {
- pt_debug(dev, DL_ERROR, "%s: Input format error!\n",
- __func__);
- ld->pip2_file_data.para_num = 0;
- rc = -EINVAL;
- goto error;
- }
- if (ic_buffer[0] < PIP2_FW_FILE || ic_buffer[0] > PIP2_FILE_7) {
- pt_debug(dev, DL_ERROR, "%s: Invalid file handle!\n",
- __func__);
- ld->pip2_file_data.para_num = 0;
- rc = -EINVAL;
- goto error;
- }
- switch (length) {
- case 1:
- ld->pip2_file_data.file_handle = ic_buffer[0];
- ld->pip2_file_data.file_offset = 0;
- ld->pip2_file_data.file_read_size = 0;
- break;
- case 2:
- ld->pip2_file_data.file_handle = ic_buffer[0];
- ld->pip2_file_data.file_offset = ic_buffer[1];
- ld->pip2_file_data.file_read_size = 0;
- break;
- case 3:
- ld->pip2_file_data.file_handle = ic_buffer[0];
- ld->pip2_file_data.file_offset = ic_buffer[1];
- ld->pip2_file_data.file_read_size = ic_buffer[2];
- break;
- default:
- break;
- }
- ld->pip2_file_data.para_num = length;
- error:
- pt_debug(dev, DL_INFO,
- "%s: %s=%d, %s=%d, %s=%d, %s=%d, %s=%d\n",
- __func__,
- "para_num", ld->pip2_file_data.para_num,
- "handle", ld->pip2_file_data.file_handle,
- "offset", ld->pip2_file_data.file_offset,
- "read", ld->pip2_file_data.file_read_size,
- "print", ld->pip2_file_data.file_print_size);
- if (rc)
- return rc;
- return count;
- }
- static struct bin_attribute bin_attr_pip2_file_read = {
- .attr = {
- .name = "pip2_file_read",
- .mode = (0644),
- },
- .read = pt_pip2_file_read_show,
- .write = pt_pip2_file_read_store,
- };
- /******************************************************************************
- * FUNCTION: pt_pip2_file_crc_show
- *
- * SUMMARY: The show method for the "pip2_file_crc" sysfs node.
- * Shows the CRC of a file or portion of the file.
- *
- * NOTE: If function is called when DUT is already in BL mode, the DUT
- * will remain in BL mode when function exits, however if DUT is in
- * normal mode when function is called, the DUT will be forced into BL
- * mode and then returned to normal mode when function exits.
- *
- * NOTE: This sysfs node only can be used for BL version 1.8 or greater.
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *attr - pointer to device attributes structure
- * *buf - pointer to print output buffer
- ******************************************************************************/
- static ssize_t pt_pip2_file_crc_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- struct pt_core_data *cd = dev_get_drvdata(dev);
- int rc = 0;
- u8 file_handle;
- int print_idx = 0;
- u8 read_buf[PT_MAX_PIP2_MSG_SIZE];
- u32 address, file_size;
- u32 length;
- u32 offset;
- u16 file_crc;
- u16 status;
- if (ld->pip2_fcrc.para_num == 0 ||
- ld->pip2_fcrc.file_handle == 0 ||
- ld->pip2_fcrc.file_read_size < 0 ||
- ld->pip2_fcrc.file_offset < 0) {
- pt_debug(dev, DL_ERROR,
- "%s: Invalid parameters!\n",
- __func__);
- print_idx = scnprintf(buf, PT_MAX_PRBUF_SIZE,
- "Status: %d\n"
- "Invalid parameters!\n", -EINVAL);
- return print_idx;
- }
- file_handle = ld->pip2_fcrc.file_handle;
- offset = ld->pip2_fcrc.file_offset;
- length = ld->pip2_fcrc.file_read_size;
- /* This functionality is only available in the BL */
- if (cd->mode != PT_MODE_BOOTLOADER) {
- rc = -EPERM;
- print_idx = scnprintf(buf, PT_MAX_PRBUF_SIZE,
- "Status: %d\n", rc);
- goto exit;
- }
- rc = cmd->request_exclusive(dev, PT_LDR_REQUEST_EXCLUSIVE_TIMEOUT);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Failed to request exclusive rc=%d\n",
- __func__, rc);
- print_idx = scnprintf(buf, PT_MAX_PRBUF_SIZE,
- "Status: %d\n", rc);
- goto exit;
- }
- rc = cmd->nonhid_cmd->pip2_file_open(dev, file_handle);
- if (rc < 0) {
- pt_debug(dev, DL_ERROR,
- "%s: Failed to file_open rc=%d\n",
- __func__, rc);
- print_idx = scnprintf(buf, PT_MAX_PRBUF_SIZE,
- "Status: %d\n", rc);
- goto exit_release;
- }
- rc = cmd->nonhid_cmd->pip2_file_get_stats(dev, file_handle,
- &address, &file_size);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Failed to get_file_state rc=%d\n",
- __func__, rc);
- print_idx = scnprintf(buf, PT_MAX_PRBUF_SIZE,
- "Status: %d\n", rc);
- goto exit_file_close;
- }
- ld->pip2_fcrc.file_max_size = file_size;
- if (ld->pip2_fcrc.file_read_size > file_size
- || ld->pip2_fcrc.file_offset > file_size
- || ((ld->pip2_fcrc.file_offset +
- ld->pip2_fcrc.file_read_size) > file_size)) {
- pt_debug(dev, DL_ERROR,
- "%s: Invalid parameters!\n",
- __func__);
- print_idx = scnprintf(buf, PT_MAX_PRBUF_SIZE,
- "Status: %d\n", rc);
- goto exit_file_close;
- }
- rc = cmd->nonhid_cmd->pip2_file_crc(dev,
- file_handle, offset, length, read_buf);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Failed to get file crc, rc=%d\n",
- __func__, rc);
- print_idx = scnprintf(buf, PT_MAX_PRBUF_SIZE,
- "Status: %d\n", rc);
- } else {
- status = read_buf[PIP2_RESP_STATUS_OFFSET];
- if (status == PIP2_RSP_ERR_NONE) {
- file_crc = get_unaligned_le16(&read_buf[5]);
- print_idx = scnprintf(buf, PT_MAX_PRBUF_SIZE,
- "Status: %d\n"
- "FILE CRC: %04X\n",
- status, file_crc);
- } else
- print_idx = scnprintf(buf, PT_MAX_PRBUF_SIZE,
- "Status: %d\n"
- "FILE CRC: n/a\n",
- status);
- }
- exit_file_close:
- rc = cmd->nonhid_cmd->pip2_file_close(dev, file_handle);
- if (file_handle != rc)
- pt_debug(dev, DL_ERROR,
- "%s Failed to close file %d, rc = %d\n", __func__,
- file_handle, rc);
- exit_release:
- cmd->release_exclusive(dev);
- exit:
- ld->pip2_fcrc.para_num = 0;
- return print_idx;
- }
- /*******************************************************************************
- * FUNCTION: pt_pip2_file_crc_store
- *
- * SUMMARY: The store method for the "pip2_file_crc" sysfs node. The passed in
- * data including file_handle, offset and read size are needed by show method.
- *
- * NOTE: This sysfs node only can be used for BL version 1.8 or greater..
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *attr - pointer to device attributes structure
- * *buf - pointer to print output buffer
- * size - size of buffer
- ******************************************************************************/
- static ssize_t pt_pip2_file_crc_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- u32 input_data[4] = {0};
- int length;
- int rc = 0;
- ld->pip2_fcrc.file_handle = PIP2_RAM_FILE;
- ld->pip2_fcrc.file_offset = -1;
- ld->pip2_fcrc.file_read_size = -1;
- length = cmd->parse_sysfs_input(dev, buf, size, input_data,
- ARRAY_SIZE(input_data));
- if (length != 3) {
- pt_debug(dev, DL_WARN, "%s: Invalid number of arguments\n",
- __func__);
- ld->pip2_fcrc.para_num = 0;
- rc = -EINVAL;
- goto exit;
- }
- if ((input_data[0] < PIP2_FW_FILE) || (input_data[0] > PIP2_FILE_MAX)) {
- pt_debug(dev, DL_WARN, "%s: Invalid file_no %d\n",
- __func__, input_data[0]);
- rc = -EINVAL;
- goto exit;
- }
- ld->pip2_fcrc.file_handle = input_data[0];
- ld->pip2_fcrc.file_offset = input_data[1];
- ld->pip2_fcrc.file_read_size = input_data[2];
- ld->pip2_fcrc.para_num = 3;
- pt_debug(dev, DL_INFO,
- "%s: %s=%d, %s=%d, %s=%d, %s=%d\n",
- __func__,
- "para_num", ld->pip2_fcrc.para_num,
- "handle", ld->pip2_fcrc.file_handle,
- "offset", ld->pip2_fcrc.file_offset,
- "length", ld->pip2_fcrc.file_read_size);
- exit:
- if (rc)
- return rc;
- return size;
- }
- static DEVICE_ATTR(pip2_file_crc, 0644,
- pt_pip2_file_crc_show, pt_pip2_file_crc_store);
- #endif
- /*******************************************************************************
- * FUNCTION: pt_pip2_file_erase_show
- *
- * SUMMARY: The show method for the "pip2_file_erase" sysfs node.
- * Prints current erase status to output buffer.
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *attr - pointer to device attributes structure
- * *buf - pointer to print output buffer
- ******************************************************************************/
- static ssize_t pt_pip2_file_erase_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- struct pt_core_data *cd = dev_get_drvdata(dev);
- u8 file_handle;
- u8 file = ld->pip2_file_erase_file_no;
- int rc;
- pip2_erase_status = -1;
- pip2_erase_rc = 0;
- if (file == PIP2_RAM_FILE) {
- rc = -EINVAL;
- goto exit;
- }
- /* This functionality is only available in the BL */
- if (cd->mode != PT_MODE_BOOTLOADER) {
- rc = -EPERM;
- goto exit;
- }
- rc = cmd->request_exclusive(dev, PT_LDR_REQUEST_EXCLUSIVE_TIMEOUT);
- if (rc < 0) {
- pt_debug(dev, DL_ERROR,
- "%s: Failed to get exclusive access rc=%d\n",
- __func__, rc);
- goto exit;
- }
- file_handle = cmd->nonhid_cmd->pip2_file_open(dev, file);
- if (file_handle != file) {
- rc = -EBADF;
- goto exit_release;
- }
- file_handle = cmd->nonhid_cmd->pip2_file_erase(dev, file,
- &pip2_erase_status);
- if (file_handle < 0) {
- rc = file_handle;
- pt_debug(dev, DL_INFO, "%s: File erase error rc = %d\n",
- __func__, rc);
- } else if (file_handle == file) {
- pt_debug(dev, DL_INFO, "%s: File %d erased\n",
- __func__, file_handle);
- } else {
- rc = -EBADF;
- }
- file_handle = cmd->nonhid_cmd->pip2_file_close(dev, file);
- if (file_handle != file && !rc)
- rc = -EBADF;
- exit_release:
- cmd->release_exclusive(dev);
- exit:
- pip2_erase_rc = rc;
- if (pip2_erase_status == -1) {
- return scnprintf(buf, PT_MAX_PRBUF_SIZE,
- "Status: %d\n"
- "Erase Status: n/a\n",
- pip2_erase_rc);
- }
- return scnprintf(buf, PT_MAX_PRBUF_SIZE,
- "Status: %d\n"
- "Erase Status: 0x%02X\n",
- pip2_erase_rc, pip2_erase_status);
- }
- /*******************************************************************************
- * FUNCTION: pt_pip2_file_erase_store
- *
- * SUMMARY: The store method for the "pip2_file_erase" sysfs node. Allows the
- * caller to provide the file number to erase in FLASH.
- *
- * NOTE: The DUT must be in BL mode before calling this function.
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *attr - pointer to device attributes structure
- * *buf - pointer to print output buffer
- * size - size of buffer
- ******************************************************************************/
- static ssize_t pt_pip2_file_erase_store(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t size)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- u32 input_data[2] = {0};
- int length;
- int rc = 0;
- length = cmd->parse_sysfs_input(dev, buf, size, input_data,
- ARRAY_SIZE(input_data));
- if (length != 1) {
- pt_debug(dev, DL_WARN, "%s: Invalid number of arguments\n",
- __func__);
- rc = -EINVAL;
- goto exit;
- }
- /* Only allow valid files to be erased */
- if (input_data[0] < PIP2_FW_FILE || input_data[0] > PIP2_FILE_MAX) {
- pip2_erase_status = PIP2_RSP_ERR_BAD_FILE;
- pt_debug(dev, DL_ERROR, "%s: ERROR - Invalid File\n",
- __func__);
- rc = -EINVAL;
- goto exit;
- }
- ld->pip2_file_erase_file_no = input_data[0];
- exit:
- if (rc)
- return rc;
- return size;
- }
- static DEVICE_ATTR(pip2_file_erase, 0644,
- pt_pip2_file_erase_show, pt_pip2_file_erase_store);
- /*******************************************************************************
- * FUNCTION: pt_pip2_bl_status_show
- *
- * SUMMARY: The show method for the pip2_bl_status sysfs node.
- * Shows the percent completion of the current BL or an error message.
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *attr - pointer to device attributes structure
- * *buf - pointer to print output buffer
- ******************************************************************************/
- static ssize_t pt_pip2_bl_status_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- ssize_t ret;
- u8 status = update_fw_status;
- if (update_fw_status <= UPDATE_FW_COMPLETE) {
- pt_debug(dev, DL_DEBUG,
- "%s BL_STATUS = %d\n", __func__, update_fw_status);
- return scnprintf(buf, strlen(buf), "%d\n", update_fw_status);
- }
- switch (status) {
- case UPDATE_FW_GENERAL_ERROR:
- ret = scnprintf(buf, strlen(buf),
- "ERROR: %d - General programming failure\n", status);
- break;
- case UPDATE_FW_PIP_VERSION_ERROR:
- ret = scnprintf(buf, strlen(buf),
- "ERROR: %d - Wrong PIP version detected\n", status);
- break;
- case UPDATE_FW_VERSION_ERROR:
- ret = scnprintf(buf, strlen(buf),
- "ERROR: %d - FW vervion newer than bin file\n", status);
- break;
- case UPDATE_FW_ERASE_ERROR:
- ret = scnprintf(buf, strlen(buf),
- "ERROR: %d - ROM BL failed to erase FW file in FLASH\n",
- status);
- break;
- case UPDATE_FW_FILE_CLOSE_ERROR:
- ret = scnprintf(buf, strlen(buf),
- "ERROR: %d - ROM BL failed to close FW file in FLASH\n",
- status);
- break;
- case UPDATE_FW_WRITE_ERROR:
- ret = scnprintf(buf, strlen(buf),
- "ERROR: %d - ROM BL file write failure\n", status);
- break;
- case UPDATE_FW_EXECUTE_ERROR:
- ret = scnprintf(buf, strlen(buf),
- "ERROR: %d - ROM BL failed to execute RAM image\n",
- status);
- break;
- case UPDATE_FW_RESET_ERROR:
- ret = scnprintf(buf, strlen(buf),
- "ERROR: %d - Reset DUT failure\n",
- status);
- break;
- case UPDATE_FW_MODE_ERROR:
- ret = scnprintf(buf, strlen(buf),
- "ERROR: %d - Program complete, Incorrect BL/APP mode detected after reset sentinel\n",
- status);
- break;
- case UPDATE_FW_ENTER_BL_ERROR:
- ret = scnprintf(buf, strlen(buf),
- "ERROR: %d - Could not enter the BL\n", status);
- break;
- case UPDATE_FW_FILE_OPEN_ERROR:
- ret = scnprintf(buf, strlen(buf),
- "ERROR: %d - ROM BL failed to open FW file in FLASH\n",
- status);
- break;
- case UPDATE_FW_SENTINEL_NOT_SEEN:
- ret = scnprintf(buf, strlen(buf),
- "ERROR: %d - FW Reset Sentinel not seen after XRES\n",
- status);
- break;
- case UPDATE_FW_EXCLUSIVE_ACCESS_ERROR:
- ret = scnprintf(buf, strlen(buf),
- "ERROR: %d - Failed to get DUT exclusive access\n",
- status);
- break;
- case UPDATE_FW_NO_FW_PROVIDED:
- ret = scnprintf(buf, strlen(buf),
- "ERROR: %d - No FW provided to load\n", status);
- break;
- case UPDATE_FW_INVALID_FW_IMAGE:
- ret = scnprintf(buf, strlen(buf), "ERROR: %d - Invalid FW image\n", status);
- break;
- case UPDATE_FW_MISALIGN_FW_IMAGE:
- ret = scnprintf(buf, strlen(buf),
- "ERROR: %d - FW image is misaligned\n", status);
- break;
- case UPDATE_FW_SYSTEM_NOMEM:
- ret = scnprintf(buf, strlen(buf),
- "ERROR: %d - Failed to alloc memory\n", status);
- break;
- case UPDATE_FW_INIT_BL_ERROR:
- ret = scnprintf(buf, strlen(buf),
- "ERROR: %d - Failed to init bootloader\n", status);
- break;
- case UPDATE_FW_PARSE_ROW_ERROR:
- ret = scnprintf(buf, strlen(buf),
- "ERROR: %d - Failed to parse row of FW image\n",
- status);
- break;
- case UPDATE_FW_PROGRAM_ROW_ERROR:
- ret = scnprintf(buf, strlen(buf),
- "ERROR: %d - Failed to progrem FW image\n", status);
- break;
- case UPDATE_FW_EXIT_BL_ERROR:
- ret = scnprintf(buf, strlen(buf),
- "ERROR: %d - Failed to exit bootloader\n", status);
- break;
- case UPDATE_FW_CHECK_SUM_ERROR:
- ret = scnprintf(buf, strlen(buf),
- "ERROR: %d - Failed to verify app checksum\n", status);
- break;
- case UPDATE_FW_NO_PLATFORM_DATA:
- ret = scnprintf(buf, strlen(buf),
- "ERROR: %d - No platform data\n", status);
- break;
- case UPDATE_FW_UNDEFINED_ERROR:
- default:
- ret = scnprintf(buf, strlen(buf), "ERROR: %d - Unknown error\n", status);
- break;
- }
- return ret;
- }
- static DEVICE_ATTR(pip2_bl_status, 0444, pt_pip2_bl_status_show, NULL);
- #if PT_FW_UPGRADE
- static DEVICE_ATTR(update_fw_status, 0444, pt_pip2_bl_status_show, NULL);
- #endif
- /*******************************************************************************
- * FUNCTION: pt_pip2_get_last_error_show
- *
- * SUMMARY: The show method for the pip2_get_last_error_show sysfs node.
- * Shows the last BL error code.
- *
- * NOTE: If function is called when DUT is already in BL mode, the DUT
- * will remain in BL mode when function exits, however if DUT is in
- * normal mode when function is called, the DUT will be forced into BL
- * mode and then returned to normal mode when function exits.
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *attr - pointer to device attributes structure
- * *buf - pointer to print output buffer
- ******************************************************************************/
- static ssize_t pt_pip2_get_last_error_show(struct device *dev,
- struct device_attribute *attr, char *buf)
- {
- struct pt_core_data *cd = dev_get_drvdata(dev);
- int rc;
- u8 read_buf[256];
- rc = cmd->request_exclusive(dev, PT_LDR_REQUEST_EXCLUSIVE_TIMEOUT);
- if (rc)
- goto exit;
- cmd->request_stop_wd(dev);
- /* This functionality is only available in the BL */
- if (cd->mode != PT_MODE_BOOTLOADER) {
- rc = -EPERM;
- goto exit_release;
- }
- /* Get and log the last error(s) */
- rc = _pt_pip2_log_last_error(dev, read_buf);
- exit_release:
- cmd->release_exclusive(dev);
- exit:
- if (rc)
- return scnprintf(buf, PT_MAX_PRBUF_SIZE, "Status: %d\n", rc);
- if (read_buf[PIP2_RESP_STATUS_OFFSET] == PIP2_RSP_ERR_NONE) {
- return scnprintf(buf, PT_MAX_PRBUF_SIZE,
- "Status: %d\n"
- "Last Error No: 0x%02X\n",
- PIP2_RSP_ERR_NONE,
- read_buf[PIP2_RESP_BODY_OFFSET]);
- } else {
- return scnprintf(buf, PT_MAX_PRBUF_SIZE,
- "Status: %d\n"
- "Last Error No: n/a\n",
- read_buf[PIP2_RESP_STATUS_OFFSET]);
- }
- }
- static DEVICE_ATTR(pip2_get_last_error, 0444,
- pt_pip2_get_last_error_show, NULL);
- #if PT_FW_UPGRADE
- /*******************************************************************************
- * FUNCTION: pt_loader_attention
- *
- * SUMMARY: Function to be registered to TTDL attention list to set up
- * int_running semaphore.
- *
- * RETURN:
- * 0 = success
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- ******************************************************************************/
- static int pt_loader_attention(struct device *dev)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- complete(&ld->int_running);
- return 0;
- }
- /*******************************************************************************
- * FUNCTION: pt_fw_upgrade_cb
- *
- * SUMMARY: Function to be registered to TTDL attention list to allow upgrade
- * if host cannot get response from firmware with ping command.
- * RETURN:
- * 0 = success
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- ******************************************************************************/
- static int pt_fw_upgrade_cb(struct device *dev)
- {
- u8 dut_gen = cmd->request_dut_generation(dev);
- #ifdef CONFIG_TOUCHSCREEN_PARADE_PLATFORM_FW_UPGRADE
- if (dut_gen == DUT_PIP1_ONLY) {
- pt_debug(dev, DL_WARN, "%s: Upgrade Platform FW", __func__);
- if (!upgrade_firmware_from_platform(dev, false))
- return 0;
- }
- #endif
- #ifdef CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE
- pt_debug(dev, DL_WARN, "%s: Upgrade Builtin FW", __func__);
- if (dut_gen == DUT_PIP2_CAPABLE) {
- if (!pt_pip2_upgrade_firmware_from_builtin(dev))
- return 0;
- pt_debug(dev, DL_WARN, "%s: Builtin FW upgrade failed",
- __func__);
- } else {
- if (!upgrade_firmware_from_builtin(dev))
- return 0;
- }
- #endif
- return 0;
- }
- /*******************************************************************************
- * FUNCTION: pt_cancel_fw_upgrade_cb
- *
- * SUMMARY: Function to be registered to TTDL attention list to allow an upgrade
- * to be canceled.
- * RETURN:
- * 0 = success
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- ******************************************************************************/
- static int pt_cancel_fw_upgrade_cb(struct device *dev)
- {
- struct pt_loader_data *ld = pt_get_loader_data(dev);
- pt_debug(dev, DL_WARN,
- "%s: CANCELLING All Loader work\n", __func__);
- cancel_work_sync(&ld->bl_from_file);
- cancel_work_sync(&ld->pip2_bl_from_file);
- cancel_work_sync(&ld->calibration_work);
- cancel_work_sync(&ld->fw_and_config_upgrade);
- return 0;
- }
- #endif /* PT_FW_UPGRADE */
- /*******************************************************************************
- * FUNCTION: pt_loader_probe
- *
- * SUMMARY: The probe function for the FW loader.
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * **data - double pointer to the loader data to be created here
- ******************************************************************************/
- static int pt_loader_probe(struct device *dev, void **data)
- {
- struct pt_loader_data *ld;
- struct pip2_loader_data *pip2_data;
- struct pt_platform_data *pdata = dev_get_platdata(dev);
- int rc;
- u8 dut_gen = cmd->request_dut_generation(dev);
- #ifdef TTDL_DIAGNOSTICS
- pt_debug(dev, DL_INFO,
- "%s: entering %s\n", __func__, __func__);
- #endif /* TTDL_DIAGNOSTICS */
- ld = kzalloc(sizeof(*ld), GFP_KERNEL);
- if (!ld) {
- rc = -ENOMEM;
- goto error_alloc_data_failed;
- }
- #if PT_FW_UPGRADE
- /* Initialize boot loader status */
- if (update_fw_status != UPDATE_FW_COMPLETE)
- _pt_pip2_update_bl_status(dev, UPDATE_FW_IDLE, PT_NO_INC);
- #endif
- if (dut_gen == DUT_PIP2_CAPABLE) {
- pip2_data = kzalloc(sizeof(*pip2_data), GFP_KERNEL);
- if (!pip2_data) {
- rc = -ENOMEM;
- goto error_alloc_data_failed;
- }
- pip2_data->dev = dev;
- ld->pip2_data = pip2_data;
- #if PT_FW_UPGRADE
- rc = device_create_file(dev, &dev_attr_update_fw_status);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Error creating update_fw_status\n",
- __func__);
- goto remove_files;
- }
- #endif
- #ifdef CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE
- rc = device_create_file(dev, &dev_attr_pt_bl_from_file);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Error creating pt_bl_from_file\n",
- __func__);
- goto remove_files;
- }
- rc = device_create_file(dev, &dev_attr_update_fw);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Error creating update_fw\n",
- __func__);
- goto remove_files;
- }
- #endif /* CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE */
- #ifdef CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE
- rc = device_create_file(dev, &dev_attr_pip2_manual_upgrade);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Error creating pip2_manual_upgrade\n",
- __func__);
- goto remove_files;
- }
- rc = device_create_file(dev, &dev_attr_pip2_manual_ram_upgrade);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Error creating pip2_manual_ram_upgrade\n",
- __func__);
- goto remove_files;
- }
- rc = device_create_file(dev, &dev_attr_pip2_file_write);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Error creating pip2_file_write\n",
- __func__);
- goto remove_files;
- }
- rc = device_create_file(dev, &dev_attr_pip2_bl_from_file);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Error creating pip2_bl_from_file\n",
- __func__);
- goto remove_files;
- }
- #endif /* CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE */
- rc = device_create_file(dev, &dev_attr_pip2_file_erase);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Error creating pip2_file_erase\n",
- __func__);
- goto remove_files;
- }
- rc = device_create_file(dev, &dev_attr_pip2_bl_status);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Error creating pip2_bl_status\n",
- __func__);
- goto remove_files;
- }
- #ifdef TTDL_DIAGNOSTICS
- rc = device_create_file(dev, &dev_attr_pip2_get_last_error);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Error creating pip2_get_last_error\n",
- __func__);
- goto remove_files;
- }
- rc = device_create_bin_file(dev, &bin_attr_pip2_file_read);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Error creating bin_attr_pip2_file_read\n",
- __func__);
- goto remove_files;
- }
- rc = device_create_file(dev, &dev_attr_pip2_file_crc);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Error creating pip2_file_crc\n",
- __func__);
- goto remove_files;
- }
- #endif
- } else {
- #if PT_FW_UPGRADE
- rc = device_create_file(dev, &dev_attr_update_fw_status);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Error creating update_fw_status\n",
- __func__);
- goto remove_files;
- }
- #endif
- #ifdef CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE
- rc = device_create_file(dev, &dev_attr_pt_bl_from_file);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Error creating pt_bl_from_file\n",
- __func__);
- goto remove_files;
- }
- rc = device_create_file(dev, &dev_attr_update_fw);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Error creating update_fw\n",
- __func__);
- goto remove_files;
- }
- #endif /* CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE */
- #ifdef CONFIG_TOUCHSCREEN_PARADE_PLATFORM_FW_UPGRADE
- rc = device_create_file(dev, &dev_attr_forced_upgrade);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Error creating forced_upgrade\n",
- __func__);
- goto remove_files;
- }
- #endif /* CONFIG_TOUCHSCREEN_PARADE_PLATFORM_FW_UPGRADE */
- #ifdef CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE
- rc = device_create_file(dev, &dev_attr_manual_upgrade);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Error creating manual_upgrade\n",
- __func__);
- goto remove_files;
- }
- #endif /* CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE */
- #ifdef CONFIG_TOUCHSCREEN_PARADE_MANUAL_TTCONFIG_UPGRADE
- rc = device_create_file(dev, &dev_attr_config_loading);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Error creating config_loading\n",
- __func__);
- goto remove_files;
- }
- rc = device_create_bin_file(dev, &bin_attr_config_data);
- if (rc) {
- pt_debug(dev, DL_ERROR,
- "%s: Error creating config_data\n",
- __func__);
- goto remove_files;
- }
- #endif /* CONFIG_TOUCHSCREEN_PARADE_MANUAL_TTCONFIG_UPGRADE */
- }
- if (!pdata || !pdata->loader_pdata) {
- pt_debug(dev, DL_ERROR,
- "%s: Missing platform data\n", __func__);
- rc = -ENODEV;
- goto error_no_pdata;
- }
- /* Default erase file to an invalid file */
- ld->pip2_file_erase_file_no = PIP2_RAM_FILE;
- ld->loader_pdata = pdata->loader_pdata;
- ld->dev = dev;
- *data = ld;
- #ifdef CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE
- INIT_WORK(&ld->bl_from_file, pt_bl_from_file_work);
- INIT_WORK(&ld->pip2_bl_from_file, pt_pip2_bl_from_file_work);
- #endif /* CONFIG_TOUCHSCREEN_PARADE_MANUAL_TTCONFIG_UPGRADE */
- #if PT_FW_UPGRADE
- init_completion(&ld->int_running);
- cmd->subscribe_attention(dev, PT_ATTEN_IRQ, PT_LOADER_NAME,
- pt_loader_attention, PT_MODE_BOOTLOADER);
- cmd->subscribe_attention(dev, PT_ATTEN_LOADER, PT_LOADER_NAME,
- pt_fw_upgrade_cb, PT_MODE_UNKNOWN);
- cmd->subscribe_attention(dev, PT_ATTEN_CANCEL_LOADER, PT_LOADER_NAME,
- pt_cancel_fw_upgrade_cb, PT_MODE_UNKNOWN);
- #endif
- #if PT_FW_UPGRADE || PT_TTCONFIG_UPGRADE
- pt_debug(dev, DL_INFO, "%s: INIT_WORK pt_calibrate_idacs\n",
- __func__);
- init_completion(&ld->calibration_complete);
- INIT_WORK(&ld->calibration_work, pt_calibrate_idacs);
- #endif
- #ifdef CONFIG_TOUCHSCREEN_PARADE_MANUAL_TTCONFIG_UPGRADE
- if (dut_gen == DUT_PIP1_ONLY)
- mutex_init(&ld->config_lock);
- #endif
- pt_debug(dev, DL_INFO, "%s: Schedule FW upgrade work\n", __func__);
- INIT_WORK(&ld->fw_and_config_upgrade, pt_fw_and_config_upgrade);
- schedule_work(&ld->fw_and_config_upgrade);
- pt_debug(dev, DL_INFO, "%s: Successful probe %s\n",
- __func__, dev_name(dev));
- return 0;
- remove_files:
- #ifdef CONFIG_TOUCHSCREEN_PARADE_MANUAL_TTCONFIG_UPGRADE
- device_remove_file(dev, &dev_attr_config_loading);
- #endif
- #ifdef CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE
- device_remove_file(dev, &dev_attr_manual_upgrade);
- #endif
- #ifdef CONFIG_TOUCHSCREEN_PARADE_PLATFORM_FW_UPGRADE
- device_remove_file(dev, &dev_attr_forced_upgrade);
- #endif
- #ifdef TTDL_DIAGNOSTICS
- device_remove_file(dev, &dev_attr_pip2_get_last_error);
- device_remove_bin_file(dev, &bin_attr_pip2_file_read);
- device_remove_file(dev, &dev_attr_pip2_file_crc);
- #endif
- device_remove_file(dev, &dev_attr_pip2_bl_status);
- device_remove_file(dev, &dev_attr_pip2_file_erase);
- #ifdef CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE
- device_remove_file(dev, &dev_attr_pip2_bl_from_file);
- device_remove_file(dev, &dev_attr_pip2_file_write);
- device_remove_file(dev, &dev_attr_pt_bl_from_file);
- device_remove_file(dev, &dev_attr_pip2_manual_ram_upgrade);
- device_remove_file(dev, &dev_attr_pip2_manual_upgrade);
- device_remove_file(dev, &dev_attr_update_fw);
- device_remove_file(dev, &dev_attr_update_fw_status);
- #endif /* CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE */
- kfree(ld->pip2_data);
- kfree(ld);
- error_alloc_data_failed:
- error_no_pdata:
- pt_debug(dev, DL_ERROR, "%s failed.\n", __func__);
- return rc;
- }
- /*******************************************************************************
- * FUNCTION: pt_loader_release
- *
- * SUMMARY: Remove function for loader module that does following cleanup:
- * - Unsubscibe all registered attention tasks
- * - Removes all created sysfs nodes
- * - Frees all pointers
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *data - pointer to the loader data
- ******************************************************************************/
- static void pt_loader_release(struct device *dev, void *data)
- {
- struct pt_loader_data *ld = (struct pt_loader_data *)data;
- u8 dut_gen = cmd->request_dut_generation(dev);
- #if PT_FW_UPGRADE
- cmd->unsubscribe_attention(dev, PT_ATTEN_IRQ, PT_LOADER_NAME,
- pt_loader_attention, PT_MODE_BOOTLOADER);
- cmd->unsubscribe_attention(dev, PT_ATTEN_LOADER, PT_LOADER_NAME,
- pt_fw_upgrade_cb, PT_MODE_UNKNOWN);
- cmd->unsubscribe_attention(dev, PT_ATTEN_CANCEL_LOADER, PT_LOADER_NAME,
- pt_cancel_fw_upgrade_cb, PT_MODE_UNKNOWN);
- #endif
- #if PT_FW_UPGRADE
- device_remove_file(dev, &dev_attr_update_fw_status);
- #endif
- if (dut_gen == DUT_PIP2_CAPABLE) {
- #ifdef CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE
- device_remove_file(dev, &dev_attr_update_fw);
- #endif /* CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE */
- #ifdef TTDL_DIAGNOSTICS
- device_remove_bin_file(dev, &bin_attr_pip2_file_read);
- device_remove_file(dev, &dev_attr_pip2_file_crc);
- #endif
- device_remove_file(dev, &dev_attr_pip2_get_last_error);
- device_remove_file(dev, &dev_attr_pip2_bl_status);
- device_remove_file(dev, &dev_attr_pip2_file_erase);
- #ifdef CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE
- device_remove_file(dev, &dev_attr_pip2_file_write);
- device_remove_file(dev, &dev_attr_pip2_bl_from_file);
- device_remove_file(dev, &dev_attr_pt_bl_from_file);
- device_remove_file(dev, &dev_attr_pip2_manual_ram_upgrade);
- device_remove_file(dev, &dev_attr_pip2_manual_upgrade);
- #endif /* CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE */
- kfree(ld->pip2_data);
- } else {
- #ifdef CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE
- device_remove_file(dev, &dev_attr_update_fw);
- #endif /* CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE */
- #ifdef CONFIG_TOUCHSCREEN_PARADE_MANUAL_TTCONFIG_UPGRADE
- device_remove_bin_file(dev, &bin_attr_config_data);
- device_remove_file(dev, &dev_attr_config_loading);
- if (!ld->config_data)
- kfree(ld->config_data);
- #endif /* CONFIG_TOUCHSCREEN_PARADE_MANUAL_TTCONFIG_UPGRADE */
- #ifdef CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE
- device_remove_file(dev, &dev_attr_pt_bl_from_file);
- device_remove_file(dev, &dev_attr_manual_upgrade);
- #endif /* CONFIG_TOUCHSCREEN_PARADE_BINARY_FW_UPGRADE */
- #ifdef CONFIG_TOUCHSCREEN_PARADE_PLATFORM_FW_UPGRADE
- device_remove_file(dev, &dev_attr_forced_upgrade);
- #endif /* CONFIG_TOUCHSCREEN_PARADE_PLATFORM_FW_UPGRADE */
- }
- kfree(ld);
- }
- static struct pt_module loader_module = {
- .name = PT_LOADER_NAME,
- .probe = pt_loader_probe,
- .release = pt_loader_release,
- };
- /*******************************************************************************
- * FUNCTION: pt_loader_init
- *
- * SUMMARY: Initialize function for loader module which to register
- * loader_module into TTDL module list.
- *
- * RETURN:
- * 0 = success
- * !0 = failure
- *
- * PARAMETERS:
- * *dev - pointer to device structure
- * *data - pointer to the loader data
- ******************************************************************************/
- static int __init pt_loader_init(void)
- {
- int rc;
- cmd = pt_get_commands();
- if (!cmd)
- return -EINVAL;
- rc = pt_register_module(&loader_module);
- if (rc < 0) {
- pr_err("%s: Error, failed registering module\n",
- __func__);
- return rc;
- }
- pr_info("%s: Parade FW Loader Driver (Version %s) rc=%d\n",
- __func__, PT_DRIVER_VERSION, rc);
- return 0;
- }
- module_init(pt_loader_init);
- /*******************************************************************************
- * FUNCTION: pt_loader_exit
- *
- * SUMMARY: Exit function for loader module which to unregister loader_module
- * from TTDL module list.
- *
- ******************************************************************************/
- static void __exit pt_loader_exit(void)
- {
- pt_unregister_module(&loader_module);
- }
- module_exit(pt_loader_exit);
- MODULE_LICENSE("GPL");
- MODULE_DESCRIPTION("Parade TrueTouch(R) Standard Product FW Loader Driver");
- MODULE_AUTHOR("Parade Technologies <[email protected]>");
|