0005-surface-sam.patch 151 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445
  1. From 17f1e21d9b782aa7d25a446b3663b72c055fd7d7 Mon Sep 17 00:00:00 2001
  2. From: Maximilian Luz <luzmaximilian@gmail.com>
  3. Date: Fri, 27 May 2022 04:34:36 +0200
  4. Subject: [PATCH] platform/surface: aggregator: Allow is_ssam_device() to be
  5. used when CONFIG_SURFACE_AGGREGATOR_BUS is disabled
  6. In SSAM subsystem drivers that handle both ACPI and SSAM-native client
  7. devices, we may want to check whether we have a SSAM (native) client
  8. device. Further, we may want to do this even when instantiation thereof
  9. cannot happen due to CONFIG_SURFACE_AGGREGATOR_BUS=n. Currently, doing
  10. so causes an error due to an undefined reference error due to
  11. ssam_device_type being placed in the bus source unit.
  12. Therefore, if CONFIG_SURFACE_AGGREGATOR_BUS is not defined, simply let
  13. is_ssam_device() return false to prevent this error.
  14. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  15. Link: https://lore.kernel.org/r/20220527023447.2460025-2-luzmaximilian@gmail.com
  16. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  17. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  18. Patchset: surface-sam
  19. ---
  20. include/linux/surface_aggregator/device.h | 11 +++++++++++
  21. 1 file changed, 11 insertions(+)
  22. diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h
  23. index cc257097eb05..62b38b4487eb 100644
  24. --- a/include/linux/surface_aggregator/device.h
  25. +++ b/include/linux/surface_aggregator/device.h
  26. @@ -177,6 +177,8 @@ struct ssam_device_driver {
  27. void (*remove)(struct ssam_device *sdev);
  28. };
  29. +#ifdef CONFIG_SURFACE_AGGREGATOR_BUS
  30. +
  31. extern struct bus_type ssam_bus_type;
  32. extern const struct device_type ssam_device_type;
  33. @@ -193,6 +195,15 @@ static inline bool is_ssam_device(struct device *d)
  34. return d->type == &ssam_device_type;
  35. }
  36. +#else /* CONFIG_SURFACE_AGGREGATOR_BUS */
  37. +
  38. +static inline bool is_ssam_device(struct device *d)
  39. +{
  40. + return false;
  41. +}
  42. +
  43. +#endif /* CONFIG_SURFACE_AGGREGATOR_BUS */
  44. +
  45. /**
  46. * to_ssam_device() - Casts the given device to a SSAM client device.
  47. * @d: The device to cast.
  48. --
  49. 2.37.2
  50. From 64ea57d5ed105ab1a046ed0ca5f0ad3f29470101 Mon Sep 17 00:00:00 2001
  51. From: Maximilian Luz <luzmaximilian@gmail.com>
  52. Date: Fri, 27 May 2022 04:34:37 +0200
  53. Subject: [PATCH] platform/surface: aggregator: Allow devices to be marked as
  54. hot-removed
  55. Some SSAM devices, notably the keyboard cover (keyboard and touchpad) on
  56. the Surface Pro 8, can be hot-removed. When this occurs, communication
  57. with the device may fail and time out. This timeout can unnecessarily
  58. block and slow down device removal and even cause issues when the
  59. devices are detached and re-attached quickly. Thus, communication should
  60. generally be avoided once hot-removal is detected.
  61. While we already remove a device as soon as we detect its (hot-)removal,
  62. the corresponding device driver may still attempt to communicate with
  63. the device during teardown. This is especially critical as communication
  64. failure may also extend to disabling of events, which is typically done
  65. at that stage.
  66. Add a flag to allow marking devices as hot-removed. This can then be
  67. used during client driver teardown to check if any communication
  68. attempts should be avoided.
  69. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  70. Link: https://lore.kernel.org/r/20220527023447.2460025-3-luzmaximilian@gmail.com
  71. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  72. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  73. Patchset: surface-sam
  74. ---
  75. include/linux/surface_aggregator/device.h | 48 +++++++++++++++++++++--
  76. 1 file changed, 45 insertions(+), 3 deletions(-)
  77. diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h
  78. index 62b38b4487eb..6df7c8d4e50e 100644
  79. --- a/include/linux/surface_aggregator/device.h
  80. +++ b/include/linux/surface_aggregator/device.h
  81. @@ -148,17 +148,30 @@ struct ssam_device_uid {
  82. #define SSAM_SDEV(cat, tid, iid, fun) \
  83. SSAM_DEVICE(SSAM_DOMAIN_SERIALHUB, SSAM_SSH_TC_##cat, tid, iid, fun)
  84. +/*
  85. + * enum ssam_device_flags - Flags for SSAM client devices.
  86. + * @SSAM_DEVICE_HOT_REMOVED_BIT:
  87. + * The device has been hot-removed. Further communication with it may time
  88. + * out and should be avoided.
  89. + */
  90. +enum ssam_device_flags {
  91. + SSAM_DEVICE_HOT_REMOVED_BIT = 0,
  92. +};
  93. +
  94. /**
  95. * struct ssam_device - SSAM client device.
  96. - * @dev: Driver model representation of the device.
  97. - * @ctrl: SSAM controller managing this device.
  98. - * @uid: UID identifying the device.
  99. + * @dev: Driver model representation of the device.
  100. + * @ctrl: SSAM controller managing this device.
  101. + * @uid: UID identifying the device.
  102. + * @flags: Device state flags, see &enum ssam_device_flags.
  103. */
  104. struct ssam_device {
  105. struct device dev;
  106. struct ssam_controller *ctrl;
  107. struct ssam_device_uid uid;
  108. +
  109. + unsigned long flags;
  110. };
  111. /**
  112. @@ -251,6 +264,35 @@ struct ssam_device *ssam_device_alloc(struct ssam_controller *ctrl,
  113. int ssam_device_add(struct ssam_device *sdev);
  114. void ssam_device_remove(struct ssam_device *sdev);
  115. +/**
  116. + * ssam_device_mark_hot_removed() - Mark the given device as hot-removed.
  117. + * @sdev: The device to mark as hot-removed.
  118. + *
  119. + * Mark the device as having been hot-removed. This signals drivers using the
  120. + * device that communication with the device should be avoided and may lead to
  121. + * timeouts.
  122. + */
  123. +static inline void ssam_device_mark_hot_removed(struct ssam_device *sdev)
  124. +{
  125. + dev_dbg(&sdev->dev, "marking device as hot-removed\n");
  126. + set_bit(SSAM_DEVICE_HOT_REMOVED_BIT, &sdev->flags);
  127. +}
  128. +
  129. +/**
  130. + * ssam_device_is_hot_removed() - Check if the given device has been
  131. + * hot-removed.
  132. + * @sdev: The device to check.
  133. + *
  134. + * Checks if the given device has been marked as hot-removed. See
  135. + * ssam_device_mark_hot_removed() for more details.
  136. + *
  137. + * Return: Returns ``true`` if the device has been marked as hot-removed.
  138. + */
  139. +static inline bool ssam_device_is_hot_removed(struct ssam_device *sdev)
  140. +{
  141. + return test_bit(SSAM_DEVICE_HOT_REMOVED_BIT, &sdev->flags);
  142. +}
  143. +
  144. /**
  145. * ssam_device_get() - Increment reference count of SSAM client device.
  146. * @sdev: The device to increment the reference count of.
  147. --
  148. 2.37.2
  149. From 66750927a15616256b0e57fad5952d857ceea0cc Mon Sep 17 00:00:00 2001
  150. From: Maximilian Luz <luzmaximilian@gmail.com>
  151. Date: Fri, 27 May 2022 04:34:38 +0200
  152. Subject: [PATCH] platform/surface: aggregator: Allow notifiers to avoid
  153. communication on unregistering
  154. When SSAM client devices have been (physically) hot-removed,
  155. communication attempts with those devices may fail and time out. This
  156. can even extend to event notifiers, due to which timeouts may occur
  157. during device removal, slowing down that process.
  158. Add a parameter to the notifier unregister function that allows skipping
  159. communication with the EC to prevent this. Furthermore, add wrappers for
  160. registering and unregistering notifiers belonging to SSAM client devices
  161. that automatically check if the device has been marked as hot-removed
  162. and communication should be avoided.
  163. Note that non-SSAM client devices can generally not be hot-removed, so
  164. also add a convenience wrapper for those, defaulting to allow
  165. communication.
  166. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  167. Link: https://lore.kernel.org/r/20220527023447.2460025-4-luzmaximilian@gmail.com
  168. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  169. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  170. Patchset: surface-sam
  171. ---
  172. .../driver-api/surface_aggregator/client.rst | 6 +-
  173. .../platform/surface/aggregator/controller.c | 53 ++++++++++-----
  174. include/linux/surface_aggregator/controller.h | 24 ++++++-
  175. include/linux/surface_aggregator/device.h | 66 +++++++++++++++++++
  176. 4 files changed, 128 insertions(+), 21 deletions(-)
  177. diff --git a/Documentation/driver-api/surface_aggregator/client.rst b/Documentation/driver-api/surface_aggregator/client.rst
  178. index e519d374c378..27f95abdbe99 100644
  179. --- a/Documentation/driver-api/surface_aggregator/client.rst
  180. +++ b/Documentation/driver-api/surface_aggregator/client.rst
  181. @@ -17,6 +17,8 @@
  182. .. |SSAM_DEVICE| replace:: :c:func:`SSAM_DEVICE`
  183. .. |ssam_notifier_register| replace:: :c:func:`ssam_notifier_register`
  184. .. |ssam_notifier_unregister| replace:: :c:func:`ssam_notifier_unregister`
  185. +.. |ssam_device_notifier_register| replace:: :c:func:`ssam_device_notifier_register`
  186. +.. |ssam_device_notifier_unregister| replace:: :c:func:`ssam_device_notifier_unregister`
  187. .. |ssam_request_sync| replace:: :c:func:`ssam_request_sync`
  188. .. |ssam_event_mask| replace:: :c:type:`enum ssam_event_mask <ssam_event_mask>`
  189. @@ -312,7 +314,9 @@ Handling Events
  190. To receive events from the SAM EC, an event notifier must be registered for
  191. the desired event via |ssam_notifier_register|. The notifier must be
  192. unregistered via |ssam_notifier_unregister| once it is not required any
  193. -more.
  194. +more. For |ssam_device| type clients, the |ssam_device_notifier_register| and
  195. +|ssam_device_notifier_unregister| wrappers should be preferred as they properly
  196. +handle hot-removal of client devices.
  197. Event notifiers are registered by providing (at minimum) a callback to call
  198. in case an event has been received, the registry specifying how the event
  199. diff --git a/drivers/platform/surface/aggregator/controller.c b/drivers/platform/surface/aggregator/controller.c
  200. index b8c377b3f932..6de834b52b63 100644
  201. --- a/drivers/platform/surface/aggregator/controller.c
  202. +++ b/drivers/platform/surface/aggregator/controller.c
  203. @@ -2199,16 +2199,26 @@ static int ssam_nf_refcount_enable(struct ssam_controller *ctrl,
  204. }
  205. /**
  206. - * ssam_nf_refcount_disable_free() - Disable event for reference count entry if it is
  207. - * no longer in use and free the corresponding entry.
  208. + * ssam_nf_refcount_disable_free() - Disable event for reference count entry if
  209. + * it is no longer in use and free the corresponding entry.
  210. * @ctrl: The controller to disable the event on.
  211. * @entry: The reference count entry for the event to be disabled.
  212. * @flags: The flags used for enabling the event on the EC.
  213. + * @ec: Flag specifying if the event should actually be disabled on the EC.
  214. *
  215. - * If the reference count equals zero, i.e. the event is no longer requested by
  216. - * any client, the event will be disabled and the corresponding reference count
  217. - * entry freed. The reference count entry must not be used any more after a
  218. - * call to this function.
  219. + * If ``ec`` equals ``true`` and the reference count equals zero (i.e. the
  220. + * event is no longer requested by any client), the specified event will be
  221. + * disabled on the EC via the corresponding request.
  222. + *
  223. + * If ``ec`` equals ``false``, no request will be sent to the EC and the event
  224. + * can be considered in a detached state (i.e. no longer used but still
  225. + * enabled). Disabling an event via this method may be required for
  226. + * hot-removable devices, where event disable requests may time out after the
  227. + * device has been physically removed.
  228. + *
  229. + * In both cases, if the reference count equals zero, the corresponding
  230. + * reference count entry will be freed. The reference count entry must not be
  231. + * used any more after a call to this function.
  232. *
  233. * Also checks if the flags used for disabling the event match the flags used
  234. * for enabling the event and warns if they do not (regardless of reference
  235. @@ -2223,7 +2233,7 @@ static int ssam_nf_refcount_enable(struct ssam_controller *ctrl,
  236. * returns the status of the event-enable EC command.
  237. */
  238. static int ssam_nf_refcount_disable_free(struct ssam_controller *ctrl,
  239. - struct ssam_nf_refcount_entry *entry, u8 flags)
  240. + struct ssam_nf_refcount_entry *entry, u8 flags, bool ec)
  241. {
  242. const struct ssam_event_registry reg = entry->key.reg;
  243. const struct ssam_event_id id = entry->key.id;
  244. @@ -2232,8 +2242,9 @@ static int ssam_nf_refcount_disable_free(struct ssam_controller *ctrl,
  245. lockdep_assert_held(&nf->lock);
  246. - ssam_dbg(ctrl, "disabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n",
  247. - reg.target_category, id.target_category, id.instance, entry->refcount);
  248. + ssam_dbg(ctrl, "%s event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n",
  249. + ec ? "disabling" : "detaching", reg.target_category, id.target_category,
  250. + id.instance, entry->refcount);
  251. if (entry->flags != flags) {
  252. ssam_warn(ctrl,
  253. @@ -2242,7 +2253,7 @@ static int ssam_nf_refcount_disable_free(struct ssam_controller *ctrl,
  254. id.instance);
  255. }
  256. - if (entry->refcount == 0) {
  257. + if (ec && entry->refcount == 0) {
  258. status = ssam_ssh_event_disable(ctrl, reg, id, flags);
  259. kfree(entry);
  260. }
  261. @@ -2322,20 +2333,26 @@ int ssam_notifier_register(struct ssam_controller *ctrl, struct ssam_event_notif
  262. EXPORT_SYMBOL_GPL(ssam_notifier_register);
  263. /**
  264. - * ssam_notifier_unregister() - Unregister an event notifier.
  265. - * @ctrl: The controller the notifier has been registered on.
  266. - * @n: The event notifier to unregister.
  267. + * __ssam_notifier_unregister() - Unregister an event notifier.
  268. + * @ctrl: The controller the notifier has been registered on.
  269. + * @n: The event notifier to unregister.
  270. + * @disable: Whether to disable the corresponding event on the EC.
  271. *
  272. * Unregister an event notifier. Decrement the usage counter of the associated
  273. * SAM event if the notifier is not marked as an observer. If the usage counter
  274. - * reaches zero, the event will be disabled.
  275. + * reaches zero and ``disable`` equals ``true``, the event will be disabled.
  276. + *
  277. + * Useful for hot-removable devices, where communication may fail once the
  278. + * device has been physically removed. In that case, specifying ``disable`` as
  279. + * ``false`` avoids communication with the EC.
  280. *
  281. * Return: Returns zero on success, %-ENOENT if the given notifier block has
  282. * not been registered on the controller. If the given notifier block was the
  283. * last one associated with its specific event, returns the status of the
  284. * event-disable EC-command.
  285. */
  286. -int ssam_notifier_unregister(struct ssam_controller *ctrl, struct ssam_event_notifier *n)
  287. +int __ssam_notifier_unregister(struct ssam_controller *ctrl, struct ssam_event_notifier *n,
  288. + bool disable)
  289. {
  290. u16 rqid = ssh_tc_to_rqid(n->event.id.target_category);
  291. struct ssam_nf_refcount_entry *entry;
  292. @@ -2373,7 +2390,7 @@ int ssam_notifier_unregister(struct ssam_controller *ctrl, struct ssam_event_not
  293. goto remove;
  294. }
  295. - status = ssam_nf_refcount_disable_free(ctrl, entry, n->event.flags);
  296. + status = ssam_nf_refcount_disable_free(ctrl, entry, n->event.flags, disable);
  297. }
  298. remove:
  299. @@ -2383,7 +2400,7 @@ int ssam_notifier_unregister(struct ssam_controller *ctrl, struct ssam_event_not
  300. return status;
  301. }
  302. -EXPORT_SYMBOL_GPL(ssam_notifier_unregister);
  303. +EXPORT_SYMBOL_GPL(__ssam_notifier_unregister);
  304. /**
  305. * ssam_controller_event_enable() - Enable the specified event.
  306. @@ -2477,7 +2494,7 @@ int ssam_controller_event_disable(struct ssam_controller *ctrl,
  307. return -ENOENT;
  308. }
  309. - status = ssam_nf_refcount_disable_free(ctrl, entry, flags);
  310. + status = ssam_nf_refcount_disable_free(ctrl, entry, flags, true);
  311. mutex_unlock(&nf->lock);
  312. return status;
  313. diff --git a/include/linux/surface_aggregator/controller.h b/include/linux/surface_aggregator/controller.h
  314. index 74bfdffaf7b0..50a2b4926c06 100644
  315. --- a/include/linux/surface_aggregator/controller.h
  316. +++ b/include/linux/surface_aggregator/controller.h
  317. @@ -835,8 +835,28 @@ struct ssam_event_notifier {
  318. int ssam_notifier_register(struct ssam_controller *ctrl,
  319. struct ssam_event_notifier *n);
  320. -int ssam_notifier_unregister(struct ssam_controller *ctrl,
  321. - struct ssam_event_notifier *n);
  322. +int __ssam_notifier_unregister(struct ssam_controller *ctrl,
  323. + struct ssam_event_notifier *n, bool disable);
  324. +
  325. +/**
  326. + * ssam_notifier_unregister() - Unregister an event notifier.
  327. + * @ctrl: The controller the notifier has been registered on.
  328. + * @n: The event notifier to unregister.
  329. + *
  330. + * Unregister an event notifier. Decrement the usage counter of the associated
  331. + * SAM event if the notifier is not marked as an observer. If the usage counter
  332. + * reaches zero, the event will be disabled.
  333. + *
  334. + * Return: Returns zero on success, %-ENOENT if the given notifier block has
  335. + * not been registered on the controller. If the given notifier block was the
  336. + * last one associated with its specific event, returns the status of the
  337. + * event-disable EC-command.
  338. + */
  339. +static inline int ssam_notifier_unregister(struct ssam_controller *ctrl,
  340. + struct ssam_event_notifier *n)
  341. +{
  342. + return __ssam_notifier_unregister(ctrl, n, true);
  343. +}
  344. int ssam_controller_event_enable(struct ssam_controller *ctrl,
  345. struct ssam_event_registry reg,
  346. diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h
  347. index 6df7c8d4e50e..c418f7f2732d 100644
  348. --- a/include/linux/surface_aggregator/device.h
  349. +++ b/include/linux/surface_aggregator/device.h
  350. @@ -483,4 +483,70 @@ static inline void ssam_remove_clients(struct device *dev) {}
  351. sdev->uid.instance, ret); \
  352. }
  353. +
  354. +/* -- Helpers for client-device notifiers. ---------------------------------- */
  355. +
  356. +/**
  357. + * ssam_device_notifier_register() - Register an event notifier for the
  358. + * specified client device.
  359. + * @sdev: The device the notifier should be registered on.
  360. + * @n: The event notifier to register.
  361. + *
  362. + * Register an event notifier. Increment the usage counter of the associated
  363. + * SAM event if the notifier is not marked as an observer. If the event is not
  364. + * marked as an observer and is currently not enabled, it will be enabled
  365. + * during this call. If the notifier is marked as an observer, no attempt will
  366. + * be made at enabling any event and no reference count will be modified.
  367. + *
  368. + * Notifiers marked as observers do not need to be associated with one specific
  369. + * event, i.e. as long as no event matching is performed, only the event target
  370. + * category needs to be set.
  371. + *
  372. + * Return: Returns zero on success, %-ENOSPC if there have already been
  373. + * %INT_MAX notifiers for the event ID/type associated with the notifier block
  374. + * registered, %-ENOMEM if the corresponding event entry could not be
  375. + * allocated, %-ENODEV if the device is marked as hot-removed. If this is the
  376. + * first time that a notifier block is registered for the specific associated
  377. + * event, returns the status of the event-enable EC-command.
  378. + */
  379. +static inline int ssam_device_notifier_register(struct ssam_device *sdev,
  380. + struct ssam_event_notifier *n)
  381. +{
  382. + /*
  383. + * Note that this check does not provide any guarantees whatsoever as
  384. + * hot-removal could happen at any point and we can't protect against
  385. + * it. Nevertheless, if we can detect hot-removal, bail early to avoid
  386. + * communication timeouts.
  387. + */
  388. + if (ssam_device_is_hot_removed(sdev))
  389. + return -ENODEV;
  390. +
  391. + return ssam_notifier_register(sdev->ctrl, n);
  392. +}
  393. +
  394. +/**
  395. + * ssam_device_notifier_unregister() - Unregister an event notifier for the
  396. + * specified client device.
  397. + * @sdev: The device the notifier has been registered on.
  398. + * @n: The event notifier to unregister.
  399. + *
  400. + * Unregister an event notifier. Decrement the usage counter of the associated
  401. + * SAM event if the notifier is not marked as an observer. If the usage counter
  402. + * reaches zero, the event will be disabled.
  403. + *
  404. + * In case the device has been marked as hot-removed, the event will not be
  405. + * disabled on the EC, as in those cases any attempt at doing so may time out.
  406. + *
  407. + * Return: Returns zero on success, %-ENOENT if the given notifier block has
  408. + * not been registered on the controller. If the given notifier block was the
  409. + * last one associated with its specific event, returns the status of the
  410. + * event-disable EC-command.
  411. + */
  412. +static inline int ssam_device_notifier_unregister(struct ssam_device *sdev,
  413. + struct ssam_event_notifier *n)
  414. +{
  415. + return __ssam_notifier_unregister(sdev->ctrl, n,
  416. + !ssam_device_is_hot_removed(sdev));
  417. +}
  418. +
  419. #endif /* _LINUX_SURFACE_AGGREGATOR_DEVICE_H */
  420. --
  421. 2.37.2
  422. From 6418fed20ac4e1540a8747b3799f48b69ec86c8c Mon Sep 17 00:00:00 2001
  423. From: Maximilian Luz <luzmaximilian@gmail.com>
  424. Date: Fri, 27 May 2022 04:34:39 +0200
  425. Subject: [PATCH] platform/surface: aggregator_registry: Use client device
  426. wrappers for notifier registration
  427. Use newly introduced client device wrapper functions for notifier
  428. registration and unregistration.
  429. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  430. Link: https://lore.kernel.org/r/20220527023447.2460025-5-luzmaximilian@gmail.com
  431. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  432. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  433. Patchset: surface-sam
  434. ---
  435. drivers/platform/surface/surface_aggregator_registry.c | 6 +++---
  436. 1 file changed, 3 insertions(+), 3 deletions(-)
  437. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  438. index ce2bd88feeaa..9f630e890ff7 100644
  439. --- a/drivers/platform/surface/surface_aggregator_registry.c
  440. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  441. @@ -468,7 +468,7 @@ static int ssam_base_hub_probe(struct ssam_device *sdev)
  442. ssam_device_set_drvdata(sdev, hub);
  443. - status = ssam_notifier_register(sdev->ctrl, &hub->notif);
  444. + status = ssam_device_notifier_register(sdev, &hub->notif);
  445. if (status)
  446. return status;
  447. @@ -480,7 +480,7 @@ static int ssam_base_hub_probe(struct ssam_device *sdev)
  448. return 0;
  449. err:
  450. - ssam_notifier_unregister(sdev->ctrl, &hub->notif);
  451. + ssam_device_notifier_unregister(sdev, &hub->notif);
  452. cancel_delayed_work_sync(&hub->update_work);
  453. ssam_remove_clients(&sdev->dev);
  454. return status;
  455. @@ -492,7 +492,7 @@ static void ssam_base_hub_remove(struct ssam_device *sdev)
  456. sysfs_remove_group(&sdev->dev.kobj, &ssam_base_hub_group);
  457. - ssam_notifier_unregister(sdev->ctrl, &hub->notif);
  458. + ssam_device_notifier_unregister(sdev, &hub->notif);
  459. cancel_delayed_work_sync(&hub->update_work);
  460. ssam_remove_clients(&sdev->dev);
  461. }
  462. --
  463. 2.37.2
  464. From 7c680b78726f4dcfb1d2714d55d68fc6ea4ac0b8 Mon Sep 17 00:00:00 2001
  465. From: Maximilian Luz <luzmaximilian@gmail.com>
  466. Date: Fri, 27 May 2022 04:34:40 +0200
  467. Subject: [PATCH] power/supply: surface_charger: Use client device wrappers for
  468. notifier registration
  469. Use newly introduced client device wrapper functions for notifier
  470. registration and unregistration.
  471. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  472. Acked-by: Sebastian Reichel <sebastian.reichel@collabora.com>
  473. Link: https://lore.kernel.org/r/20220527023447.2460025-6-luzmaximilian@gmail.com
  474. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  475. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  476. Patchset: surface-sam
  477. ---
  478. drivers/power/supply/surface_charger.c | 4 ++--
  479. 1 file changed, 2 insertions(+), 2 deletions(-)
  480. diff --git a/drivers/power/supply/surface_charger.c b/drivers/power/supply/surface_charger.c
  481. index a060c36c7766..59182d55742d 100644
  482. --- a/drivers/power/supply/surface_charger.c
  483. +++ b/drivers/power/supply/surface_charger.c
  484. @@ -216,7 +216,7 @@ static int spwr_ac_register(struct spwr_ac_device *ac)
  485. if (IS_ERR(ac->psy))
  486. return PTR_ERR(ac->psy);
  487. - return ssam_notifier_register(ac->sdev->ctrl, &ac->notif);
  488. + return ssam_device_notifier_register(ac->sdev, &ac->notif);
  489. }
  490. @@ -251,7 +251,7 @@ static void surface_ac_remove(struct ssam_device *sdev)
  491. {
  492. struct spwr_ac_device *ac = ssam_device_get_drvdata(sdev);
  493. - ssam_notifier_unregister(sdev->ctrl, &ac->notif);
  494. + ssam_device_notifier_unregister(sdev, &ac->notif);
  495. }
  496. static const struct spwr_psy_properties spwr_psy_props_adp1 = {
  497. --
  498. 2.37.2
  499. From c4a286e4b15803af7d9b7e893ba3ce86d785ad86 Mon Sep 17 00:00:00 2001
  500. From: Maximilian Luz <luzmaximilian@gmail.com>
  501. Date: Fri, 27 May 2022 04:34:41 +0200
  502. Subject: [PATCH] power/supply: surface_battery: Use client device wrappers for
  503. notifier registration
  504. Use newly introduced client device wrapper functions for notifier
  505. registration and unregistration.
  506. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  507. Acked-by: Sebastian Reichel <sebastian.reichel@collabora.com>
  508. Link: https://lore.kernel.org/r/20220527023447.2460025-7-luzmaximilian@gmail.com
  509. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  510. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  511. Patchset: surface-sam
  512. ---
  513. drivers/power/supply/surface_battery.c | 4 ++--
  514. 1 file changed, 2 insertions(+), 2 deletions(-)
  515. diff --git a/drivers/power/supply/surface_battery.c b/drivers/power/supply/surface_battery.c
  516. index 5ec2e6bb2465..540707882bb0 100644
  517. --- a/drivers/power/supply/surface_battery.c
  518. +++ b/drivers/power/supply/surface_battery.c
  519. @@ -802,7 +802,7 @@ static int spwr_battery_register(struct spwr_battery_device *bat)
  520. if (IS_ERR(bat->psy))
  521. return PTR_ERR(bat->psy);
  522. - return ssam_notifier_register(bat->sdev->ctrl, &bat->notif);
  523. + return ssam_device_notifier_register(bat->sdev, &bat->notif);
  524. }
  525. @@ -837,7 +837,7 @@ static void surface_battery_remove(struct ssam_device *sdev)
  526. {
  527. struct spwr_battery_device *bat = ssam_device_get_drvdata(sdev);
  528. - ssam_notifier_unregister(sdev->ctrl, &bat->notif);
  529. + ssam_device_notifier_unregister(sdev, &bat->notif);
  530. cancel_delayed_work_sync(&bat->update_work);
  531. }
  532. --
  533. 2.37.2
  534. From a76ab65a0845e951c6614ff9ab78ced2488e49b1 Mon Sep 17 00:00:00 2001
  535. From: Maximilian Luz <luzmaximilian@gmail.com>
  536. Date: Fri, 27 May 2022 04:34:42 +0200
  537. Subject: [PATCH] HID: surface-hid: Add support for hot-removal
  538. Add support for hot-removal of SSAM HID client devices.
  539. Once a device has been hot-removed, further communication with it should
  540. be avoided as it may fail and time out. While the device will be removed
  541. as soon as we detect hot-removal, communication may still occur during
  542. teardown, especially when unregistering notifiers.
  543. While hot-removal is a surprise event that can happen at any time, try
  544. to avoid communication as much as possible once it has been detected to
  545. prevent timeouts that can slow down device removal and cause issues,
  546. e.g. when quickly re-attaching the device.
  547. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  548. Link: https://lore.kernel.org/r/20220527023447.2460025-8-luzmaximilian@gmail.com
  549. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  550. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  551. Patchset: surface-sam
  552. ---
  553. drivers/hid/surface-hid/surface_hid_core.c | 38 +++++++++++++++++++++-
  554. 1 file changed, 37 insertions(+), 1 deletion(-)
  555. diff --git a/drivers/hid/surface-hid/surface_hid_core.c b/drivers/hid/surface-hid/surface_hid_core.c
  556. index e46330b2e561..87637f813de2 100644
  557. --- a/drivers/hid/surface-hid/surface_hid_core.c
  558. +++ b/drivers/hid/surface-hid/surface_hid_core.c
  559. @@ -19,12 +19,30 @@
  560. #include "surface_hid_core.h"
  561. +/* -- Utility functions. ---------------------------------------------------- */
  562. +
  563. +static bool surface_hid_is_hot_removed(struct surface_hid_device *shid)
  564. +{
  565. + /*
  566. + * Non-ssam client devices, i.e. platform client devices, cannot be
  567. + * hot-removed.
  568. + */
  569. + if (!is_ssam_device(shid->dev))
  570. + return false;
  571. +
  572. + return ssam_device_is_hot_removed(to_ssam_device(shid->dev));
  573. +}
  574. +
  575. +
  576. /* -- Device descriptor access. --------------------------------------------- */
  577. static int surface_hid_load_hid_descriptor(struct surface_hid_device *shid)
  578. {
  579. int status;
  580. + if (surface_hid_is_hot_removed(shid))
  581. + return -ENODEV;
  582. +
  583. status = shid->ops.get_descriptor(shid, SURFACE_HID_DESC_HID,
  584. (u8 *)&shid->hid_desc, sizeof(shid->hid_desc));
  585. if (status)
  586. @@ -61,6 +79,9 @@ static int surface_hid_load_device_attributes(struct surface_hid_device *shid)
  587. {
  588. int status;
  589. + if (surface_hid_is_hot_removed(shid))
  590. + return -ENODEV;
  591. +
  592. status = shid->ops.get_descriptor(shid, SURFACE_HID_DESC_ATTRS,
  593. (u8 *)&shid->attrs, sizeof(shid->attrs));
  594. if (status)
  595. @@ -88,9 +109,18 @@ static int surface_hid_start(struct hid_device *hid)
  596. static void surface_hid_stop(struct hid_device *hid)
  597. {
  598. struct surface_hid_device *shid = hid->driver_data;
  599. + bool hot_removed;
  600. +
  601. + /*
  602. + * Communication may fail for devices that have been hot-removed. This
  603. + * also includes unregistration of HID events, so we need to check this
  604. + * here. Only if the device has not been marked as hot-removed, we can
  605. + * safely disable events.
  606. + */
  607. + hot_removed = surface_hid_is_hot_removed(shid);
  608. /* Note: This call will log errors for us, so ignore them here. */
  609. - ssam_notifier_unregister(shid->ctrl, &shid->notif);
  610. + __ssam_notifier_unregister(shid->ctrl, &shid->notif, !hot_removed);
  611. }
  612. static int surface_hid_open(struct hid_device *hid)
  613. @@ -109,6 +139,9 @@ static int surface_hid_parse(struct hid_device *hid)
  614. u8 *buf;
  615. int status;
  616. + if (surface_hid_is_hot_removed(shid))
  617. + return -ENODEV;
  618. +
  619. buf = kzalloc(len, GFP_KERNEL);
  620. if (!buf)
  621. return -ENOMEM;
  622. @@ -126,6 +159,9 @@ static int surface_hid_raw_request(struct hid_device *hid, unsigned char reportn
  623. {
  624. struct surface_hid_device *shid = hid->driver_data;
  625. + if (surface_hid_is_hot_removed(shid))
  626. + return -ENODEV;
  627. +
  628. if (rtype == HID_OUTPUT_REPORT && reqtype == HID_REQ_SET_REPORT)
  629. return shid->ops.output_report(shid, reportnum, buf, len);
  630. --
  631. 2.37.2
  632. From 65dd92ca9f5b7871e5c49040c2155d2e341e1039 Mon Sep 17 00:00:00 2001
  633. From: Maximilian Luz <luzmaximilian@gmail.com>
  634. Date: Fri, 27 May 2022 04:34:43 +0200
  635. Subject: [PATCH] platform/surface: aggregator: Add comment for KIP subsystem
  636. category
  637. The KIP subsystem (full name unknown, abbreviation has been obtained
  638. through reverse engineering) handles detachable peripherals such as the
  639. keyboard cover on the Surface Pro X and Surface Pro 8.
  640. It is currently not entirely clear what this subsystem entails, but at
  641. the very least it provides event notifications for when the keyboard
  642. cover on the Surface Pro X and Surface Pro 8 have been detached or
  643. re-attached, as well as the state that the keyboard cover is currently
  644. in (e.g. folded-back, folded laptop-like, closed, etc.).
  645. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  646. Link: https://lore.kernel.org/r/20220527023447.2460025-9-luzmaximilian@gmail.com
  647. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  648. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  649. Patchset: surface-sam
  650. ---
  651. include/linux/surface_aggregator/serial_hub.h | 2 +-
  652. 1 file changed, 1 insertion(+), 1 deletion(-)
  653. diff --git a/include/linux/surface_aggregator/serial_hub.h b/include/linux/surface_aggregator/serial_hub.h
  654. index c3de43edcffa..26b95ec12733 100644
  655. --- a/include/linux/surface_aggregator/serial_hub.h
  656. +++ b/include/linux/surface_aggregator/serial_hub.h
  657. @@ -306,7 +306,7 @@ enum ssam_ssh_tc {
  658. SSAM_SSH_TC_LPC = 0x0b,
  659. SSAM_SSH_TC_TCL = 0x0c,
  660. SSAM_SSH_TC_SFL = 0x0d,
  661. - SSAM_SSH_TC_KIP = 0x0e,
  662. + SSAM_SSH_TC_KIP = 0x0e, /* Manages detachable peripherals (Pro X/8 keyboard cover) */
  663. SSAM_SSH_TC_EXT = 0x0f,
  664. SSAM_SSH_TC_BLD = 0x10,
  665. SSAM_SSH_TC_BAS = 0x11, /* Detachment system (Surface Book 2/3). */
  666. --
  667. 2.37.2
  668. From c46d674b2876bb2ad81c649ac4d6c2fe182cc262 Mon Sep 17 00:00:00 2001
  669. From: Maximilian Luz <luzmaximilian@gmail.com>
  670. Date: Fri, 27 May 2022 04:34:44 +0200
  671. Subject: [PATCH] platform/surface: aggregator_registry: Generify subsystem hub
  672. functionality
  673. The Surface System Aggregator Module (SSAM) has multiple subsystems that
  674. can manage detachable devices. At the moment, we only support the "base"
  675. (BAS/0x11) subsystem, which is used on the Surface Book 3 to manage
  676. devices (including keyboard, touchpad, and secondary battery) connected
  677. to the base of the device.
  678. The Surface Pro 8 has a new type-cover with keyboard and touchpad, which
  679. is managed via the KIP/0x0e subsystem. The general procedure is the
  680. same, but with slightly different events and setup. To make
  681. implementation of the KIP hub easier and prevent duplication, generify
  682. the parts of the base hub that we can use for the KIP hub (or any
  683. potential future subsystem hubs).
  684. This also switches over to use the newly introduced "hot-remove"
  685. functionality, which should prevent communication issues when devices
  686. have been detached.
  687. Lastly, also drop the undocumented and unused sysfs "state" attribute of
  688. the base hub. It has at best been useful for debugging.
  689. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  690. Link: https://lore.kernel.org/r/20220527023447.2460025-10-luzmaximilian@gmail.com
  691. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  692. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  693. Patchset: surface-sam
  694. ---
  695. .../surface/surface_aggregator_registry.c | 269 ++++++++++--------
  696. 1 file changed, 153 insertions(+), 116 deletions(-)
  697. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  698. index 9f630e890ff7..09cbeee2428b 100644
  699. --- a/drivers/platform/surface/surface_aggregator_registry.c
  700. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  701. @@ -308,30 +308,159 @@ static int ssam_hub_register_clients(struct device *parent, struct ssam_controll
  702. }
  703. -/* -- SSAM base-hub driver. ------------------------------------------------- */
  704. +/* -- SSAM generic subsystem hub driver framework. -------------------------- */
  705. -/*
  706. - * Some devices (especially battery) may need a bit of time to be fully usable
  707. - * after being (re-)connected. This delay has been determined via
  708. - * experimentation.
  709. - */
  710. -#define SSAM_BASE_UPDATE_CONNECT_DELAY msecs_to_jiffies(2500)
  711. +enum ssam_hub_state {
  712. + SSAM_HUB_UNINITIALIZED, /* Only set during initialization. */
  713. + SSAM_HUB_CONNECTED,
  714. + SSAM_HUB_DISCONNECTED,
  715. +};
  716. -enum ssam_base_hub_state {
  717. - SSAM_BASE_HUB_UNINITIALIZED,
  718. - SSAM_BASE_HUB_CONNECTED,
  719. - SSAM_BASE_HUB_DISCONNECTED,
  720. +enum ssam_hub_flags {
  721. + SSAM_HUB_HOT_REMOVED,
  722. };
  723. -struct ssam_base_hub {
  724. +struct ssam_hub {
  725. struct ssam_device *sdev;
  726. - enum ssam_base_hub_state state;
  727. + enum ssam_hub_state state;
  728. + unsigned long flags;
  729. +
  730. struct delayed_work update_work;
  731. + unsigned long connect_delay;
  732. struct ssam_event_notifier notif;
  733. +
  734. + int (*get_state)(struct ssam_hub *hub, enum ssam_hub_state *state);
  735. };
  736. +static void ssam_hub_update_workfn(struct work_struct *work)
  737. +{
  738. + struct ssam_hub *hub = container_of(work, struct ssam_hub, update_work.work);
  739. + struct fwnode_handle *node = dev_fwnode(&hub->sdev->dev);
  740. + enum ssam_hub_state state;
  741. + int status = 0;
  742. +
  743. + status = hub->get_state(hub, &state);
  744. + if (status)
  745. + return;
  746. +
  747. + /*
  748. + * There is a small possibility that hub devices were hot-removed and
  749. + * re-added before we were able to remove them here. In that case, both
  750. + * the state returned by get_state() and the state of the hub will
  751. + * equal SSAM_HUB_CONNECTED and we would bail early below, which would
  752. + * leave child devices without proper (re-)initialization and the
  753. + * hot-remove flag set.
  754. + *
  755. + * Therefore, we check whether devices have been hot-removed via an
  756. + * additional flag on the hub and, in this case, override the returned
  757. + * hub state. In case of a missed disconnect (i.e. get_state returned
  758. + * "connected"), we further need to re-schedule this work (with the
  759. + * appropriate delay) as the actual connect work submission might have
  760. + * been merged with this one.
  761. + *
  762. + * This then leads to one of two cases: Either we submit an unnecessary
  763. + * work item (which will get ignored via either the queue or the state
  764. + * checks) or, in the unlikely case that the work is actually required,
  765. + * double the normal connect delay.
  766. + */
  767. + if (test_and_clear_bit(SSAM_HUB_HOT_REMOVED, &hub->flags)) {
  768. + if (state == SSAM_HUB_CONNECTED)
  769. + schedule_delayed_work(&hub->update_work, hub->connect_delay);
  770. +
  771. + state = SSAM_HUB_DISCONNECTED;
  772. + }
  773. +
  774. + if (hub->state == state)
  775. + return;
  776. + hub->state = state;
  777. +
  778. + if (hub->state == SSAM_HUB_CONNECTED)
  779. + status = ssam_hub_register_clients(&hub->sdev->dev, hub->sdev->ctrl, node);
  780. + else
  781. + ssam_remove_clients(&hub->sdev->dev);
  782. +
  783. + if (status)
  784. + dev_err(&hub->sdev->dev, "failed to update hub child devices: %d\n", status);
  785. +}
  786. +
  787. +static int ssam_hub_mark_hot_removed(struct device *dev, void *_data)
  788. +{
  789. + struct ssam_device *sdev = to_ssam_device(dev);
  790. +
  791. + if (is_ssam_device(dev))
  792. + ssam_device_mark_hot_removed(sdev);
  793. +
  794. + return 0;
  795. +}
  796. +
  797. +static void ssam_hub_update(struct ssam_hub *hub, bool connected)
  798. +{
  799. + unsigned long delay;
  800. +
  801. + /* Mark devices as hot-removed before we remove any. */
  802. + if (!connected) {
  803. + set_bit(SSAM_HUB_HOT_REMOVED, &hub->flags);
  804. + device_for_each_child_reverse(&hub->sdev->dev, NULL, ssam_hub_mark_hot_removed);
  805. + }
  806. +
  807. + /*
  808. + * Delay update when the base/keyboard cover is being connected to give
  809. + * devices/EC some time to set up.
  810. + */
  811. + delay = connected ? hub->connect_delay : 0;
  812. +
  813. + schedule_delayed_work(&hub->update_work, delay);
  814. +}
  815. +
  816. +static int __maybe_unused ssam_hub_resume(struct device *dev)
  817. +{
  818. + struct ssam_hub *hub = dev_get_drvdata(dev);
  819. +
  820. + schedule_delayed_work(&hub->update_work, 0);
  821. + return 0;
  822. +}
  823. +static SIMPLE_DEV_PM_OPS(ssam_hub_pm_ops, NULL, ssam_hub_resume);
  824. +
  825. +static int ssam_hub_setup(struct ssam_device *sdev, struct ssam_hub *hub)
  826. +{
  827. + int status;
  828. +
  829. + hub->sdev = sdev;
  830. + hub->state = SSAM_HUB_UNINITIALIZED;
  831. +
  832. + INIT_DELAYED_WORK(&hub->update_work, ssam_hub_update_workfn);
  833. +
  834. + ssam_device_set_drvdata(sdev, hub);
  835. +
  836. + status = ssam_device_notifier_register(sdev, &hub->notif);
  837. + if (status)
  838. + return status;
  839. +
  840. + schedule_delayed_work(&hub->update_work, 0);
  841. + return 0;
  842. +}
  843. +
  844. +static void ssam_hub_remove(struct ssam_device *sdev)
  845. +{
  846. + struct ssam_hub *hub = ssam_device_get_drvdata(sdev);
  847. +
  848. + ssam_device_notifier_unregister(sdev, &hub->notif);
  849. + cancel_delayed_work_sync(&hub->update_work);
  850. + ssam_remove_clients(&sdev->dev);
  851. +}
  852. +
  853. +
  854. +/* -- SSAM base-hub driver. ------------------------------------------------- */
  855. +
  856. +/*
  857. + * Some devices (especially battery) may need a bit of time to be fully usable
  858. + * after being (re-)connected. This delay has been determined via
  859. + * experimentation.
  860. + */
  861. +#define SSAM_BASE_UPDATE_CONNECT_DELAY msecs_to_jiffies(2500)
  862. +
  863. SSAM_DEFINE_SYNC_REQUEST_R(ssam_bas_query_opmode, u8, {
  864. .target_category = SSAM_SSH_TC_BAS,
  865. .target_id = 0x01,
  866. @@ -342,7 +471,7 @@ SSAM_DEFINE_SYNC_REQUEST_R(ssam_bas_query_opmode, u8, {
  867. #define SSAM_BAS_OPMODE_TABLET 0x00
  868. #define SSAM_EVENT_BAS_CID_CONNECTION 0x0c
  869. -static int ssam_base_hub_query_state(struct ssam_base_hub *hub, enum ssam_base_hub_state *state)
  870. +static int ssam_base_hub_query_state(struct ssam_hub *hub, enum ssam_hub_state *state)
  871. {
  872. u8 opmode;
  873. int status;
  874. @@ -354,62 +483,16 @@ static int ssam_base_hub_query_state(struct ssam_base_hub *hub, enum ssam_base_h
  875. }
  876. if (opmode != SSAM_BAS_OPMODE_TABLET)
  877. - *state = SSAM_BASE_HUB_CONNECTED;
  878. + *state = SSAM_HUB_CONNECTED;
  879. else
  880. - *state = SSAM_BASE_HUB_DISCONNECTED;
  881. + *state = SSAM_HUB_DISCONNECTED;
  882. return 0;
  883. }
  884. -static ssize_t ssam_base_hub_state_show(struct device *dev, struct device_attribute *attr,
  885. - char *buf)
  886. -{
  887. - struct ssam_base_hub *hub = dev_get_drvdata(dev);
  888. - bool connected = hub->state == SSAM_BASE_HUB_CONNECTED;
  889. -
  890. - return sysfs_emit(buf, "%d\n", connected);
  891. -}
  892. -
  893. -static struct device_attribute ssam_base_hub_attr_state =
  894. - __ATTR(state, 0444, ssam_base_hub_state_show, NULL);
  895. -
  896. -static struct attribute *ssam_base_hub_attrs[] = {
  897. - &ssam_base_hub_attr_state.attr,
  898. - NULL,
  899. -};
  900. -
  901. -static const struct attribute_group ssam_base_hub_group = {
  902. - .attrs = ssam_base_hub_attrs,
  903. -};
  904. -
  905. -static void ssam_base_hub_update_workfn(struct work_struct *work)
  906. -{
  907. - struct ssam_base_hub *hub = container_of(work, struct ssam_base_hub, update_work.work);
  908. - struct fwnode_handle *node = dev_fwnode(&hub->sdev->dev);
  909. - enum ssam_base_hub_state state;
  910. - int status = 0;
  911. -
  912. - status = ssam_base_hub_query_state(hub, &state);
  913. - if (status)
  914. - return;
  915. -
  916. - if (hub->state == state)
  917. - return;
  918. - hub->state = state;
  919. -
  920. - if (hub->state == SSAM_BASE_HUB_CONNECTED)
  921. - status = ssam_hub_register_clients(&hub->sdev->dev, hub->sdev->ctrl, node);
  922. - else
  923. - ssam_remove_clients(&hub->sdev->dev);
  924. -
  925. - if (status)
  926. - dev_err(&hub->sdev->dev, "failed to update base-hub devices: %d\n", status);
  927. -}
  928. -
  929. static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
  930. {
  931. - struct ssam_base_hub *hub = container_of(nf, struct ssam_base_hub, notif);
  932. - unsigned long delay;
  933. + struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
  934. if (event->command_id != SSAM_EVENT_BAS_CID_CONNECTION)
  935. return 0;
  936. @@ -419,13 +502,7 @@ static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam
  937. return 0;
  938. }
  939. - /*
  940. - * Delay update when the base is being connected to give devices/EC
  941. - * some time to set up.
  942. - */
  943. - delay = event->data[0] ? SSAM_BASE_UPDATE_CONNECT_DELAY : 0;
  944. -
  945. - schedule_delayed_work(&hub->update_work, delay);
  946. + ssam_hub_update(hub, event->data[0]);
  947. /*
  948. * Do not return SSAM_NOTIF_HANDLED: The event should be picked up and
  949. @@ -435,27 +512,14 @@ static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam
  950. return 0;
  951. }
  952. -static int __maybe_unused ssam_base_hub_resume(struct device *dev)
  953. -{
  954. - struct ssam_base_hub *hub = dev_get_drvdata(dev);
  955. -
  956. - schedule_delayed_work(&hub->update_work, 0);
  957. - return 0;
  958. -}
  959. -static SIMPLE_DEV_PM_OPS(ssam_base_hub_pm_ops, NULL, ssam_base_hub_resume);
  960. -
  961. static int ssam_base_hub_probe(struct ssam_device *sdev)
  962. {
  963. - struct ssam_base_hub *hub;
  964. - int status;
  965. + struct ssam_hub *hub;
  966. hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL);
  967. if (!hub)
  968. return -ENOMEM;
  969. - hub->sdev = sdev;
  970. - hub->state = SSAM_BASE_HUB_UNINITIALIZED;
  971. -
  972. hub->notif.base.priority = INT_MAX; /* This notifier should run first. */
  973. hub->notif.base.fn = ssam_base_hub_notif;
  974. hub->notif.event.reg = SSAM_EVENT_REGISTRY_SAM;
  975. @@ -464,37 +528,10 @@ static int ssam_base_hub_probe(struct ssam_device *sdev)
  976. hub->notif.event.mask = SSAM_EVENT_MASK_NONE;
  977. hub->notif.event.flags = SSAM_EVENT_SEQUENCED;
  978. - INIT_DELAYED_WORK(&hub->update_work, ssam_base_hub_update_workfn);
  979. -
  980. - ssam_device_set_drvdata(sdev, hub);
  981. -
  982. - status = ssam_device_notifier_register(sdev, &hub->notif);
  983. - if (status)
  984. - return status;
  985. -
  986. - status = sysfs_create_group(&sdev->dev.kobj, &ssam_base_hub_group);
  987. - if (status)
  988. - goto err;
  989. -
  990. - schedule_delayed_work(&hub->update_work, 0);
  991. - return 0;
  992. + hub->connect_delay = SSAM_BASE_UPDATE_CONNECT_DELAY;
  993. + hub->get_state = ssam_base_hub_query_state;
  994. -err:
  995. - ssam_device_notifier_unregister(sdev, &hub->notif);
  996. - cancel_delayed_work_sync(&hub->update_work);
  997. - ssam_remove_clients(&sdev->dev);
  998. - return status;
  999. -}
  1000. -
  1001. -static void ssam_base_hub_remove(struct ssam_device *sdev)
  1002. -{
  1003. - struct ssam_base_hub *hub = ssam_device_get_drvdata(sdev);
  1004. -
  1005. - sysfs_remove_group(&sdev->dev.kobj, &ssam_base_hub_group);
  1006. -
  1007. - ssam_device_notifier_unregister(sdev, &hub->notif);
  1008. - cancel_delayed_work_sync(&hub->update_work);
  1009. - ssam_remove_clients(&sdev->dev);
  1010. + return ssam_hub_setup(sdev, hub);
  1011. }
  1012. static const struct ssam_device_id ssam_base_hub_match[] = {
  1013. @@ -504,12 +541,12 @@ static const struct ssam_device_id ssam_base_hub_match[] = {
  1014. static struct ssam_device_driver ssam_base_hub_driver = {
  1015. .probe = ssam_base_hub_probe,
  1016. - .remove = ssam_base_hub_remove,
  1017. + .remove = ssam_hub_remove,
  1018. .match_table = ssam_base_hub_match,
  1019. .driver = {
  1020. .name = "surface_aggregator_base_hub",
  1021. .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  1022. - .pm = &ssam_base_hub_pm_ops,
  1023. + .pm = &ssam_hub_pm_ops,
  1024. },
  1025. };
  1026. --
  1027. 2.37.2
  1028. From d293378f454cb71b55886aeec00c58088e529ca7 Mon Sep 17 00:00:00 2001
  1029. From: Maximilian Luz <luzmaximilian@gmail.com>
  1030. Date: Fri, 27 May 2022 04:34:45 +0200
  1031. Subject: [PATCH] platform/surface: aggregator_registry: Change device ID for
  1032. base hub
  1033. Use the target category of the (base) hub as instance id in the
  1034. (virtual) hub device UID. This makes association of the hub with the
  1035. respective subsystem easier.
  1036. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  1037. Link: https://lore.kernel.org/r/20220527023447.2460025-11-luzmaximilian@gmail.com
  1038. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  1039. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  1040. Patchset: surface-sam
  1041. ---
  1042. drivers/platform/surface/surface_aggregator_registry.c | 4 ++--
  1043. 1 file changed, 2 insertions(+), 2 deletions(-)
  1044. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  1045. index 09cbeee2428b..b11ce87c7184 100644
  1046. --- a/drivers/platform/surface/surface_aggregator_registry.c
  1047. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  1048. @@ -43,7 +43,7 @@ static const struct software_node ssam_node_root = {
  1049. /* Base device hub (devices attached to Surface Book 3 base). */
  1050. static const struct software_node ssam_node_hub_base = {
  1051. - .name = "ssam:00:00:02:00:00",
  1052. + .name = "ssam:00:00:02:11:00",
  1053. .parent = &ssam_node_root,
  1054. };
  1055. @@ -535,7 +535,7 @@ static int ssam_base_hub_probe(struct ssam_device *sdev)
  1056. }
  1057. static const struct ssam_device_id ssam_base_hub_match[] = {
  1058. - { SSAM_VDEV(HUB, 0x02, SSAM_ANY_IID, 0x00) },
  1059. + { SSAM_VDEV(HUB, 0x02, SSAM_SSH_TC_BAS, 0x00) },
  1060. { },
  1061. };
  1062. --
  1063. 2.37.2
  1064. From c4bdb8393081ba9121aadc7d6643a42613fbcbd0 Mon Sep 17 00:00:00 2001
  1065. From: Maximilian Luz <luzmaximilian@gmail.com>
  1066. Date: Fri, 27 May 2022 04:34:46 +0200
  1067. Subject: [PATCH] platform/surface: aggregator_registry: Add KIP device hub
  1068. Add a Surface System Aggregator Module (SSAM) client device hub for
  1069. hot-removable devices managed via the KIP subsystem.
  1070. The KIP subsystem (full name unknown, abbreviation has been obtained
  1071. through reverse engineering) is a subsystem that manages hot-removable
  1072. SSAM client devices. Specifically, it manages HID input devices
  1073. contained in the detachable keyboard cover of the Surface Pro 8 and
  1074. Surface Pro X.
  1075. The KIP subsystem handles a single group of devices (e.g. all devices
  1076. contained in the keyboard cover) and cannot handle devices individually.
  1077. Thus we model it as a client device hub, which (hot-)removes all devices
  1078. contained under it once removal of the hub (e.g. keyboard cover) has
  1079. been detected and (re-)adds all devices once the physical hub device has
  1080. been (re-)attached. To do this, use the previously generified SSAM
  1081. subsystem hub framework.
  1082. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  1083. Link: https://lore.kernel.org/r/20220527023447.2460025-12-luzmaximilian@gmail.com
  1084. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  1085. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  1086. Patchset: surface-sam
  1087. ---
  1088. .../surface/surface_aggregator_registry.c | 103 +++++++++++++++++-
  1089. 1 file changed, 101 insertions(+), 2 deletions(-)
  1090. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  1091. index b11ce87c7184..f15cef60630f 100644
  1092. --- a/drivers/platform/surface/surface_aggregator_registry.c
  1093. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  1094. @@ -551,6 +551,93 @@ static struct ssam_device_driver ssam_base_hub_driver = {
  1095. };
  1096. +/* -- SSAM KIP-subsystem hub driver. ---------------------------------------- */
  1097. +
  1098. +/*
  1099. + * Some devices may need a bit of time to be fully usable after being
  1100. + * (re-)connected. This delay has been determined via experimentation.
  1101. + */
  1102. +#define SSAM_KIP_UPDATE_CONNECT_DELAY msecs_to_jiffies(250)
  1103. +
  1104. +#define SSAM_EVENT_KIP_CID_CONNECTION 0x2c
  1105. +
  1106. +SSAM_DEFINE_SYNC_REQUEST_R(__ssam_kip_get_connection_state, u8, {
  1107. + .target_category = SSAM_SSH_TC_KIP,
  1108. + .target_id = 0x01,
  1109. + .command_id = 0x2c,
  1110. + .instance_id = 0x00,
  1111. +});
  1112. +
  1113. +static int ssam_kip_get_connection_state(struct ssam_hub *hub, enum ssam_hub_state *state)
  1114. +{
  1115. + int status;
  1116. + u8 connected;
  1117. +
  1118. + status = ssam_retry(__ssam_kip_get_connection_state, hub->sdev->ctrl, &connected);
  1119. + if (status < 0) {
  1120. + dev_err(&hub->sdev->dev, "failed to query KIP connection state: %d\n", status);
  1121. + return status;
  1122. + }
  1123. +
  1124. + *state = connected ? SSAM_HUB_CONNECTED : SSAM_HUB_DISCONNECTED;
  1125. + return 0;
  1126. +}
  1127. +
  1128. +static u32 ssam_kip_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
  1129. +{
  1130. + struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
  1131. +
  1132. + if (event->command_id != SSAM_EVENT_KIP_CID_CONNECTION)
  1133. + return 0; /* Return "unhandled". */
  1134. +
  1135. + if (event->length < 1) {
  1136. + dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length);
  1137. + return 0;
  1138. + }
  1139. +
  1140. + ssam_hub_update(hub, event->data[0]);
  1141. + return SSAM_NOTIF_HANDLED;
  1142. +}
  1143. +
  1144. +static int ssam_kip_hub_probe(struct ssam_device *sdev)
  1145. +{
  1146. + struct ssam_hub *hub;
  1147. +
  1148. + hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL);
  1149. + if (!hub)
  1150. + return -ENOMEM;
  1151. +
  1152. + hub->notif.base.priority = INT_MAX; /* This notifier should run first. */
  1153. + hub->notif.base.fn = ssam_kip_hub_notif;
  1154. + hub->notif.event.reg = SSAM_EVENT_REGISTRY_SAM;
  1155. + hub->notif.event.id.target_category = SSAM_SSH_TC_KIP,
  1156. + hub->notif.event.id.instance = 0,
  1157. + hub->notif.event.mask = SSAM_EVENT_MASK_TARGET;
  1158. + hub->notif.event.flags = SSAM_EVENT_SEQUENCED;
  1159. +
  1160. + hub->connect_delay = SSAM_KIP_UPDATE_CONNECT_DELAY;
  1161. + hub->get_state = ssam_kip_get_connection_state;
  1162. +
  1163. + return ssam_hub_setup(sdev, hub);
  1164. +}
  1165. +
  1166. +static const struct ssam_device_id ssam_kip_hub_match[] = {
  1167. + { SSAM_VDEV(HUB, 0x01, SSAM_SSH_TC_KIP, 0x00) },
  1168. + { },
  1169. +};
  1170. +
  1171. +static struct ssam_device_driver ssam_kip_hub_driver = {
  1172. + .probe = ssam_kip_hub_probe,
  1173. + .remove = ssam_hub_remove,
  1174. + .match_table = ssam_kip_hub_match,
  1175. + .driver = {
  1176. + .name = "surface_kip_hub",
  1177. + .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  1178. + .pm = &ssam_hub_pm_ops,
  1179. + },
  1180. +};
  1181. +
  1182. +
  1183. /* -- SSAM platform/meta-hub driver. ---------------------------------------- */
  1184. static const struct acpi_device_id ssam_platform_hub_match[] = {
  1185. @@ -673,18 +760,30 @@ static int __init ssam_device_hub_init(void)
  1186. status = platform_driver_register(&ssam_platform_hub_driver);
  1187. if (status)
  1188. - return status;
  1189. + goto err_platform;
  1190. status = ssam_device_driver_register(&ssam_base_hub_driver);
  1191. if (status)
  1192. - platform_driver_unregister(&ssam_platform_hub_driver);
  1193. + goto err_base;
  1194. +
  1195. + status = ssam_device_driver_register(&ssam_kip_hub_driver);
  1196. + if (status)
  1197. + goto err_kip;
  1198. + return 0;
  1199. +
  1200. +err_kip:
  1201. + ssam_device_driver_unregister(&ssam_base_hub_driver);
  1202. +err_base:
  1203. + platform_driver_unregister(&ssam_platform_hub_driver);
  1204. +err_platform:
  1205. return status;
  1206. }
  1207. module_init(ssam_device_hub_init);
  1208. static void __exit ssam_device_hub_exit(void)
  1209. {
  1210. + ssam_device_driver_unregister(&ssam_kip_hub_driver);
  1211. ssam_device_driver_unregister(&ssam_base_hub_driver);
  1212. platform_driver_unregister(&ssam_platform_hub_driver);
  1213. }
  1214. --
  1215. 2.37.2
  1216. From f4c22cd50fb6eba94141a7823be1d4d4db06eb92 Mon Sep 17 00:00:00 2001
  1217. From: Maximilian Luz <luzmaximilian@gmail.com>
  1218. Date: Fri, 27 May 2022 04:34:47 +0200
  1219. Subject: [PATCH] platform/surface: aggregator_registry: Add support for
  1220. keyboard cover on Surface Pro 8
  1221. Add support for the detachable keyboard cover on the Surface Pro 8.
  1222. The keyboard cover on the Surface Pro 8 is, unlike the keyboard covers
  1223. of earlier Surface Pro generations, handled via the Surface System
  1224. Aggregator Module (SSAM). The keyboard and touchpad (as well as other
  1225. HID input devices) of this cover are standard SSAM HID client devices
  1226. (just like keyboard and touchpad on e.g. the Surface Laptop 3 and 4),
  1227. however, some care needs to be taken as they can be physically detached
  1228. (similarly to the Surface Book 3). Specifically, the respective SSAM
  1229. client devices need to be removed when the keyboard cover has been
  1230. detached and (re-)initialized when the keyboard cover has been
  1231. (re-)attached.
  1232. On the Surface Pro 8, detachment of the keyboard cover (and by extension
  1233. its devices) is managed via the KIP subsystem. Therefore, said devices
  1234. need to be registered under the KIP device hub, which in turn will
  1235. remove and re-create/re-initialize those devices as needed.
  1236. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  1237. Link: https://lore.kernel.org/r/20220527023447.2460025-13-luzmaximilian@gmail.com
  1238. Reviewed-by: Hans de Goede <hdegoede@redhat.com>
  1239. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
  1240. Patchset: surface-sam
  1241. ---
  1242. .../surface/surface_aggregator_registry.c | 37 ++++++++++++++++++-
  1243. 1 file changed, 36 insertions(+), 1 deletion(-)
  1244. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  1245. index f15cef60630f..bf3303f1aa71 100644
  1246. --- a/drivers/platform/surface/surface_aggregator_registry.c
  1247. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  1248. @@ -41,6 +41,12 @@ static const struct software_node ssam_node_root = {
  1249. .name = "ssam_platform_hub",
  1250. };
  1251. +/* KIP device hub (connects keyboard cover devices on Surface Pro 8). */
  1252. +static const struct software_node ssam_node_hub_kip = {
  1253. + .name = "ssam:00:00:01:0e:00",
  1254. + .parent = &ssam_node_root,
  1255. +};
  1256. +
  1257. /* Base device hub (devices attached to Surface Book 3 base). */
  1258. static const struct software_node ssam_node_hub_base = {
  1259. .name = "ssam:00:00:02:11:00",
  1260. @@ -155,6 +161,30 @@ static const struct software_node ssam_node_hid_base_iid6 = {
  1261. .parent = &ssam_node_hub_base,
  1262. };
  1263. +/* HID keyboard (KIP hub). */
  1264. +static const struct software_node ssam_node_hid_kip_keyboard = {
  1265. + .name = "ssam:01:15:02:01:00",
  1266. + .parent = &ssam_node_hub_kip,
  1267. +};
  1268. +
  1269. +/* HID pen stash (KIP hub; pen taken / stashed away evens). */
  1270. +static const struct software_node ssam_node_hid_kip_penstash = {
  1271. + .name = "ssam:01:15:02:02:00",
  1272. + .parent = &ssam_node_hub_kip,
  1273. +};
  1274. +
  1275. +/* HID touchpad (KIP hub). */
  1276. +static const struct software_node ssam_node_hid_kip_touchpad = {
  1277. + .name = "ssam:01:15:02:03:00",
  1278. + .parent = &ssam_node_hub_kip,
  1279. +};
  1280. +
  1281. +/* HID device instance 5 (KIP hub, unknown HID device). */
  1282. +static const struct software_node ssam_node_hid_kip_iid5 = {
  1283. + .name = "ssam:01:15:02:05:00",
  1284. + .parent = &ssam_node_hub_kip,
  1285. +};
  1286. +
  1287. /*
  1288. * Devices for 5th- and 6th-generations models:
  1289. * - Surface Book 2,
  1290. @@ -230,10 +260,15 @@ static const struct software_node *ssam_node_group_sp7[] = {
  1291. static const struct software_node *ssam_node_group_sp8[] = {
  1292. &ssam_node_root,
  1293. + &ssam_node_hub_kip,
  1294. &ssam_node_bat_ac,
  1295. &ssam_node_bat_main,
  1296. &ssam_node_tmp_pprof,
  1297. - /* TODO: Add support for keyboard cover. */
  1298. + &ssam_node_hid_kip_keyboard,
  1299. + &ssam_node_hid_kip_penstash,
  1300. + &ssam_node_hid_kip_touchpad,
  1301. + &ssam_node_hid_kip_iid5,
  1302. + /* TODO: Add support for tablet mode switch. */
  1303. NULL,
  1304. };
  1305. --
  1306. 2.37.2
  1307. From 9fbb688836c42161b6389da82442a12ff2346e44 Mon Sep 17 00:00:00 2001
  1308. From: Maximilian Luz <luzmaximilian@gmail.com>
  1309. Date: Tue, 14 Jun 2022 13:17:49 +0200
  1310. Subject: [PATCH] platform/surface: aggregator: Reserve more event- and
  1311. target-categories
  1312. With the introduction of the Surface Laptop Studio, more event- and
  1313. target categories have been added. Therefore, increase the number of
  1314. reserved events and extend the enum of know target categories to
  1315. accommodate this.
  1316. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  1317. Patchset: surface-sam
  1318. ---
  1319. drivers/platform/surface/aggregator/trace.h | 80 +++++++++++--------
  1320. include/linux/surface_aggregator/serial_hub.h | 75 +++++++++--------
  1321. 2 files changed, 85 insertions(+), 70 deletions(-)
  1322. diff --git a/drivers/platform/surface/aggregator/trace.h b/drivers/platform/surface/aggregator/trace.h
  1323. index de64cf169060..cc9e73fbc18e 100644
  1324. --- a/drivers/platform/surface/aggregator/trace.h
  1325. +++ b/drivers/platform/surface/aggregator/trace.h
  1326. @@ -76,7 +76,7 @@ TRACE_DEFINE_ENUM(SSAM_SSH_TC_HID);
  1327. TRACE_DEFINE_ENUM(SSAM_SSH_TC_TCH);
  1328. TRACE_DEFINE_ENUM(SSAM_SSH_TC_BKL);
  1329. TRACE_DEFINE_ENUM(SSAM_SSH_TC_TAM);
  1330. -TRACE_DEFINE_ENUM(SSAM_SSH_TC_ACC);
  1331. +TRACE_DEFINE_ENUM(SSAM_SSH_TC_ACC0);
  1332. TRACE_DEFINE_ENUM(SSAM_SSH_TC_UFI);
  1333. TRACE_DEFINE_ENUM(SSAM_SSH_TC_USC);
  1334. TRACE_DEFINE_ENUM(SSAM_SSH_TC_PEN);
  1335. @@ -85,6 +85,11 @@ TRACE_DEFINE_ENUM(SSAM_SSH_TC_AUD);
  1336. TRACE_DEFINE_ENUM(SSAM_SSH_TC_SMC);
  1337. TRACE_DEFINE_ENUM(SSAM_SSH_TC_KPD);
  1338. TRACE_DEFINE_ENUM(SSAM_SSH_TC_REG);
  1339. +TRACE_DEFINE_ENUM(SSAM_SSH_TC_SPT);
  1340. +TRACE_DEFINE_ENUM(SSAM_SSH_TC_SYS);
  1341. +TRACE_DEFINE_ENUM(SSAM_SSH_TC_ACC1);
  1342. +TRACE_DEFINE_ENUM(SSAM_SSH_TC_SHB);
  1343. +TRACE_DEFINE_ENUM(SSAM_SSH_TC_POS);
  1344. #define SSAM_PTR_UID_LEN 9
  1345. #define SSAM_U8_FIELD_NOT_APPLICABLE ((u16)-1)
  1346. @@ -229,40 +234,45 @@ static inline u32 ssam_trace_get_request_tc(const struct ssh_packet *p)
  1347. #define ssam_show_ssh_tc(rqid) \
  1348. __print_symbolic(rqid, \
  1349. - { SSAM_SSH_TC_NOT_APPLICABLE, "N/A" }, \
  1350. - { SSAM_SSH_TC_SAM, "SAM" }, \
  1351. - { SSAM_SSH_TC_BAT, "BAT" }, \
  1352. - { SSAM_SSH_TC_TMP, "TMP" }, \
  1353. - { SSAM_SSH_TC_PMC, "PMC" }, \
  1354. - { SSAM_SSH_TC_FAN, "FAN" }, \
  1355. - { SSAM_SSH_TC_PoM, "PoM" }, \
  1356. - { SSAM_SSH_TC_DBG, "DBG" }, \
  1357. - { SSAM_SSH_TC_KBD, "KBD" }, \
  1358. - { SSAM_SSH_TC_FWU, "FWU" }, \
  1359. - { SSAM_SSH_TC_UNI, "UNI" }, \
  1360. - { SSAM_SSH_TC_LPC, "LPC" }, \
  1361. - { SSAM_SSH_TC_TCL, "TCL" }, \
  1362. - { SSAM_SSH_TC_SFL, "SFL" }, \
  1363. - { SSAM_SSH_TC_KIP, "KIP" }, \
  1364. - { SSAM_SSH_TC_EXT, "EXT" }, \
  1365. - { SSAM_SSH_TC_BLD, "BLD" }, \
  1366. - { SSAM_SSH_TC_BAS, "BAS" }, \
  1367. - { SSAM_SSH_TC_SEN, "SEN" }, \
  1368. - { SSAM_SSH_TC_SRQ, "SRQ" }, \
  1369. - { SSAM_SSH_TC_MCU, "MCU" }, \
  1370. - { SSAM_SSH_TC_HID, "HID" }, \
  1371. - { SSAM_SSH_TC_TCH, "TCH" }, \
  1372. - { SSAM_SSH_TC_BKL, "BKL" }, \
  1373. - { SSAM_SSH_TC_TAM, "TAM" }, \
  1374. - { SSAM_SSH_TC_ACC, "ACC" }, \
  1375. - { SSAM_SSH_TC_UFI, "UFI" }, \
  1376. - { SSAM_SSH_TC_USC, "USC" }, \
  1377. - { SSAM_SSH_TC_PEN, "PEN" }, \
  1378. - { SSAM_SSH_TC_VID, "VID" }, \
  1379. - { SSAM_SSH_TC_AUD, "AUD" }, \
  1380. - { SSAM_SSH_TC_SMC, "SMC" }, \
  1381. - { SSAM_SSH_TC_KPD, "KPD" }, \
  1382. - { SSAM_SSH_TC_REG, "REG" } \
  1383. + { SSAM_SSH_TC_NOT_APPLICABLE, "N/A" }, \
  1384. + { SSAM_SSH_TC_SAM, "SAM" }, \
  1385. + { SSAM_SSH_TC_BAT, "BAT" }, \
  1386. + { SSAM_SSH_TC_TMP, "TMP" }, \
  1387. + { SSAM_SSH_TC_PMC, "PMC" }, \
  1388. + { SSAM_SSH_TC_FAN, "FAN" }, \
  1389. + { SSAM_SSH_TC_PoM, "PoM" }, \
  1390. + { SSAM_SSH_TC_DBG, "DBG" }, \
  1391. + { SSAM_SSH_TC_KBD, "KBD" }, \
  1392. + { SSAM_SSH_TC_FWU, "FWU" }, \
  1393. + { SSAM_SSH_TC_UNI, "UNI" }, \
  1394. + { SSAM_SSH_TC_LPC, "LPC" }, \
  1395. + { SSAM_SSH_TC_TCL, "TCL" }, \
  1396. + { SSAM_SSH_TC_SFL, "SFL" }, \
  1397. + { SSAM_SSH_TC_KIP, "KIP" }, \
  1398. + { SSAM_SSH_TC_EXT, "EXT" }, \
  1399. + { SSAM_SSH_TC_BLD, "BLD" }, \
  1400. + { SSAM_SSH_TC_BAS, "BAS" }, \
  1401. + { SSAM_SSH_TC_SEN, "SEN" }, \
  1402. + { SSAM_SSH_TC_SRQ, "SRQ" }, \
  1403. + { SSAM_SSH_TC_MCU, "MCU" }, \
  1404. + { SSAM_SSH_TC_HID, "HID" }, \
  1405. + { SSAM_SSH_TC_TCH, "TCH" }, \
  1406. + { SSAM_SSH_TC_BKL, "BKL" }, \
  1407. + { SSAM_SSH_TC_TAM, "TAM" }, \
  1408. + { SSAM_SSH_TC_ACC0, "ACC0" }, \
  1409. + { SSAM_SSH_TC_UFI, "UFI" }, \
  1410. + { SSAM_SSH_TC_USC, "USC" }, \
  1411. + { SSAM_SSH_TC_PEN, "PEN" }, \
  1412. + { SSAM_SSH_TC_VID, "VID" }, \
  1413. + { SSAM_SSH_TC_AUD, "AUD" }, \
  1414. + { SSAM_SSH_TC_SMC, "SMC" }, \
  1415. + { SSAM_SSH_TC_KPD, "KPD" }, \
  1416. + { SSAM_SSH_TC_REG, "REG" }, \
  1417. + { SSAM_SSH_TC_SPT, "SPT" }, \
  1418. + { SSAM_SSH_TC_SYS, "SYS" }, \
  1419. + { SSAM_SSH_TC_ACC1, "ACC1" }, \
  1420. + { SSAM_SSH_TC_SHB, "SMB" }, \
  1421. + { SSAM_SSH_TC_POS, "POS" } \
  1422. )
  1423. DECLARE_EVENT_CLASS(ssam_frame_class,
  1424. diff --git a/include/linux/surface_aggregator/serial_hub.h b/include/linux/surface_aggregator/serial_hub.h
  1425. index 26b95ec12733..45501b6e54e8 100644
  1426. --- a/include/linux/surface_aggregator/serial_hub.h
  1427. +++ b/include/linux/surface_aggregator/serial_hub.h
  1428. @@ -201,7 +201,7 @@ static inline u16 ssh_crc(const u8 *buf, size_t len)
  1429. * exception of zero, which is not an event ID. Thus, this is also the
  1430. * absolute maximum number of event handlers that can be registered.
  1431. */
  1432. -#define SSH_NUM_EVENTS 34
  1433. +#define SSH_NUM_EVENTS 38
  1434. /*
  1435. * SSH_NUM_TARGETS - The number of communication targets used in the protocol.
  1436. @@ -292,40 +292,45 @@ struct ssam_span {
  1437. * Windows driver.
  1438. */
  1439. enum ssam_ssh_tc {
  1440. - /* Category 0x00 is invalid for EC use. */
  1441. - SSAM_SSH_TC_SAM = 0x01, /* Generic system functionality, real-time clock. */
  1442. - SSAM_SSH_TC_BAT = 0x02, /* Battery/power subsystem. */
  1443. - SSAM_SSH_TC_TMP = 0x03, /* Thermal subsystem. */
  1444. - SSAM_SSH_TC_PMC = 0x04,
  1445. - SSAM_SSH_TC_FAN = 0x05,
  1446. - SSAM_SSH_TC_PoM = 0x06,
  1447. - SSAM_SSH_TC_DBG = 0x07,
  1448. - SSAM_SSH_TC_KBD = 0x08, /* Legacy keyboard (Laptop 1/2). */
  1449. - SSAM_SSH_TC_FWU = 0x09,
  1450. - SSAM_SSH_TC_UNI = 0x0a,
  1451. - SSAM_SSH_TC_LPC = 0x0b,
  1452. - SSAM_SSH_TC_TCL = 0x0c,
  1453. - SSAM_SSH_TC_SFL = 0x0d,
  1454. - SSAM_SSH_TC_KIP = 0x0e, /* Manages detachable peripherals (Pro X/8 keyboard cover) */
  1455. - SSAM_SSH_TC_EXT = 0x0f,
  1456. - SSAM_SSH_TC_BLD = 0x10,
  1457. - SSAM_SSH_TC_BAS = 0x11, /* Detachment system (Surface Book 2/3). */
  1458. - SSAM_SSH_TC_SEN = 0x12,
  1459. - SSAM_SSH_TC_SRQ = 0x13,
  1460. - SSAM_SSH_TC_MCU = 0x14,
  1461. - SSAM_SSH_TC_HID = 0x15, /* Generic HID input subsystem. */
  1462. - SSAM_SSH_TC_TCH = 0x16,
  1463. - SSAM_SSH_TC_BKL = 0x17,
  1464. - SSAM_SSH_TC_TAM = 0x18,
  1465. - SSAM_SSH_TC_ACC = 0x19,
  1466. - SSAM_SSH_TC_UFI = 0x1a,
  1467. - SSAM_SSH_TC_USC = 0x1b,
  1468. - SSAM_SSH_TC_PEN = 0x1c,
  1469. - SSAM_SSH_TC_VID = 0x1d,
  1470. - SSAM_SSH_TC_AUD = 0x1e,
  1471. - SSAM_SSH_TC_SMC = 0x1f,
  1472. - SSAM_SSH_TC_KPD = 0x20,
  1473. - SSAM_SSH_TC_REG = 0x21, /* Extended event registry. */
  1474. + /* Category 0x00 is invalid for EC use. */
  1475. + SSAM_SSH_TC_SAM = 0x01, /* Generic system functionality, real-time clock. */
  1476. + SSAM_SSH_TC_BAT = 0x02, /* Battery/power subsystem. */
  1477. + SSAM_SSH_TC_TMP = 0x03, /* Thermal subsystem. */
  1478. + SSAM_SSH_TC_PMC = 0x04,
  1479. + SSAM_SSH_TC_FAN = 0x05,
  1480. + SSAM_SSH_TC_PoM = 0x06,
  1481. + SSAM_SSH_TC_DBG = 0x07,
  1482. + SSAM_SSH_TC_KBD = 0x08, /* Legacy keyboard (Laptop 1/2). */
  1483. + SSAM_SSH_TC_FWU = 0x09,
  1484. + SSAM_SSH_TC_UNI = 0x0a,
  1485. + SSAM_SSH_TC_LPC = 0x0b,
  1486. + SSAM_SSH_TC_TCL = 0x0c,
  1487. + SSAM_SSH_TC_SFL = 0x0d,
  1488. + SSAM_SSH_TC_KIP = 0x0e, /* Manages detachable peripherals (Pro X/8 keyboard cover) */
  1489. + SSAM_SSH_TC_EXT = 0x0f,
  1490. + SSAM_SSH_TC_BLD = 0x10,
  1491. + SSAM_SSH_TC_BAS = 0x11, /* Detachment system (Surface Book 2/3). */
  1492. + SSAM_SSH_TC_SEN = 0x12,
  1493. + SSAM_SSH_TC_SRQ = 0x13,
  1494. + SSAM_SSH_TC_MCU = 0x14,
  1495. + SSAM_SSH_TC_HID = 0x15, /* Generic HID input subsystem. */
  1496. + SSAM_SSH_TC_TCH = 0x16,
  1497. + SSAM_SSH_TC_BKL = 0x17,
  1498. + SSAM_SSH_TC_TAM = 0x18,
  1499. + SSAM_SSH_TC_ACC0 = 0x19,
  1500. + SSAM_SSH_TC_UFI = 0x1a,
  1501. + SSAM_SSH_TC_USC = 0x1b,
  1502. + SSAM_SSH_TC_PEN = 0x1c,
  1503. + SSAM_SSH_TC_VID = 0x1d,
  1504. + SSAM_SSH_TC_AUD = 0x1e,
  1505. + SSAM_SSH_TC_SMC = 0x1f,
  1506. + SSAM_SSH_TC_KPD = 0x20,
  1507. + SSAM_SSH_TC_REG = 0x21, /* Extended event registry. */
  1508. + SSAM_SSH_TC_SPT = 0x22,
  1509. + SSAM_SSH_TC_SYS = 0x23,
  1510. + SSAM_SSH_TC_ACC1 = 0x24,
  1511. + SSAM_SSH_TC_SHB = 0x25,
  1512. + SSAM_SSH_TC_POS = 0x26, /* For obtaining Laptop Studio screen position. */
  1513. };
  1514. --
  1515. 2.37.2
  1516. From f26c891671fde07b2b198bc69d36b2c372a0ac55 Mon Sep 17 00:00:00 2001
  1517. From: Maximilian Luz <luzmaximilian@gmail.com>
  1518. Date: Thu, 16 Jun 2022 01:50:12 +0200
  1519. Subject: [PATCH] platform/surface: aggregator: Add helper macros for requests
  1520. with argument and return value
  1521. Add helper macros for synchronous stack-allocated Surface Aggregator
  1522. request with both argument and return value, similar to the current
  1523. argument-only and return-value-only ones.
  1524. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  1525. Patchset: surface-sam
  1526. ---
  1527. include/linux/surface_aggregator/controller.h | 125 ++++++++++++++++++
  1528. include/linux/surface_aggregator/device.h | 36 +++++
  1529. 2 files changed, 161 insertions(+)
  1530. diff --git a/include/linux/surface_aggregator/controller.h b/include/linux/surface_aggregator/controller.h
  1531. index 50a2b4926c06..d11a1c6e3186 100644
  1532. --- a/include/linux/surface_aggregator/controller.h
  1533. +++ b/include/linux/surface_aggregator/controller.h
  1534. @@ -469,6 +469,67 @@ struct ssam_request_spec_md {
  1535. return 0; \
  1536. }
  1537. +/**
  1538. + * SSAM_DEFINE_SYNC_REQUEST_WR() - Define synchronous SAM request function with
  1539. + * both argument and return value.
  1540. + * @name: Name of the generated function.
  1541. + * @atype: Type of the request's argument.
  1542. + * @rtype: Type of the request's return value.
  1543. + * @spec: Specification (&struct ssam_request_spec) defining the request.
  1544. + *
  1545. + * Defines a function executing the synchronous SAM request specified by @spec,
  1546. + * with the request taking an argument of type @atype and having a return value
  1547. + * of type @rtype. The generated function takes care of setting up the request
  1548. + * and response structs, buffer allocation, as well as execution of the request
  1549. + * itself, returning once the request has been fully completed. The required
  1550. + * transport buffer will be allocated on the stack.
  1551. + *
  1552. + * The generated function is defined as ``static int name(struct
  1553. + * ssam_controller *ctrl, const atype *arg, rtype *ret)``, returning the status
  1554. + * of the request, which is zero on success and negative on failure. The
  1555. + * ``ctrl`` parameter is the controller via which the request is sent. The
  1556. + * request argument is specified via the ``arg`` pointer. The request's return
  1557. + * value is written to the memory pointed to by the ``ret`` parameter.
  1558. + *
  1559. + * Refer to ssam_request_sync_onstack() for more details on the behavior of
  1560. + * the generated function.
  1561. + */
  1562. +#define SSAM_DEFINE_SYNC_REQUEST_WR(name, atype, rtype, spec...) \
  1563. + static int name(struct ssam_controller *ctrl, const atype *arg, rtype *ret) \
  1564. + { \
  1565. + struct ssam_request_spec s = (struct ssam_request_spec)spec; \
  1566. + struct ssam_request rqst; \
  1567. + struct ssam_response rsp; \
  1568. + int status; \
  1569. + \
  1570. + rqst.target_category = s.target_category; \
  1571. + rqst.target_id = s.target_id; \
  1572. + rqst.command_id = s.command_id; \
  1573. + rqst.instance_id = s.instance_id; \
  1574. + rqst.flags = s.flags | SSAM_REQUEST_HAS_RESPONSE; \
  1575. + rqst.length = sizeof(atype); \
  1576. + rqst.payload = (u8 *)arg; \
  1577. + \
  1578. + rsp.capacity = sizeof(rtype); \
  1579. + rsp.length = 0; \
  1580. + rsp.pointer = (u8 *)ret; \
  1581. + \
  1582. + status = ssam_request_sync_onstack(ctrl, &rqst, &rsp, sizeof(atype)); \
  1583. + if (status) \
  1584. + return status; \
  1585. + \
  1586. + if (rsp.length != sizeof(rtype)) { \
  1587. + struct device *dev = ssam_controller_device(ctrl); \
  1588. + dev_err(dev, \
  1589. + "rqst: invalid response length, expected %zu, got %zu (tc: %#04x, cid: %#04x)", \
  1590. + sizeof(rtype), rsp.length, rqst.target_category,\
  1591. + rqst.command_id); \
  1592. + return -EIO; \
  1593. + } \
  1594. + \
  1595. + return 0; \
  1596. + }
  1597. +
  1598. /**
  1599. * SSAM_DEFINE_SYNC_REQUEST_MD_N() - Define synchronous multi-device SAM
  1600. * request function with neither argument nor return value.
  1601. @@ -613,6 +674,70 @@ struct ssam_request_spec_md {
  1602. return 0; \
  1603. }
  1604. +/**
  1605. + * SSAM_DEFINE_SYNC_REQUEST_MD_WR() - Define synchronous multi-device SAM
  1606. + * request function with both argument and return value.
  1607. + * @name: Name of the generated function.
  1608. + * @atype: Type of the request's argument.
  1609. + * @rtype: Type of the request's return value.
  1610. + * @spec: Specification (&struct ssam_request_spec_md) defining the request.
  1611. + *
  1612. + * Defines a function executing the synchronous SAM request specified by @spec,
  1613. + * with the request taking an argument of type @atype and having a return value
  1614. + * of type @rtype. Device specifying parameters are not hard-coded, but instead
  1615. + * must be provided to the function. The generated function takes care of
  1616. + * setting up the request and response structs, buffer allocation, as well as
  1617. + * execution of the request itself, returning once the request has been fully
  1618. + * completed. The required transport buffer will be allocated on the stack.
  1619. + *
  1620. + * The generated function is defined as ``static int name(struct
  1621. + * ssam_controller *ctrl, u8 tid, u8 iid, const atype *arg, rtype *ret)``,
  1622. + * returning the status of the request, which is zero on success and negative
  1623. + * on failure. The ``ctrl`` parameter is the controller via which the request
  1624. + * is sent, ``tid`` the target ID for the request, and ``iid`` the instance ID.
  1625. + * The request argument is specified via the ``arg`` pointer. The request's
  1626. + * return value is written to the memory pointed to by the ``ret`` parameter.
  1627. + *
  1628. + * Refer to ssam_request_sync_onstack() for more details on the behavior of
  1629. + * the generated function.
  1630. + */
  1631. +#define SSAM_DEFINE_SYNC_REQUEST_MD_WR(name, atype, rtype, spec...) \
  1632. + static int name(struct ssam_controller *ctrl, u8 tid, u8 iid, \
  1633. + const atype *arg, rtype *ret) \
  1634. + { \
  1635. + struct ssam_request_spec_md s = (struct ssam_request_spec_md)spec; \
  1636. + struct ssam_request rqst; \
  1637. + struct ssam_response rsp; \
  1638. + int status; \
  1639. + \
  1640. + rqst.target_category = s.target_category; \
  1641. + rqst.target_id = tid; \
  1642. + rqst.command_id = s.command_id; \
  1643. + rqst.instance_id = iid; \
  1644. + rqst.flags = s.flags | SSAM_REQUEST_HAS_RESPONSE; \
  1645. + rqst.length = sizeof(atype); \
  1646. + rqst.payload = (u8 *)arg; \
  1647. + \
  1648. + rsp.capacity = sizeof(rtype); \
  1649. + rsp.length = 0; \
  1650. + rsp.pointer = (u8 *)ret; \
  1651. + \
  1652. + status = ssam_request_sync_onstack(ctrl, &rqst, &rsp, sizeof(atype)); \
  1653. + if (status) \
  1654. + return status; \
  1655. + \
  1656. + if (rsp.length != sizeof(rtype)) { \
  1657. + struct device *dev = ssam_controller_device(ctrl); \
  1658. + dev_err(dev, \
  1659. + "rqst: invalid response length, expected %zu, got %zu (tc: %#04x, cid: %#04x)", \
  1660. + sizeof(rtype), rsp.length, rqst.target_category,\
  1661. + rqst.command_id); \
  1662. + return -EIO; \
  1663. + } \
  1664. + \
  1665. + return 0; \
  1666. + }
  1667. +
  1668. /* -- Event notifier/callbacks. --------------------------------------------- */
  1669. diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h
  1670. index c418f7f2732d..6cf7e80312d5 100644
  1671. --- a/include/linux/surface_aggregator/device.h
  1672. +++ b/include/linux/surface_aggregator/device.h
  1673. @@ -483,6 +483,42 @@ static inline void ssam_remove_clients(struct device *dev) {}
  1674. sdev->uid.instance, ret); \
  1675. }
  1676. +/**
  1677. + * SSAM_DEFINE_SYNC_REQUEST_CL_WR() - Define synchronous client-device SAM
  1678. + * request function with argument and return value.
  1679. + * @name: Name of the generated function.
  1680. + * @atype: Type of the request's argument.
  1681. + * @rtype: Type of the request's return value.
  1682. + * @spec: Specification (&struct ssam_request_spec_md) defining the request.
  1683. + *
  1684. + * Defines a function executing the synchronous SAM request specified by @spec,
  1685. + * with the request taking an argument of type @atype and having a return value
  1686. + * of type @rtype. Device specifying parameters are not hard-coded, but instead
  1687. + * are provided via the client device, specifically its UID, supplied when
  1688. + * calling this function. The generated function takes care of setting up the
  1689. + * request struct, buffer allocation, as well as execution of the request
  1690. + * itself, returning once the request has been fully completed. The required
  1691. + * transport buffer will be allocated on the stack.
  1692. + *
  1693. + * The generated function is defined as ``static int name(struct ssam_device
  1694. + * *sdev, const atype *arg, rtype *ret)``, returning the status of the request,
  1695. + * which is zero on success and negative on failure. The ``sdev`` parameter
  1696. + * specifies both the target device of the request and by association the
  1697. + * controller via which the request is sent. The request's argument is
  1698. + * specified via the ``arg`` pointer. The request's return value is written to
  1699. + * the memory pointed to by the ``ret`` parameter.
  1700. + *
  1701. + * Refer to ssam_request_sync_onstack() for more details on the behavior of
  1702. + * the generated function.
  1703. + */
  1704. +#define SSAM_DEFINE_SYNC_REQUEST_CL_WR(name, atype, rtype, spec...) \
  1705. + SSAM_DEFINE_SYNC_REQUEST_MD_WR(__raw_##name, atype, rtype, spec) \
  1706. + static int name(struct ssam_device *sdev, const atype *arg, rtype *ret) \
  1707. + { \
  1708. + return __raw_##name(sdev->ctrl, sdev->uid.target, \
  1709. + sdev->uid.instance, arg, ret); \
  1710. + }
  1711. +
  1712. /* -- Helpers for client-device notifiers. ---------------------------------- */
  1713. --
  1714. 2.37.2
  1715. From b89f2ac538abd4dd449bd9bd84d86e93b5567b38 Mon Sep 17 00:00:00 2001
  1716. From: Maximilian Luz <luzmaximilian@gmail.com>
  1717. Date: Tue, 8 Jun 2021 03:19:20 +0200
  1718. Subject: [PATCH] platform/surface: Add KIP tablet-mode switch
  1719. Add a driver providing a tablet-mode switch input device for Surface
  1720. models using the KIP subsystem to manage detachable peripherals.
  1721. The Surface Pro 8 has a detachable keyboard cover. Unlike the keyboard
  1722. covers of previous generation Surface Pro models, this cover is fully
  1723. handled by the Surface System Aggregator Module (SSAM). The SSAM KIP
  1724. subsystem (full name unknown, abbreviation found through reverse
  1725. engineering) provides notifications for mode changes of the cover.
  1726. Specifically, it allows us to know when the cover has been folded back,
  1727. detached, or whether it is in laptop mode.
  1728. The driver introduced with this change captures these events and
  1729. translates them to standard SW_TABLET_MODE input events.
  1730. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  1731. Patchset: surface-sam
  1732. ---
  1733. MAINTAINERS | 6 +
  1734. drivers/platform/surface/Kconfig | 23 +
  1735. drivers/platform/surface/Makefile | 1 +
  1736. .../surface/surface_aggregator_tabletsw.c | 535 ++++++++++++++++++
  1737. 4 files changed, 565 insertions(+)
  1738. create mode 100644 drivers/platform/surface/surface_aggregator_tabletsw.c
  1739. diff --git a/MAINTAINERS b/MAINTAINERS
  1740. index c7c7a96b62a8..852231f4e469 100644
  1741. --- a/MAINTAINERS
  1742. +++ b/MAINTAINERS
  1743. @@ -13030,6 +13030,12 @@ F: drivers/scsi/smartpqi/smartpqi*.[ch]
  1744. F: include/linux/cciss*.h
  1745. F: include/uapi/linux/cciss*.h
  1746. +MICROSOFT SURFACE AGGREGATOR TABLET-MODE SWITCH
  1747. +M: Maximilian Luz <luzmaximilian@gmail.com>
  1748. +L: platform-driver-x86@vger.kernel.org
  1749. +S: Maintained
  1750. +F: drivers/platform/surface/surface_aggregator_tablet_switch.c
  1751. +
  1752. MICROSOFT SURFACE BATTERY AND AC DRIVERS
  1753. M: Maximilian Luz <luzmaximilian@gmail.com>
  1754. L: linux-pm@vger.kernel.org
  1755. diff --git a/drivers/platform/surface/Kconfig b/drivers/platform/surface/Kconfig
  1756. index eb79fbed8059..b152e930cc84 100644
  1757. --- a/drivers/platform/surface/Kconfig
  1758. +++ b/drivers/platform/surface/Kconfig
  1759. @@ -99,6 +99,29 @@ config SURFACE_AGGREGATOR_REGISTRY
  1760. the respective client devices. Drivers for these devices still need to
  1761. be selected via the other options.
  1762. +config SURFACE_AGGREGATOR_TABLET_SWITCH
  1763. + tristate "Surface Aggregator Generic Tablet-Mode Switch Driver"
  1764. + depends on SURFACE_AGGREGATOR
  1765. + depends on SURFACE_AGGREGATOR_BUS
  1766. + depends on INPUT
  1767. + help
  1768. + Provides a tablet-mode switch input device on Microsoft Surface models
  1769. + using the KIP subsystem for detachable keyboards (e.g. keyboard covers)
  1770. + or the POS subsystem for device/screen posture changes.
  1771. +
  1772. + The KIP subsystem is used on newer Surface generations to handle
  1773. + detachable input peripherals, specifically the keyboard cover (containing
  1774. + keyboard and touchpad) on the Surface Pro 8 and Surface Pro X. The POS
  1775. + subsystem is used for device posture change notifications on the Surface
  1776. + Laptop Studio. This module provides a driver to let user-space know when
  1777. + the device should be considered in tablet-mode due to the keyboard cover
  1778. + being detached or folded back (essentially signaling when the keyboard is
  1779. + not available for input). It does so by creating a tablet-mode switch
  1780. + input device, sending the standard SW_TABLET_MODE event on mode change.
  1781. +
  1782. + Select M or Y here, if you want to provide tablet-mode switch input
  1783. + events on the Surface Pro 8, Surface Pro X, and Surface Laptop Studio.
  1784. +
  1785. config SURFACE_DTX
  1786. tristate "Surface DTX (Detachment System) Driver"
  1787. depends on SURFACE_AGGREGATOR
  1788. diff --git a/drivers/platform/surface/Makefile b/drivers/platform/surface/Makefile
  1789. index 0fc9cd3e4dd9..18b27898543e 100644
  1790. --- a/drivers/platform/surface/Makefile
  1791. +++ b/drivers/platform/surface/Makefile
  1792. @@ -10,6 +10,7 @@ obj-$(CONFIG_SURFACE_ACPI_NOTIFY) += surface_acpi_notify.o
  1793. obj-$(CONFIG_SURFACE_AGGREGATOR) += aggregator/
  1794. obj-$(CONFIG_SURFACE_AGGREGATOR_CDEV) += surface_aggregator_cdev.o
  1795. obj-$(CONFIG_SURFACE_AGGREGATOR_REGISTRY) += surface_aggregator_registry.o
  1796. +obj-$(CONFIG_SURFACE_AGGREGATOR_TABLET_SWITCH) += surface_aggregator_tabletsw.o
  1797. obj-$(CONFIG_SURFACE_DTX) += surface_dtx.o
  1798. obj-$(CONFIG_SURFACE_GPE) += surface_gpe.o
  1799. obj-$(CONFIG_SURFACE_HOTPLUG) += surface_hotplug.o
  1800. diff --git a/drivers/platform/surface/surface_aggregator_tabletsw.c b/drivers/platform/surface/surface_aggregator_tabletsw.c
  1801. new file mode 100644
  1802. index 000000000000..6f402d2ca894
  1803. --- /dev/null
  1804. +++ b/drivers/platform/surface/surface_aggregator_tabletsw.c
  1805. @@ -0,0 +1,535 @@
  1806. +// SPDX-License-Identifier: GPL-2.0+
  1807. +/*
  1808. + * Surface System Aggregator Module (SSAM) tablet mode switch driver.
  1809. + *
  1810. + * Copyright (C) 2022 Maximilian Luz <luzmaximilian@gmail.com>
  1811. + */
  1812. +
  1813. +#include <asm/unaligned.h>
  1814. +#include <linux/input.h>
  1815. +#include <linux/kernel.h>
  1816. +#include <linux/module.h>
  1817. +#include <linux/types.h>
  1818. +#include <linux/workqueue.h>
  1819. +
  1820. +#include <linux/surface_aggregator/controller.h>
  1821. +#include <linux/surface_aggregator/device.h>
  1822. +
  1823. +
  1824. +/* -- SSAM generic tablet switch driver framework. -------------------------- */
  1825. +
  1826. +struct ssam_tablet_sw;
  1827. +
  1828. +struct ssam_tablet_sw_ops {
  1829. + int (*get_state)(struct ssam_tablet_sw *sw, u32 *state);
  1830. + const char *(*state_name)(struct ssam_tablet_sw *sw, u32 state);
  1831. + bool (*state_is_tablet_mode)(struct ssam_tablet_sw *sw, u32 state);
  1832. +};
  1833. +
  1834. +struct ssam_tablet_sw {
  1835. + struct ssam_device *sdev;
  1836. +
  1837. + u32 state;
  1838. + struct work_struct update_work;
  1839. + struct input_dev *mode_switch;
  1840. +
  1841. + struct ssam_tablet_sw_ops ops;
  1842. + struct ssam_event_notifier notif;
  1843. +};
  1844. +
  1845. +struct ssam_tablet_sw_desc {
  1846. + struct {
  1847. + const char *name;
  1848. + const char *phys;
  1849. + } dev;
  1850. +
  1851. + struct {
  1852. + u32 (*notify)(struct ssam_event_notifier *nf, const struct ssam_event *event);
  1853. + int (*get_state)(struct ssam_tablet_sw *sw, u32 *state);
  1854. + const char *(*state_name)(struct ssam_tablet_sw *sw, u32 state);
  1855. + bool (*state_is_tablet_mode)(struct ssam_tablet_sw *sw, u32 state);
  1856. + } ops;
  1857. +
  1858. + struct {
  1859. + struct ssam_event_registry reg;
  1860. + struct ssam_event_id id;
  1861. + enum ssam_event_mask mask;
  1862. + u8 flags;
  1863. + } event;
  1864. +};
  1865. +
  1866. +static ssize_t state_show(struct device *dev, struct device_attribute *attr, char *buf)
  1867. +{
  1868. + struct ssam_tablet_sw *sw = dev_get_drvdata(dev);
  1869. + const char *state = sw->ops.state_name(sw, sw->state);
  1870. +
  1871. + return sysfs_emit(buf, "%s\n", state);
  1872. +}
  1873. +static DEVICE_ATTR_RO(state);
  1874. +
  1875. +static struct attribute *ssam_tablet_sw_attrs[] = {
  1876. + &dev_attr_state.attr,
  1877. + NULL,
  1878. +};
  1879. +
  1880. +static const struct attribute_group ssam_tablet_sw_group = {
  1881. + .attrs = ssam_tablet_sw_attrs,
  1882. +};
  1883. +
  1884. +static void ssam_tablet_sw_update_workfn(struct work_struct *work)
  1885. +{
  1886. + struct ssam_tablet_sw *sw = container_of(work, struct ssam_tablet_sw, update_work);
  1887. + int tablet, status;
  1888. + u32 state;
  1889. +
  1890. + status = sw->ops.get_state(sw, &state);
  1891. + if (status)
  1892. + return;
  1893. +
  1894. + if (sw->state == state)
  1895. + return;
  1896. + sw->state = state;
  1897. +
  1898. + /* Send SW_TABLET_MODE event. */
  1899. + tablet = sw->ops.state_is_tablet_mode(sw, state);
  1900. + input_report_switch(sw->mode_switch, SW_TABLET_MODE, tablet);
  1901. + input_sync(sw->mode_switch);
  1902. +}
  1903. +
  1904. +static int __maybe_unused ssam_tablet_sw_resume(struct device *dev)
  1905. +{
  1906. + struct ssam_tablet_sw *sw = dev_get_drvdata(dev);
  1907. +
  1908. + schedule_work(&sw->update_work);
  1909. + return 0;
  1910. +}
  1911. +static SIMPLE_DEV_PM_OPS(ssam_tablet_sw_pm_ops, NULL, ssam_tablet_sw_resume);
  1912. +
  1913. +static int ssam_tablet_sw_probe(struct ssam_device *sdev)
  1914. +{
  1915. + const struct ssam_tablet_sw_desc *desc;
  1916. + struct ssam_tablet_sw *sw;
  1917. + int tablet, status;
  1918. +
  1919. + desc = ssam_device_get_match_data(sdev);
  1920. + if (!desc) {
  1921. + WARN(1, "no driver match data specified");
  1922. + return -EINVAL;
  1923. + }
  1924. +
  1925. + sw = devm_kzalloc(&sdev->dev, sizeof(*sw), GFP_KERNEL);
  1926. + if (!sw)
  1927. + return -ENOMEM;
  1928. +
  1929. + sw->sdev = sdev;
  1930. +
  1931. + sw->ops.get_state = desc->ops.get_state;
  1932. + sw->ops.state_name = desc->ops.state_name;
  1933. + sw->ops.state_is_tablet_mode = desc->ops.state_is_tablet_mode;
  1934. +
  1935. + INIT_WORK(&sw->update_work, ssam_tablet_sw_update_workfn);
  1936. +
  1937. + ssam_device_set_drvdata(sdev, sw);
  1938. +
  1939. + /* Get initial state. */
  1940. + status = sw->ops.get_state(sw, &sw->state);
  1941. + if (status)
  1942. + return status;
  1943. +
  1944. + /* Set up tablet mode switch. */
  1945. + sw->mode_switch = devm_input_allocate_device(&sdev->dev);
  1946. + if (!sw->mode_switch)
  1947. + return -ENOMEM;
  1948. +
  1949. + sw->mode_switch->name = desc->dev.name;
  1950. + sw->mode_switch->phys = desc->dev.phys;
  1951. + sw->mode_switch->id.bustype = BUS_HOST;
  1952. + sw->mode_switch->dev.parent = &sdev->dev;
  1953. +
  1954. + tablet = sw->ops.state_is_tablet_mode(sw, sw->state);
  1955. + input_set_capability(sw->mode_switch, EV_SW, SW_TABLET_MODE);
  1956. + input_report_switch(sw->mode_switch, SW_TABLET_MODE, tablet);
  1957. +
  1958. + status = input_register_device(sw->mode_switch);
  1959. + if (status)
  1960. + return status;
  1961. +
  1962. + /* Set up notifier. */
  1963. + sw->notif.base.priority = 0;
  1964. + sw->notif.base.fn = desc->ops.notify;
  1965. + sw->notif.event.reg = desc->event.reg;
  1966. + sw->notif.event.id = desc->event.id;
  1967. + sw->notif.event.mask = desc->event.mask;
  1968. + sw->notif.event.flags = SSAM_EVENT_SEQUENCED;
  1969. +
  1970. + status = ssam_device_notifier_register(sdev, &sw->notif);
  1971. + if (status)
  1972. + return status;
  1973. +
  1974. + status = sysfs_create_group(&sdev->dev.kobj, &ssam_tablet_sw_group);
  1975. + if (status)
  1976. + goto err;
  1977. +
  1978. + /* We might have missed events during setup, so check again. */
  1979. + schedule_work(&sw->update_work);
  1980. + return 0;
  1981. +
  1982. +err:
  1983. + ssam_device_notifier_unregister(sdev, &sw->notif);
  1984. + cancel_work_sync(&sw->update_work);
  1985. + return status;
  1986. +}
  1987. +
  1988. +static void ssam_tablet_sw_remove(struct ssam_device *sdev)
  1989. +{
  1990. + struct ssam_tablet_sw *sw = ssam_device_get_drvdata(sdev);
  1991. +
  1992. + sysfs_remove_group(&sdev->dev.kobj, &ssam_tablet_sw_group);
  1993. +
  1994. + ssam_device_notifier_unregister(sdev, &sw->notif);
  1995. + cancel_work_sync(&sw->update_work);
  1996. +}
  1997. +
  1998. +
  1999. +/* -- SSAM KIP tablet switch implementation. -------------------------------- */
  2000. +
  2001. +#define SSAM_EVENT_KIP_CID_COVER_STATE_CHANGED 0x1d
  2002. +
  2003. +enum ssam_kip_cover_state {
  2004. + SSAM_KIP_COVER_STATE_DISCONNECTED = 0x01,
  2005. + SSAM_KIP_COVER_STATE_CLOSED = 0x02,
  2006. + SSAM_KIP_COVER_STATE_LAPTOP = 0x03,
  2007. + SSAM_KIP_COVER_STATE_FOLDED_CANVAS = 0x04,
  2008. + SSAM_KIP_COVER_STATE_FOLDED_BACK = 0x05,
  2009. +};
  2010. +
  2011. +static const char* ssam_kip_cover_state_name(struct ssam_tablet_sw *sw, u32 state)
  2012. +{
  2013. + switch (state) {
  2014. + case SSAM_KIP_COVER_STATE_DISCONNECTED:
  2015. + return "disconnected";
  2016. +
  2017. + case SSAM_KIP_COVER_STATE_CLOSED:
  2018. + return "closed";
  2019. +
  2020. + case SSAM_KIP_COVER_STATE_LAPTOP:
  2021. + return "laptop";
  2022. +
  2023. + case SSAM_KIP_COVER_STATE_FOLDED_CANVAS:
  2024. + return "folded-canvas";
  2025. +
  2026. + case SSAM_KIP_COVER_STATE_FOLDED_BACK:
  2027. + return "folded-back";
  2028. +
  2029. + default:
  2030. + dev_warn(&sw->sdev->dev, "unknown KIP cover state: %u\n", state);
  2031. + return "<unknown>";
  2032. + }
  2033. +}
  2034. +
  2035. +static bool ssam_kip_cover_state_is_tablet_mode(struct ssam_tablet_sw *sw, u32 state)
  2036. +{
  2037. + switch (state) {
  2038. + case SSAM_KIP_COVER_STATE_DISCONNECTED:
  2039. + case SSAM_KIP_COVER_STATE_FOLDED_CANVAS:
  2040. + case SSAM_KIP_COVER_STATE_FOLDED_BACK:
  2041. + return true;
  2042. +
  2043. + case SSAM_KIP_COVER_STATE_CLOSED:
  2044. + case SSAM_KIP_COVER_STATE_LAPTOP:
  2045. + return false;
  2046. +
  2047. + default:
  2048. + dev_warn(&sw->sdev->dev, "unknown KIP cover state: %d\n", sw->state);
  2049. + return true;
  2050. + }
  2051. +}
  2052. +
  2053. +SSAM_DEFINE_SYNC_REQUEST_R(__ssam_kip_get_cover_state, u8, {
  2054. + .target_category = SSAM_SSH_TC_KIP,
  2055. + .target_id = 0x01,
  2056. + .command_id = 0x1d,
  2057. + .instance_id = 0x00,
  2058. +});
  2059. +
  2060. +static int ssam_kip_get_cover_state(struct ssam_tablet_sw *sw, u32 *state)
  2061. +{
  2062. + int status;
  2063. + u8 raw;
  2064. +
  2065. + status = ssam_retry(__ssam_kip_get_cover_state, sw->sdev->ctrl, &raw);
  2066. + if (status < 0) {
  2067. + dev_err(&sw->sdev->dev, "failed to query KIP lid state: %d\n", status);
  2068. + return status;
  2069. + }
  2070. +
  2071. + *state = raw;
  2072. + return 0;
  2073. +}
  2074. +
  2075. +static u32 ssam_kip_sw_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
  2076. +{
  2077. + struct ssam_tablet_sw *sw = container_of(nf, struct ssam_tablet_sw, notif);
  2078. +
  2079. + if (event->command_id != SSAM_EVENT_KIP_CID_COVER_STATE_CHANGED)
  2080. + return 0; /* Return "unhandled". */
  2081. +
  2082. + if (event->length < 1) {
  2083. + dev_warn(&sw->sdev->dev, "unexpected payload size: %u\n", event->length);
  2084. + }
  2085. +
  2086. + schedule_work(&sw->update_work);
  2087. + return SSAM_NOTIF_HANDLED;
  2088. +}
  2089. +
  2090. +static const struct ssam_tablet_sw_desc ssam_kip_sw_desc = {
  2091. + .dev = {
  2092. + .name = "Microsoft Surface KIP Tablet Mode Switch",
  2093. + .phys = "ssam/01:0e:01:00:01/input0",
  2094. + },
  2095. + .ops = {
  2096. + .notify = ssam_kip_sw_notif,
  2097. + .get_state = ssam_kip_get_cover_state,
  2098. + .state_name = ssam_kip_cover_state_name,
  2099. + .state_is_tablet_mode = ssam_kip_cover_state_is_tablet_mode,
  2100. + },
  2101. + .event = {
  2102. + .reg = SSAM_EVENT_REGISTRY_SAM,
  2103. + .id = {
  2104. + .target_category = SSAM_SSH_TC_KIP,
  2105. + .instance = 0,
  2106. + },
  2107. + .mask = SSAM_EVENT_MASK_TARGET,
  2108. + },
  2109. +};
  2110. +
  2111. +
  2112. +/* -- SSAM POS tablet switch implementation. -------------------------------- */
  2113. +
  2114. +static bool tablet_mode_in_slate_state = true;
  2115. +module_param(tablet_mode_in_slate_state, bool, S_IRUGO);
  2116. +MODULE_PARM_DESC(tablet_mode_in_slate_state, "Enable tablet mode in slate device posture, default is 'true'");
  2117. +
  2118. +#define SSAM_EVENT_POS_CID_POSTURE_CHANGED 0x03
  2119. +#define SSAM_POS_MAX_SOURCES 4
  2120. +
  2121. +enum ssam_pos_state {
  2122. + SSAM_POS_POSTURE_LID_CLOSED = 0x00,
  2123. + SSAM_POS_POSTURE_LAPTOP = 0x01,
  2124. + SSAM_POS_POSTURE_SLATE = 0x02,
  2125. + SSAM_POS_POSTURE_TABLET = 0x03,
  2126. +};
  2127. +
  2128. +struct ssam_sources_list {
  2129. + __le32 count;
  2130. + __le32 id[SSAM_POS_MAX_SOURCES];
  2131. +} __packed;
  2132. +
  2133. +static const char* ssam_pos_state_name(struct ssam_tablet_sw *sw, u32 state)
  2134. +{
  2135. + switch (state) {
  2136. + case SSAM_POS_POSTURE_LID_CLOSED:
  2137. + return "closed";
  2138. +
  2139. + case SSAM_POS_POSTURE_LAPTOP:
  2140. + return "laptop";
  2141. +
  2142. + case SSAM_POS_POSTURE_SLATE:
  2143. + return "slate";
  2144. +
  2145. + case SSAM_POS_POSTURE_TABLET:
  2146. + return "tablet";
  2147. +
  2148. + default:
  2149. + dev_warn(&sw->sdev->dev, "unknown device posture: %u\n", state);
  2150. + return "<unknown>";
  2151. + }
  2152. +}
  2153. +
  2154. +static bool ssam_pos_state_is_tablet_mode(struct ssam_tablet_sw *sw, u32 state)
  2155. +{
  2156. + switch (state) {
  2157. + case SSAM_POS_POSTURE_LAPTOP:
  2158. + case SSAM_POS_POSTURE_LID_CLOSED:
  2159. + return false;
  2160. +
  2161. + case SSAM_POS_POSTURE_SLATE:
  2162. + return tablet_mode_in_slate_state;
  2163. +
  2164. + case SSAM_POS_POSTURE_TABLET:
  2165. + return true;
  2166. +
  2167. + default:
  2168. + dev_warn(&sw->sdev->dev, "unknown device posture: %u\n", state);
  2169. + return true;
  2170. + }
  2171. +}
  2172. +
  2173. +static int ssam_pos_get_sources_list(struct ssam_tablet_sw *sw, struct ssam_sources_list *sources)
  2174. +{
  2175. + struct ssam_request rqst;
  2176. + struct ssam_response rsp;
  2177. + int status;
  2178. +
  2179. + rqst.target_category = SSAM_SSH_TC_POS;
  2180. + rqst.target_id = 0x01;
  2181. + rqst.command_id = 0x01;
  2182. + rqst.instance_id = 0x00;
  2183. + rqst.flags = SSAM_REQUEST_HAS_RESPONSE;
  2184. + rqst.length = 0;
  2185. + rqst.payload = NULL;
  2186. +
  2187. + rsp.capacity = sizeof(*sources);
  2188. + rsp.length = 0;
  2189. + rsp.pointer = (u8 *)sources;
  2190. +
  2191. + status = ssam_retry(ssam_request_sync_onstack, sw->sdev->ctrl, &rqst, &rsp, 0);
  2192. + if (status)
  2193. + return status;
  2194. +
  2195. + /* We need at least the 'sources->count' field. */
  2196. + if (rsp.length < sizeof(__le32)) {
  2197. + dev_err(&sw->sdev->dev, "received source list response is too small\n");
  2198. + return -EPROTO;
  2199. + }
  2200. +
  2201. + /* Make sure 'sources->count' matches with the response length. */
  2202. + if (get_unaligned_le32(&sources->count) * sizeof(__le32) + sizeof(__le32) != rsp.length) {
  2203. + dev_err(&sw->sdev->dev, "mismatch between number of sources and response size\n");
  2204. + return -EPROTO;
  2205. + }
  2206. +
  2207. + return 0;
  2208. +}
  2209. +
  2210. +static int ssam_pos_get_source(struct ssam_tablet_sw *sw, u32 *source_id)
  2211. +{
  2212. + struct ssam_sources_list sources = {};
  2213. + int status;
  2214. +
  2215. + status = ssam_pos_get_sources_list(sw, &sources);
  2216. + if (status)
  2217. + return status;
  2218. +
  2219. + if (sources.count == 0) {
  2220. + dev_err(&sw->sdev->dev, "no posture sources found\n");
  2221. + return -ENODEV;
  2222. + }
  2223. +
  2224. + /*
  2225. + * We currently don't know what to do with more than one posture souce.
  2226. + * At the moment, only one source seems to be used/provided. The
  2227. + * WARN_ON() here should hopefully let us know quickly once there is a
  2228. + * device that provides multiple sources, at which point we can then
  2229. + * try to figure out how to handle them.
  2230. + */
  2231. + WARN_ON(sources.count > 1);
  2232. +
  2233. + *source_id = get_unaligned_le32(&sources.id[0]);
  2234. + return 0;
  2235. +}
  2236. +
  2237. +SSAM_DEFINE_SYNC_REQUEST_WR(__ssam_pos_get_posture_for_source, __le32, __le32, {
  2238. + .target_category = SSAM_SSH_TC_POS,
  2239. + .target_id = 0x01,
  2240. + .command_id = 0x02,
  2241. + .instance_id = 0x00,
  2242. +});
  2243. +
  2244. +static int ssam_pos_get_posture_for_source(struct ssam_tablet_sw *sw, u32 source_id, u32 *posture)
  2245. +{
  2246. + __le32 source_le = cpu_to_le32(source_id);
  2247. + __le32 rspval_le = 0;
  2248. + int status;
  2249. +
  2250. + status = ssam_retry(__ssam_pos_get_posture_for_source, sw->sdev->ctrl,
  2251. + &source_le, &rspval_le);
  2252. + if (status)
  2253. + return status;
  2254. +
  2255. + *posture = le32_to_cpu(rspval_le);
  2256. + return 0;
  2257. +}
  2258. +
  2259. +static int ssam_pos_get_posture(struct ssam_tablet_sw *sw, u32 *state)
  2260. +{
  2261. + u32 source_id;
  2262. + int status;
  2263. +
  2264. + status = ssam_pos_get_source(sw, &source_id);
  2265. + if (status) {
  2266. + dev_err(&sw->sdev->dev, "failed to get posture source ID: %d\n", status);
  2267. + return status;
  2268. + }
  2269. +
  2270. + status = ssam_pos_get_posture_for_source(sw, source_id, state);
  2271. + if (status) {
  2272. + dev_err(&sw->sdev->dev, "failed to get posture value for source %u: %d\n",
  2273. + source_id, status);
  2274. + return status;
  2275. + }
  2276. +
  2277. + return 0;
  2278. +}
  2279. +
  2280. +static u32 ssam_pos_sw_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
  2281. +{
  2282. + struct ssam_tablet_sw *sw = container_of(nf, struct ssam_tablet_sw, notif);
  2283. +
  2284. + if (event->command_id != SSAM_EVENT_POS_CID_POSTURE_CHANGED)
  2285. + return 0; /* Return "unhandled". */
  2286. +
  2287. + if (event->length != sizeof(__le32) * 3) {
  2288. + dev_warn(&sw->sdev->dev, "unexpected payload size: %u\n", event->length);
  2289. + }
  2290. +
  2291. + schedule_work(&sw->update_work);
  2292. + return SSAM_NOTIF_HANDLED;
  2293. +}
  2294. +
  2295. +static const struct ssam_tablet_sw_desc ssam_pos_sw_desc = {
  2296. + .dev = {
  2297. + .name = "Microsoft Surface POS Tablet Mode Switch",
  2298. + .phys = "ssam/01:26:01:00:01/input0",
  2299. + },
  2300. + .ops = {
  2301. + .notify = ssam_pos_sw_notif,
  2302. + .get_state = ssam_pos_get_posture,
  2303. + .state_name = ssam_pos_state_name,
  2304. + .state_is_tablet_mode = ssam_pos_state_is_tablet_mode,
  2305. + },
  2306. + .event = {
  2307. + .reg = SSAM_EVENT_REGISTRY_SAM,
  2308. + .id = {
  2309. + .target_category = SSAM_SSH_TC_POS,
  2310. + .instance = 0,
  2311. + },
  2312. + .mask = SSAM_EVENT_MASK_TARGET,
  2313. + },
  2314. +};
  2315. +
  2316. +
  2317. +/* -- Driver registration. -------------------------------------------------- */
  2318. +
  2319. +static const struct ssam_device_id ssam_tablet_sw_match[] = {
  2320. + { SSAM_SDEV(KIP, 0x01, 0x00, 0x01), (unsigned long)&ssam_kip_sw_desc },
  2321. + { SSAM_SDEV(POS, 0x01, 0x00, 0x01), (unsigned long)&ssam_pos_sw_desc },
  2322. + { },
  2323. +};
  2324. +MODULE_DEVICE_TABLE(ssam, ssam_tablet_sw_match);
  2325. +
  2326. +static struct ssam_device_driver ssam_tablet_sw_driver = {
  2327. + .probe = ssam_tablet_sw_probe,
  2328. + .remove = ssam_tablet_sw_remove,
  2329. + .match_table = ssam_tablet_sw_match,
  2330. + .driver = {
  2331. + .name = "surface_aggregator_tablet_mode_switch",
  2332. + .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  2333. + .pm = &ssam_tablet_sw_pm_ops,
  2334. + },
  2335. +};
  2336. +module_ssam_device_driver(ssam_tablet_sw_driver);
  2337. +
  2338. +MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
  2339. +MODULE_DESCRIPTION("Tablet mode switch driver for Surface devices using the Surface Aggregator Module");
  2340. +MODULE_LICENSE("GPL");
  2341. --
  2342. 2.37.2
  2343. From 14f40e0eba6884c5eb7e71d0852463db08c9d3b1 Mon Sep 17 00:00:00 2001
  2344. From: Maximilian Luz <luzmaximilian@gmail.com>
  2345. Date: Wed, 27 Oct 2021 22:33:03 +0200
  2346. Subject: [PATCH] platform/surface: aggregator_registry: Add support for tablet
  2347. mode switch on Surface Pro 8
  2348. Add a KIP subsystem tablet-mode switch device for the Surface Pro 8.
  2349. The respective driver for this device provides SW_TABLET_MODE input
  2350. events for user-space based on the state of the keyboard cover (e.g.
  2351. detached, folded-back, normal/laptop mode).
  2352. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  2353. Patchset: surface-sam
  2354. ---
  2355. drivers/platform/surface/surface_aggregator_registry.c | 8 +++++++-
  2356. 1 file changed, 7 insertions(+), 1 deletion(-)
  2357. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  2358. index bf3303f1aa71..8f249df673a4 100644
  2359. --- a/drivers/platform/surface/surface_aggregator_registry.c
  2360. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  2361. @@ -77,6 +77,12 @@ static const struct software_node ssam_node_tmp_pprof = {
  2362. .parent = &ssam_node_root,
  2363. };
  2364. +/* Tablet-mode switch via KIP subsystem. */
  2365. +static const struct software_node ssam_node_kip_tablet_switch = {
  2366. + .name = "ssam:01:0e:01:00:01",
  2367. + .parent = &ssam_node_root,
  2368. +};
  2369. +
  2370. /* DTX / detachment-system device (Surface Book 3). */
  2371. static const struct software_node ssam_node_bas_dtx = {
  2372. .name = "ssam:01:11:01:00:00",
  2373. @@ -264,11 +270,11 @@ static const struct software_node *ssam_node_group_sp8[] = {
  2374. &ssam_node_bat_ac,
  2375. &ssam_node_bat_main,
  2376. &ssam_node_tmp_pprof,
  2377. + &ssam_node_kip_tablet_switch,
  2378. &ssam_node_hid_kip_keyboard,
  2379. &ssam_node_hid_kip_penstash,
  2380. &ssam_node_hid_kip_touchpad,
  2381. &ssam_node_hid_kip_iid5,
  2382. - /* TODO: Add support for tablet mode switch. */
  2383. NULL,
  2384. };
  2385. --
  2386. 2.37.2
  2387. From 41c17d879bc5f5d1700673e7cbb8f1bd4862cafc Mon Sep 17 00:00:00 2001
  2388. From: Maximilian Luz <luzmaximilian@gmail.com>
  2389. Date: Thu, 16 Jun 2022 02:30:16 +0200
  2390. Subject: [PATCH] platform/surface: aggregator_registry: Add support for tablet
  2391. mode switch on Surface Laptop Studio
  2392. Add a POS subsystem tablet-mode switch device for the Surface Laptop
  2393. Studio. The respective driver for this device provides SW_TABLET_MODE
  2394. input events for user-space based on the posture of the screen.
  2395. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  2396. Patchset: surface-sam
  2397. ---
  2398. drivers/platform/surface/surface_aggregator_registry.c | 7 +++++++
  2399. 1 file changed, 7 insertions(+)
  2400. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  2401. index 8f249df673a4..f1c5905f1c16 100644
  2402. --- a/drivers/platform/surface/surface_aggregator_registry.c
  2403. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  2404. @@ -191,6 +191,12 @@ static const struct software_node ssam_node_hid_kip_iid5 = {
  2405. .parent = &ssam_node_hub_kip,
  2406. };
  2407. +/* Tablet-mode switch via POS subsystem. */
  2408. +static const struct software_node ssam_node_pos_tablet_switch = {
  2409. + .name = "ssam:01:26:01:00:01",
  2410. + .parent = &ssam_node_root,
  2411. +};
  2412. +
  2413. /*
  2414. * Devices for 5th- and 6th-generations models:
  2415. * - Surface Book 2,
  2416. @@ -237,6 +243,7 @@ static const struct software_node *ssam_node_group_sls[] = {
  2417. &ssam_node_bat_ac,
  2418. &ssam_node_bat_main,
  2419. &ssam_node_tmp_pprof,
  2420. + &ssam_node_pos_tablet_switch,
  2421. &ssam_node_hid_tid1_keyboard,
  2422. &ssam_node_hid_tid1_penstash,
  2423. &ssam_node_hid_tid1_touchpad,
  2424. --
  2425. 2.37.2
  2426. From 7814ea13e040abe5f2e273865e28f6bd6bc51f17 Mon Sep 17 00:00:00 2001
  2427. From: Maximilian Luz <luzmaximilian@gmail.com>
  2428. Date: Sat, 21 May 2022 00:30:46 +0200
  2429. Subject: [PATCH] platform/surface: aggregator: Move device registry helper
  2430. functions to core module
  2431. Move helper functions for client device registration to the core module.
  2432. This simplifies addition of future DT/OF support and also allows us to
  2433. split out the device hub drivers into their own module.
  2434. At the same time, also improve device node validation a bit by not
  2435. silently skipping devices with invalid device UID specifiers.
  2436. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  2437. Patchset: surface-sam
  2438. ---
  2439. drivers/platform/surface/aggregator/bus.c | 176 ++++++++++++++++--
  2440. .../surface/surface_aggregator_registry.c | 75 +-------
  2441. include/linux/surface_aggregator/device.h | 37 ++++
  2442. 3 files changed, 199 insertions(+), 89 deletions(-)
  2443. diff --git a/drivers/platform/surface/aggregator/bus.c b/drivers/platform/surface/aggregator/bus.c
  2444. index abbbb5b08b07..4bba60884bb5 100644
  2445. --- a/drivers/platform/surface/aggregator/bus.c
  2446. +++ b/drivers/platform/surface/aggregator/bus.c
  2447. @@ -6,6 +6,7 @@
  2448. */
  2449. #include <linux/device.h>
  2450. +#include <linux/property.h>
  2451. #include <linux/slab.h>
  2452. #include <linux/surface_aggregator/controller.h>
  2453. @@ -14,6 +15,9 @@
  2454. #include "bus.h"
  2455. #include "controller.h"
  2456. +
  2457. +/* -- Device and bus functions. --------------------------------------------- */
  2458. +
  2459. static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
  2460. char *buf)
  2461. {
  2462. @@ -363,6 +367,162 @@ void ssam_device_driver_unregister(struct ssam_device_driver *sdrv)
  2463. }
  2464. EXPORT_SYMBOL_GPL(ssam_device_driver_unregister);
  2465. +
  2466. +/* -- Bus registration. ----------------------------------------------------- */
  2467. +
  2468. +/**
  2469. + * ssam_bus_register() - Register and set-up the SSAM client device bus.
  2470. + */
  2471. +int ssam_bus_register(void)
  2472. +{
  2473. + return bus_register(&ssam_bus_type);
  2474. +}
  2475. +
  2476. +/**
  2477. + * ssam_bus_unregister() - Unregister the SSAM client device bus.
  2478. + */
  2479. +void ssam_bus_unregister(void)
  2480. +{
  2481. + return bus_unregister(&ssam_bus_type);
  2482. +}
  2483. +
  2484. +
  2485. +/* -- Helpers for controller and hub devices. ------------------------------- */
  2486. +
  2487. +static int ssam_device_uid_from_string(const char *str, struct ssam_device_uid *uid)
  2488. +{
  2489. + u8 d, tc, tid, iid, fn;
  2490. + int n;
  2491. +
  2492. + n = sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx", &d, &tc, &tid, &iid, &fn);
  2493. + if (n != 5)
  2494. + return -EINVAL;
  2495. +
  2496. + uid->domain = d;
  2497. + uid->category = tc;
  2498. + uid->target = tid;
  2499. + uid->instance = iid;
  2500. + uid->function = fn;
  2501. +
  2502. + return 0;
  2503. +}
  2504. +
  2505. +static int ssam_get_uid_for_node(struct fwnode_handle *node, struct ssam_device_uid *uid)
  2506. +{
  2507. + const char* str = fwnode_get_name(node);
  2508. +
  2509. + /*
  2510. + * To simplify definitions of firmware nodes, we set the device name
  2511. + * based on the UID of the device, prefixed with "ssam:".
  2512. + */
  2513. + if (strncmp(str, "ssam:", strlen("ssam:")) != 0)
  2514. + return -ENODEV;
  2515. +
  2516. + str += strlen("ssam:");
  2517. + return ssam_device_uid_from_string(str, uid);
  2518. +}
  2519. +
  2520. +static int ssam_add_client_device(struct device *parent, struct ssam_controller *ctrl,
  2521. + struct fwnode_handle *node)
  2522. +{
  2523. + struct ssam_device_uid uid;
  2524. + struct ssam_device *sdev;
  2525. + int status;
  2526. +
  2527. + status = ssam_get_uid_for_node(node, &uid);
  2528. + if (status)
  2529. + return status;
  2530. +
  2531. + sdev = ssam_device_alloc(ctrl, uid);
  2532. + if (!sdev)
  2533. + return -ENOMEM;
  2534. +
  2535. + sdev->dev.parent = parent;
  2536. + sdev->dev.fwnode = node;
  2537. +
  2538. + status = ssam_device_add(sdev);
  2539. + if (status)
  2540. + ssam_device_put(sdev);
  2541. +
  2542. + return status;
  2543. +}
  2544. +
  2545. +/**
  2546. + * __ssam_register_clients() - Register client devices defined under the
  2547. + * given firmware node as children of the given device.
  2548. + * @parent: The parent device under which clients should be registered.
  2549. + * @ctrl: The controller with which client should be registered.
  2550. + * @node: The firmware node holding definitions of the devices to be added.
  2551. + *
  2552. + * Register all clients that have been defined as children of the given root
  2553. + * firmware node as children of the given parent device. The respective child
  2554. + * firmware nodes will be associated with the correspondingly created child
  2555. + * devices.
  2556. + *
  2557. + * The given controller will be used to instantiate the new devices. See
  2558. + * ssam_device_add() for details.
  2559. + *
  2560. + * Note that, generally, the use of either ssam_device_register_clients() or
  2561. + * ssam_register_clients() should be preferred as they directly use the
  2562. + * firmware node and/or controller associated with the given device. This
  2563. + * function is only intended for use when different device specifications (e.g.
  2564. + * ACPI and firmware nodes) need to be combined (as is done in the platform hub
  2565. + * of the device registry).
  2566. + *
  2567. + * Return: Returns zero on success, nonzero on failure.
  2568. + */
  2569. +int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl,
  2570. + struct fwnode_handle *node)
  2571. +{
  2572. + struct fwnode_handle *child;
  2573. + int status;
  2574. +
  2575. + fwnode_for_each_child_node(node, child) {
  2576. + /*
  2577. + * Try to add the device specified in the firmware node. If
  2578. + * this fails with -ENODEV, the node does not specify any SSAM
  2579. + * device, so ignore it and continue with the next one.
  2580. + */
  2581. + status = ssam_add_client_device(parent, ctrl, child);
  2582. + if (status && status != -ENODEV)
  2583. + goto err;
  2584. + }
  2585. +
  2586. + return 0;
  2587. +err:
  2588. + ssam_remove_clients(parent);
  2589. + return status;
  2590. +}
  2591. +EXPORT_SYMBOL_GPL(__ssam_register_clients);
  2592. +
  2593. +/**
  2594. + * ssam_register_clients() - Register all client devices defined under the
  2595. + * given parent device.
  2596. + * @dev: The parent device under which clients should be registered.
  2597. + * @ctrl: The controller with which client should be registered.
  2598. + *
  2599. + * Register all clients that have via firmware nodes been defined as children
  2600. + * of the given (parent) device. The respective child firmware nodes will be
  2601. + * associated with the correspondingly created child devices.
  2602. + *
  2603. + * The given controller will be used to instantiate the new devices. See
  2604. + * ssam_device_add() for details.
  2605. + *
  2606. + * Return: Returns zero on success, nonzero on failure.
  2607. + */
  2608. +int ssam_register_clients(struct device *dev, struct ssam_controller *ctrl)
  2609. +{
  2610. + struct fwnode_handle *node;
  2611. + int status;
  2612. +
  2613. + node = fwnode_handle_get(dev_fwnode(dev));
  2614. + status = __ssam_register_clients(dev, ctrl, node);
  2615. + fwnode_handle_put(node);
  2616. +
  2617. + return status;
  2618. +}
  2619. +EXPORT_SYMBOL_GPL(ssam_register_clients);
  2620. +
  2621. static int ssam_remove_device(struct device *dev, void *_data)
  2622. {
  2623. struct ssam_device *sdev = to_ssam_device(dev);
  2624. @@ -387,19 +547,3 @@ void ssam_remove_clients(struct device *dev)
  2625. device_for_each_child_reverse(dev, NULL, ssam_remove_device);
  2626. }
  2627. EXPORT_SYMBOL_GPL(ssam_remove_clients);
  2628. -
  2629. -/**
  2630. - * ssam_bus_register() - Register and set-up the SSAM client device bus.
  2631. - */
  2632. -int ssam_bus_register(void)
  2633. -{
  2634. - return bus_register(&ssam_bus_type);
  2635. -}
  2636. -
  2637. -/**
  2638. - * ssam_bus_unregister() - Unregister the SSAM client device bus.
  2639. - */
  2640. -void ssam_bus_unregister(void)
  2641. -{
  2642. - return bus_unregister(&ssam_bus_type);
  2643. -}
  2644. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  2645. index f1c5905f1c16..c680792a037e 100644
  2646. --- a/drivers/platform/surface/surface_aggregator_registry.c
  2647. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  2648. @@ -286,76 +286,6 @@ static const struct software_node *ssam_node_group_sp8[] = {
  2649. };
  2650. -/* -- Device registry helper functions. ------------------------------------- */
  2651. -
  2652. -static int ssam_uid_from_string(const char *str, struct ssam_device_uid *uid)
  2653. -{
  2654. - u8 d, tc, tid, iid, fn;
  2655. - int n;
  2656. -
  2657. - n = sscanf(str, "ssam:%hhx:%hhx:%hhx:%hhx:%hhx", &d, &tc, &tid, &iid, &fn);
  2658. - if (n != 5)
  2659. - return -EINVAL;
  2660. -
  2661. - uid->domain = d;
  2662. - uid->category = tc;
  2663. - uid->target = tid;
  2664. - uid->instance = iid;
  2665. - uid->function = fn;
  2666. -
  2667. - return 0;
  2668. -}
  2669. -
  2670. -static int ssam_hub_add_device(struct device *parent, struct ssam_controller *ctrl,
  2671. - struct fwnode_handle *node)
  2672. -{
  2673. - struct ssam_device_uid uid;
  2674. - struct ssam_device *sdev;
  2675. - int status;
  2676. -
  2677. - status = ssam_uid_from_string(fwnode_get_name(node), &uid);
  2678. - if (status)
  2679. - return status;
  2680. -
  2681. - sdev = ssam_device_alloc(ctrl, uid);
  2682. - if (!sdev)
  2683. - return -ENOMEM;
  2684. -
  2685. - sdev->dev.parent = parent;
  2686. - sdev->dev.fwnode = node;
  2687. -
  2688. - status = ssam_device_add(sdev);
  2689. - if (status)
  2690. - ssam_device_put(sdev);
  2691. -
  2692. - return status;
  2693. -}
  2694. -
  2695. -static int ssam_hub_register_clients(struct device *parent, struct ssam_controller *ctrl,
  2696. - struct fwnode_handle *node)
  2697. -{
  2698. - struct fwnode_handle *child;
  2699. - int status;
  2700. -
  2701. - fwnode_for_each_child_node(node, child) {
  2702. - /*
  2703. - * Try to add the device specified in the firmware node. If
  2704. - * this fails with -EINVAL, the node does not specify any SSAM
  2705. - * device, so ignore it and continue with the next one.
  2706. - */
  2707. -
  2708. - status = ssam_hub_add_device(parent, ctrl, child);
  2709. - if (status && status != -EINVAL)
  2710. - goto err;
  2711. - }
  2712. -
  2713. - return 0;
  2714. -err:
  2715. - ssam_remove_clients(parent);
  2716. - return status;
  2717. -}
  2718. -
  2719. -
  2720. /* -- SSAM generic subsystem hub driver framework. -------------------------- */
  2721. enum ssam_hub_state {
  2722. @@ -385,7 +315,6 @@ struct ssam_hub {
  2723. static void ssam_hub_update_workfn(struct work_struct *work)
  2724. {
  2725. struct ssam_hub *hub = container_of(work, struct ssam_hub, update_work.work);
  2726. - struct fwnode_handle *node = dev_fwnode(&hub->sdev->dev);
  2727. enum ssam_hub_state state;
  2728. int status = 0;
  2729. @@ -425,7 +354,7 @@ static void ssam_hub_update_workfn(struct work_struct *work)
  2730. hub->state = state;
  2731. if (hub->state == SSAM_HUB_CONNECTED)
  2732. - status = ssam_hub_register_clients(&hub->sdev->dev, hub->sdev->ctrl, node);
  2733. + status = ssam_device_register_clients(hub->sdev);
  2734. else
  2735. ssam_remove_clients(&hub->sdev->dev);
  2736. @@ -769,7 +698,7 @@ static int ssam_platform_hub_probe(struct platform_device *pdev)
  2737. set_secondary_fwnode(&pdev->dev, root);
  2738. - status = ssam_hub_register_clients(&pdev->dev, ctrl, root);
  2739. + status = __ssam_register_clients(&pdev->dev, ctrl, root);
  2740. if (status) {
  2741. set_secondary_fwnode(&pdev->dev, NULL);
  2742. software_node_unregister_node_group(nodes);
  2743. diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h
  2744. index 6cf7e80312d5..6e75fb605479 100644
  2745. --- a/include/linux/surface_aggregator/device.h
  2746. +++ b/include/linux/surface_aggregator/device.h
  2747. @@ -375,11 +375,48 @@ void ssam_device_driver_unregister(struct ssam_device_driver *d);
  2748. /* -- Helpers for controller and hub devices. ------------------------------- */
  2749. #ifdef CONFIG_SURFACE_AGGREGATOR_BUS
  2750. +
  2751. +int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl,
  2752. + struct fwnode_handle *node);
  2753. +int ssam_register_clients(struct device *dev, struct ssam_controller *ctrl);
  2754. void ssam_remove_clients(struct device *dev);
  2755. +
  2756. #else /* CONFIG_SURFACE_AGGREGATOR_BUS */
  2757. +
  2758. +static inline int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl,
  2759. + struct fwnode_handle *node)
  2760. +{
  2761. + return 0;
  2762. +}
  2763. +
  2764. +static inline int ssam_register_clients(struct device *dev, struct ssam_controller *ctrl)
  2765. +{
  2766. + return 0;
  2767. +}
  2768. +
  2769. static inline void ssam_remove_clients(struct device *dev) {}
  2770. +
  2771. #endif /* CONFIG_SURFACE_AGGREGATOR_BUS */
  2772. +/**
  2773. + * ssam_device_register_clients() - Register all client devices defined under
  2774. + * the given SSAM parent device.
  2775. + * @sdev: The parent device under which clients should be registered.
  2776. + *
  2777. + * Register all clients that have via firmware nodes been defined as children
  2778. + * of the given (parent) device. The respective child firmware nodes will be
  2779. + * associated with the correspondingly created child devices.
  2780. + *
  2781. + * The controller used by the parent device will be used to instantiate the new
  2782. + * devices. See ssam_device_add() for details.
  2783. + *
  2784. + * Return: Returns zero on success, nonzero on failure.
  2785. + */
  2786. +static inline int ssam_device_register_clients(struct ssam_device *sdev)
  2787. +{
  2788. + return ssam_register_clients(&sdev->dev, sdev->ctrl);
  2789. +}
  2790. +
  2791. /* -- Helpers for client-device requests. ----------------------------------- */
  2792. --
  2793. 2.37.2
  2794. From 446587a52772adcbdf620ec48d04414f062af173 Mon Sep 17 00:00:00 2001
  2795. From: Maximilian Luz <luzmaximilian@gmail.com>
  2796. Date: Sat, 21 May 2022 00:39:56 +0200
  2797. Subject: [PATCH] platform/surface: aggregator: Move subsystem hub drivers to
  2798. their own module
  2799. Split out subsystem device hub drivers into their own module. This
  2800. allows us to load the hub drivers separately from the registry, which
  2801. will help future DT/OF support.
  2802. While doing so, also remove a small bit of code duplication.
  2803. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  2804. Patchset: surface-sam
  2805. ---
  2806. MAINTAINERS | 6 +
  2807. drivers/platform/surface/Kconfig | 35 +-
  2808. drivers/platform/surface/Makefile | 1 +
  2809. .../platform/surface/surface_aggregator_hub.c | 371 ++++++++++++++++++
  2810. .../surface/surface_aggregator_registry.c | 371 +-----------------
  2811. 5 files changed, 410 insertions(+), 374 deletions(-)
  2812. create mode 100644 drivers/platform/surface/surface_aggregator_hub.c
  2813. diff --git a/MAINTAINERS b/MAINTAINERS
  2814. index 852231f4e469..f96b3dba903a 100644
  2815. --- a/MAINTAINERS
  2816. +++ b/MAINTAINERS
  2817. @@ -13107,6 +13107,12 @@ F: include/linux/surface_acpi_notify.h
  2818. F: include/linux/surface_aggregator/
  2819. F: include/uapi/linux/surface_aggregator/
  2820. +MICROSOFT SURFACE SYSTEM AGGREGATOR HUB DRIVER
  2821. +M: Maximilian Luz <luzmaximilian@gmail.com>
  2822. +L: platform-driver-x86@vger.kernel.org
  2823. +S: Maintained
  2824. +F: drivers/platform/surface/surface_aggregator_hub.c
  2825. +
  2826. MICROTEK X6 SCANNER
  2827. M: Oliver Neukum <oliver@neukum.org>
  2828. S: Maintained
  2829. diff --git a/drivers/platform/surface/Kconfig b/drivers/platform/surface/Kconfig
  2830. index b152e930cc84..b629e82af97c 100644
  2831. --- a/drivers/platform/surface/Kconfig
  2832. +++ b/drivers/platform/surface/Kconfig
  2833. @@ -72,18 +72,45 @@ config SURFACE_AGGREGATOR_CDEV
  2834. The provided interface is intended for debugging and development only,
  2835. and should not be used otherwise.
  2836. +config SURFACE_AGGREGATOR_HUB
  2837. + tristate "Surface System Aggregator Module Subsystem Device Hubs"
  2838. + depends on SURFACE_AGGREGATOR
  2839. + depends on SURFACE_AGGREGATOR_BUS
  2840. + help
  2841. + Device-hub drivers for Surface System Aggregator Module (SSAM) subsystem
  2842. + devices.
  2843. +
  2844. + Provides subsystem hub drivers which manage client devices on various
  2845. + SSAM subsystems. In some subsystems, notably the BAS subsystem managing
  2846. + devices contained in the base of the Surface Book 3 and the KIP subsystem
  2847. + managing type-cover devices in the Surface Pro 8 and Surface Pro X,
  2848. + devices can be (hot-)removed. Hub devices and drivers are required to
  2849. + manage these subdevices.
  2850. +
  2851. + Devices managed via these hubs are:
  2852. + - Battery/AC devices (Surface Book 3).
  2853. + - HID input devices (7th-generation and later models with detachable
  2854. + input devices).
  2855. +
  2856. + Select M (recommended) or Y here if you want support for the above
  2857. + mentioned devices on the corresponding Surface models. Without this
  2858. + module, the respective devices mentioned above will not be instantiated
  2859. + and thus any functionality provided by them will be missing, even when
  2860. + drivers for these devices are present. This module only provides the
  2861. + respective subsystem hubs. Both drivers and device specification (e.g.
  2862. + via the Surface Aggregator Registry) for these devices still need to be
  2863. + selected via other options.
  2864. +
  2865. config SURFACE_AGGREGATOR_REGISTRY
  2866. tristate "Surface System Aggregator Module Device Registry"
  2867. depends on SURFACE_AGGREGATOR
  2868. depends on SURFACE_AGGREGATOR_BUS
  2869. help
  2870. - Device-registry and device-hubs for Surface System Aggregator Module
  2871. - (SSAM) devices.
  2872. + Device-registry for Surface System Aggregator Module (SSAM) devices.
  2873. Provides a module and driver which act as a device-registry for SSAM
  2874. client devices that cannot be detected automatically, e.g. via ACPI.
  2875. - Such devices are instead provided via this registry and attached via
  2876. - device hubs, also provided in this module.
  2877. + Such devices are instead provided and managed via this registry.
  2878. Devices provided via this registry are:
  2879. - Platform profile (performance-/cooling-mode) device (5th- and later
  2880. diff --git a/drivers/platform/surface/Makefile b/drivers/platform/surface/Makefile
  2881. index 18b27898543e..53344330939b 100644
  2882. --- a/drivers/platform/surface/Makefile
  2883. +++ b/drivers/platform/surface/Makefile
  2884. @@ -9,6 +9,7 @@ obj-$(CONFIG_SURFACE_3_POWER_OPREGION) += surface3_power.o
  2885. obj-$(CONFIG_SURFACE_ACPI_NOTIFY) += surface_acpi_notify.o
  2886. obj-$(CONFIG_SURFACE_AGGREGATOR) += aggregator/
  2887. obj-$(CONFIG_SURFACE_AGGREGATOR_CDEV) += surface_aggregator_cdev.o
  2888. +obj-$(CONFIG_SURFACE_AGGREGATOR_HUB) += surface_aggregator_hub.o
  2889. obj-$(CONFIG_SURFACE_AGGREGATOR_REGISTRY) += surface_aggregator_registry.o
  2890. obj-$(CONFIG_SURFACE_AGGREGATOR_TABLET_SWITCH) += surface_aggregator_tabletsw.o
  2891. obj-$(CONFIG_SURFACE_DTX) += surface_dtx.o
  2892. diff --git a/drivers/platform/surface/surface_aggregator_hub.c b/drivers/platform/surface/surface_aggregator_hub.c
  2893. new file mode 100644
  2894. index 000000000000..43061514be38
  2895. --- /dev/null
  2896. +++ b/drivers/platform/surface/surface_aggregator_hub.c
  2897. @@ -0,0 +1,371 @@
  2898. +// SPDX-License-Identifier: GPL-2.0+
  2899. +/*
  2900. + * Driver for Surface System Aggregator Module (SSAM) subsystem device hubs.
  2901. + *
  2902. + * Provides a driver for SSAM subsystems device hubs. This driver performs
  2903. + * instantiation of the devices managed by said hubs and takes care of
  2904. + * (hot-)removal.
  2905. + *
  2906. + * Copyright (C) 2020-2022 Maximilian Luz <luzmaximilian@gmail.com>
  2907. + */
  2908. +
  2909. +#include <linux/kernel.h>
  2910. +#include <linux/limits.h>
  2911. +#include <linux/module.h>
  2912. +#include <linux/types.h>
  2913. +#include <linux/workqueue.h>
  2914. +
  2915. +#include <linux/surface_aggregator/device.h>
  2916. +
  2917. +
  2918. +/* -- SSAM generic subsystem hub driver framework. -------------------------- */
  2919. +
  2920. +enum ssam_hub_state {
  2921. + SSAM_HUB_UNINITIALIZED, /* Only set during initialization. */
  2922. + SSAM_HUB_CONNECTED,
  2923. + SSAM_HUB_DISCONNECTED,
  2924. +};
  2925. +
  2926. +enum ssam_hub_flags {
  2927. + SSAM_HUB_HOT_REMOVED,
  2928. +};
  2929. +
  2930. +struct ssam_hub;
  2931. +
  2932. +struct ssam_hub_ops {
  2933. + int (*get_state)(struct ssam_hub *hub, enum ssam_hub_state *state);
  2934. +};
  2935. +
  2936. +struct ssam_hub {
  2937. + struct ssam_device *sdev;
  2938. +
  2939. + enum ssam_hub_state state;
  2940. + unsigned long flags;
  2941. +
  2942. + struct delayed_work update_work;
  2943. + unsigned long connect_delay;
  2944. +
  2945. + struct ssam_event_notifier notif;
  2946. + struct ssam_hub_ops ops;
  2947. +};
  2948. +
  2949. +struct ssam_hub_desc {
  2950. + struct {
  2951. + struct ssam_event_registry reg;
  2952. + struct ssam_event_id id;
  2953. + enum ssam_event_mask mask;
  2954. + } event;
  2955. +
  2956. + struct {
  2957. + u32 (*notify)(struct ssam_event_notifier *nf, const struct ssam_event *event);
  2958. + int (*get_state)(struct ssam_hub *hub, enum ssam_hub_state *state);
  2959. + } ops;
  2960. +
  2961. + unsigned long connect_delay_ms;
  2962. +};
  2963. +
  2964. +static void ssam_hub_update_workfn(struct work_struct *work)
  2965. +{
  2966. + struct ssam_hub *hub = container_of(work, struct ssam_hub, update_work.work);
  2967. + enum ssam_hub_state state;
  2968. + int status = 0;
  2969. +
  2970. + status = hub->ops.get_state(hub, &state);
  2971. + if (status)
  2972. + return;
  2973. +
  2974. + /*
  2975. + * There is a small possibility that hub devices were hot-removed and
  2976. + * re-added before we were able to remove them here. In that case, both
  2977. + * the state returned by get_state() and the state of the hub will
  2978. + * equal SSAM_HUB_CONNECTED and we would bail early below, which would
  2979. + * leave child devices without proper (re-)initialization and the
  2980. + * hot-remove flag set.
  2981. + *
  2982. + * Therefore, we check whether devices have been hot-removed via an
  2983. + * additional flag on the hub and, in this case, override the returned
  2984. + * hub state. In case of a missed disconnect (i.e. get_state returned
  2985. + * "connected"), we further need to re-schedule this work (with the
  2986. + * appropriate delay) as the actual connect work submission might have
  2987. + * been merged with this one.
  2988. + *
  2989. + * This then leads to one of two cases: Either we submit an unnecessary
  2990. + * work item (which will get ignored via either the queue or the state
  2991. + * checks) or, in the unlikely case that the work is actually required,
  2992. + * double the normal connect delay.
  2993. + */
  2994. + if (test_and_clear_bit(SSAM_HUB_HOT_REMOVED, &hub->flags)) {
  2995. + if (state == SSAM_HUB_CONNECTED)
  2996. + schedule_delayed_work(&hub->update_work, hub->connect_delay);
  2997. +
  2998. + state = SSAM_HUB_DISCONNECTED;
  2999. + }
  3000. +
  3001. + if (hub->state == state)
  3002. + return;
  3003. + hub->state = state;
  3004. +
  3005. + if (hub->state == SSAM_HUB_CONNECTED)
  3006. + status = ssam_device_register_clients(hub->sdev);
  3007. + else
  3008. + ssam_remove_clients(&hub->sdev->dev);
  3009. +
  3010. + if (status)
  3011. + dev_err(&hub->sdev->dev, "failed to update hub child devices: %d\n", status);
  3012. +}
  3013. +
  3014. +static int ssam_hub_mark_hot_removed(struct device *dev, void *_data)
  3015. +{
  3016. + struct ssam_device *sdev = to_ssam_device(dev);
  3017. +
  3018. + if (is_ssam_device(dev))
  3019. + ssam_device_mark_hot_removed(sdev);
  3020. +
  3021. + return 0;
  3022. +}
  3023. +
  3024. +static void ssam_hub_update(struct ssam_hub *hub, bool connected)
  3025. +{
  3026. + unsigned long delay;
  3027. +
  3028. + /* Mark devices as hot-removed before we remove any. */
  3029. + if (!connected) {
  3030. + set_bit(SSAM_HUB_HOT_REMOVED, &hub->flags);
  3031. + device_for_each_child_reverse(&hub->sdev->dev, NULL, ssam_hub_mark_hot_removed);
  3032. + }
  3033. +
  3034. + /*
  3035. + * Delay update when the base/keyboard cover is being connected to give
  3036. + * devices/EC some time to set up.
  3037. + */
  3038. + delay = connected ? hub->connect_delay : 0;
  3039. +
  3040. + schedule_delayed_work(&hub->update_work, delay);
  3041. +}
  3042. +
  3043. +static int __maybe_unused ssam_hub_resume(struct device *dev)
  3044. +{
  3045. + struct ssam_hub *hub = dev_get_drvdata(dev);
  3046. +
  3047. + schedule_delayed_work(&hub->update_work, 0);
  3048. + return 0;
  3049. +}
  3050. +static SIMPLE_DEV_PM_OPS(ssam_hub_pm_ops, NULL, ssam_hub_resume);
  3051. +
  3052. +static int ssam_hub_probe(struct ssam_device *sdev)
  3053. +{
  3054. + const struct ssam_hub_desc *desc;
  3055. + struct ssam_hub *hub;
  3056. + int status;
  3057. +
  3058. + desc = ssam_device_get_match_data(sdev);
  3059. + if (!desc) {
  3060. + WARN(1, "no driver match data specified");
  3061. + return -EINVAL;
  3062. + }
  3063. +
  3064. + hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL);
  3065. + if (!hub)
  3066. + return -ENOMEM;
  3067. +
  3068. + hub->sdev = sdev;
  3069. + hub->state = SSAM_HUB_UNINITIALIZED;
  3070. +
  3071. + hub->notif.base.priority = INT_MAX; /* This notifier should run first. */
  3072. + hub->notif.base.fn = desc->ops.notify;
  3073. + hub->notif.event.reg = desc->event.reg;
  3074. + hub->notif.event.id = desc->event.id;
  3075. + hub->notif.event.mask = desc->event.mask;
  3076. + hub->notif.event.flags = SSAM_EVENT_SEQUENCED;
  3077. +
  3078. + hub->connect_delay = msecs_to_jiffies(desc->connect_delay_ms);
  3079. + hub->ops.get_state = desc->ops.get_state;
  3080. +
  3081. + INIT_DELAYED_WORK(&hub->update_work, ssam_hub_update_workfn);
  3082. +
  3083. + ssam_device_set_drvdata(sdev, hub);
  3084. +
  3085. + status = ssam_device_notifier_register(sdev, &hub->notif);
  3086. + if (status)
  3087. + return status;
  3088. +
  3089. + schedule_delayed_work(&hub->update_work, 0);
  3090. + return 0;
  3091. +}
  3092. +
  3093. +static void ssam_hub_remove(struct ssam_device *sdev)
  3094. +{
  3095. + struct ssam_hub *hub = ssam_device_get_drvdata(sdev);
  3096. +
  3097. + ssam_device_notifier_unregister(sdev, &hub->notif);
  3098. + cancel_delayed_work_sync(&hub->update_work);
  3099. + ssam_remove_clients(&sdev->dev);
  3100. +}
  3101. +
  3102. +
  3103. +/* -- SSAM base-subsystem hub driver. --------------------------------------- */
  3104. +
  3105. +/*
  3106. + * Some devices (especially battery) may need a bit of time to be fully usable
  3107. + * after being (re-)connected. This delay has been determined via
  3108. + * experimentation.
  3109. + */
  3110. +#define SSAM_BASE_UPDATE_CONNECT_DELAY 2500
  3111. +
  3112. +SSAM_DEFINE_SYNC_REQUEST_R(ssam_bas_query_opmode, u8, {
  3113. + .target_category = SSAM_SSH_TC_BAS,
  3114. + .target_id = 0x01,
  3115. + .command_id = 0x0d,
  3116. + .instance_id = 0x00,
  3117. +});
  3118. +
  3119. +#define SSAM_BAS_OPMODE_TABLET 0x00
  3120. +#define SSAM_EVENT_BAS_CID_CONNECTION 0x0c
  3121. +
  3122. +static int ssam_base_hub_query_state(struct ssam_hub *hub, enum ssam_hub_state *state)
  3123. +{
  3124. + u8 opmode;
  3125. + int status;
  3126. +
  3127. + status = ssam_retry(ssam_bas_query_opmode, hub->sdev->ctrl, &opmode);
  3128. + if (status < 0) {
  3129. + dev_err(&hub->sdev->dev, "failed to query base state: %d\n", status);
  3130. + return status;
  3131. + }
  3132. +
  3133. + if (opmode != SSAM_BAS_OPMODE_TABLET)
  3134. + *state = SSAM_HUB_CONNECTED;
  3135. + else
  3136. + *state = SSAM_HUB_DISCONNECTED;
  3137. +
  3138. + return 0;
  3139. +}
  3140. +
  3141. +static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
  3142. +{
  3143. + struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
  3144. +
  3145. + if (event->command_id != SSAM_EVENT_BAS_CID_CONNECTION)
  3146. + return 0;
  3147. +
  3148. + if (event->length < 1) {
  3149. + dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length);
  3150. + return 0;
  3151. + }
  3152. +
  3153. + ssam_hub_update(hub, event->data[0]);
  3154. +
  3155. + /*
  3156. + * Do not return SSAM_NOTIF_HANDLED: The event should be picked up and
  3157. + * consumed by the detachment system driver. We're just a (more or less)
  3158. + * silent observer.
  3159. + */
  3160. + return 0;
  3161. +}
  3162. +
  3163. +static const struct ssam_hub_desc base_hub = {
  3164. + .event = {
  3165. + .reg = SSAM_EVENT_REGISTRY_SAM,
  3166. + .id = {
  3167. + .target_category = SSAM_SSH_TC_BAS,
  3168. + .instance = 0,
  3169. + },
  3170. + .mask = SSAM_EVENT_MASK_NONE,
  3171. + },
  3172. + .ops = {
  3173. + .notify = ssam_base_hub_notif,
  3174. + .get_state = ssam_base_hub_query_state,
  3175. + },
  3176. + .connect_delay_ms = SSAM_BASE_UPDATE_CONNECT_DELAY,
  3177. +};
  3178. +
  3179. +
  3180. +/* -- SSAM KIP-subsystem hub driver. ---------------------------------------- */
  3181. +
  3182. +/*
  3183. + * Some devices may need a bit of time to be fully usable after being
  3184. + * (re-)connected. This delay has been determined via experimentation.
  3185. + */
  3186. +#define SSAM_KIP_UPDATE_CONNECT_DELAY 250
  3187. +
  3188. +#define SSAM_EVENT_KIP_CID_CONNECTION 0x2c
  3189. +
  3190. +SSAM_DEFINE_SYNC_REQUEST_R(__ssam_kip_query_state, u8, {
  3191. + .target_category = SSAM_SSH_TC_KIP,
  3192. + .target_id = 0x01,
  3193. + .command_id = 0x2c,
  3194. + .instance_id = 0x00,
  3195. +});
  3196. +
  3197. +static int ssam_kip_hub_query_state(struct ssam_hub *hub, enum ssam_hub_state *state)
  3198. +{
  3199. + int status;
  3200. + u8 connected;
  3201. +
  3202. + status = ssam_retry(__ssam_kip_query_state, hub->sdev->ctrl, &connected);
  3203. + if (status < 0) {
  3204. + dev_err(&hub->sdev->dev, "failed to query KIP connection state: %d\n", status);
  3205. + return status;
  3206. + }
  3207. +
  3208. + *state = connected ? SSAM_HUB_CONNECTED : SSAM_HUB_DISCONNECTED;
  3209. + return 0;
  3210. +}
  3211. +
  3212. +static u32 ssam_kip_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
  3213. +{
  3214. + struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
  3215. +
  3216. + if (event->command_id != SSAM_EVENT_KIP_CID_CONNECTION)
  3217. + return 0; /* Return "unhandled". */
  3218. +
  3219. + if (event->length < 1) {
  3220. + dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length);
  3221. + return 0;
  3222. + }
  3223. +
  3224. + ssam_hub_update(hub, event->data[0]);
  3225. + return SSAM_NOTIF_HANDLED;
  3226. +}
  3227. +
  3228. +static const struct ssam_hub_desc kip_hub = {
  3229. + .event = {
  3230. + .reg = SSAM_EVENT_REGISTRY_SAM,
  3231. + .id = {
  3232. + .target_category = SSAM_SSH_TC_KIP,
  3233. + .instance = 0,
  3234. + },
  3235. + .mask = SSAM_EVENT_MASK_TARGET,
  3236. + },
  3237. + .ops = {
  3238. + .notify = ssam_kip_hub_notif,
  3239. + .get_state = ssam_kip_hub_query_state,
  3240. + },
  3241. + .connect_delay_ms = SSAM_KIP_UPDATE_CONNECT_DELAY,
  3242. +};
  3243. +
  3244. +
  3245. +/* -- Driver registration. -------------------------------------------------- */
  3246. +
  3247. +static const struct ssam_device_id ssam_hub_match[] = {
  3248. + { SSAM_VDEV(HUB, 0x01, SSAM_SSH_TC_KIP, 0x00), (unsigned long)&kip_hub },
  3249. + { SSAM_VDEV(HUB, 0x02, SSAM_SSH_TC_BAS, 0x00), (unsigned long)&base_hub },
  3250. + { }
  3251. +};
  3252. +MODULE_DEVICE_TABLE(ssam, ssam_hub_match);
  3253. +
  3254. +static struct ssam_device_driver ssam_subsystem_hub_driver = {
  3255. + .probe = ssam_hub_probe,
  3256. + .remove = ssam_hub_remove,
  3257. + .match_table = ssam_hub_match,
  3258. + .driver = {
  3259. + .name = "surface_aggregator_subsystem_hub",
  3260. + .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  3261. + .pm = &ssam_hub_pm_ops,
  3262. + },
  3263. +};
  3264. +module_ssam_device_driver(ssam_subsystem_hub_driver);
  3265. +
  3266. +MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
  3267. +MODULE_DESCRIPTION("Subsystem device hub driver for Surface System Aggregator Module");
  3268. +MODULE_LICENSE("GPL");
  3269. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  3270. index c680792a037e..0cbb7f3a6b2d 100644
  3271. --- a/drivers/platform/surface/surface_aggregator_registry.c
  3272. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  3273. @@ -11,14 +11,11 @@
  3274. #include <linux/acpi.h>
  3275. #include <linux/kernel.h>
  3276. -#include <linux/limits.h>
  3277. #include <linux/module.h>
  3278. #include <linux/platform_device.h>
  3279. #include <linux/property.h>
  3280. #include <linux/types.h>
  3281. -#include <linux/workqueue.h>
  3282. -#include <linux/surface_aggregator/controller.h>
  3283. #include <linux/surface_aggregator/device.h>
  3284. @@ -286,335 +283,6 @@ static const struct software_node *ssam_node_group_sp8[] = {
  3285. };
  3286. -/* -- SSAM generic subsystem hub driver framework. -------------------------- */
  3287. -
  3288. -enum ssam_hub_state {
  3289. - SSAM_HUB_UNINITIALIZED, /* Only set during initialization. */
  3290. - SSAM_HUB_CONNECTED,
  3291. - SSAM_HUB_DISCONNECTED,
  3292. -};
  3293. -
  3294. -enum ssam_hub_flags {
  3295. - SSAM_HUB_HOT_REMOVED,
  3296. -};
  3297. -
  3298. -struct ssam_hub {
  3299. - struct ssam_device *sdev;
  3300. -
  3301. - enum ssam_hub_state state;
  3302. - unsigned long flags;
  3303. -
  3304. - struct delayed_work update_work;
  3305. - unsigned long connect_delay;
  3306. -
  3307. - struct ssam_event_notifier notif;
  3308. -
  3309. - int (*get_state)(struct ssam_hub *hub, enum ssam_hub_state *state);
  3310. -};
  3311. -
  3312. -static void ssam_hub_update_workfn(struct work_struct *work)
  3313. -{
  3314. - struct ssam_hub *hub = container_of(work, struct ssam_hub, update_work.work);
  3315. - enum ssam_hub_state state;
  3316. - int status = 0;
  3317. -
  3318. - status = hub->get_state(hub, &state);
  3319. - if (status)
  3320. - return;
  3321. -
  3322. - /*
  3323. - * There is a small possibility that hub devices were hot-removed and
  3324. - * re-added before we were able to remove them here. In that case, both
  3325. - * the state returned by get_state() and the state of the hub will
  3326. - * equal SSAM_HUB_CONNECTED and we would bail early below, which would
  3327. - * leave child devices without proper (re-)initialization and the
  3328. - * hot-remove flag set.
  3329. - *
  3330. - * Therefore, we check whether devices have been hot-removed via an
  3331. - * additional flag on the hub and, in this case, override the returned
  3332. - * hub state. In case of a missed disconnect (i.e. get_state returned
  3333. - * "connected"), we further need to re-schedule this work (with the
  3334. - * appropriate delay) as the actual connect work submission might have
  3335. - * been merged with this one.
  3336. - *
  3337. - * This then leads to one of two cases: Either we submit an unnecessary
  3338. - * work item (which will get ignored via either the queue or the state
  3339. - * checks) or, in the unlikely case that the work is actually required,
  3340. - * double the normal connect delay.
  3341. - */
  3342. - if (test_and_clear_bit(SSAM_HUB_HOT_REMOVED, &hub->flags)) {
  3343. - if (state == SSAM_HUB_CONNECTED)
  3344. - schedule_delayed_work(&hub->update_work, hub->connect_delay);
  3345. -
  3346. - state = SSAM_HUB_DISCONNECTED;
  3347. - }
  3348. -
  3349. - if (hub->state == state)
  3350. - return;
  3351. - hub->state = state;
  3352. -
  3353. - if (hub->state == SSAM_HUB_CONNECTED)
  3354. - status = ssam_device_register_clients(hub->sdev);
  3355. - else
  3356. - ssam_remove_clients(&hub->sdev->dev);
  3357. -
  3358. - if (status)
  3359. - dev_err(&hub->sdev->dev, "failed to update hub child devices: %d\n", status);
  3360. -}
  3361. -
  3362. -static int ssam_hub_mark_hot_removed(struct device *dev, void *_data)
  3363. -{
  3364. - struct ssam_device *sdev = to_ssam_device(dev);
  3365. -
  3366. - if (is_ssam_device(dev))
  3367. - ssam_device_mark_hot_removed(sdev);
  3368. -
  3369. - return 0;
  3370. -}
  3371. -
  3372. -static void ssam_hub_update(struct ssam_hub *hub, bool connected)
  3373. -{
  3374. - unsigned long delay;
  3375. -
  3376. - /* Mark devices as hot-removed before we remove any. */
  3377. - if (!connected) {
  3378. - set_bit(SSAM_HUB_HOT_REMOVED, &hub->flags);
  3379. - device_for_each_child_reverse(&hub->sdev->dev, NULL, ssam_hub_mark_hot_removed);
  3380. - }
  3381. -
  3382. - /*
  3383. - * Delay update when the base/keyboard cover is being connected to give
  3384. - * devices/EC some time to set up.
  3385. - */
  3386. - delay = connected ? hub->connect_delay : 0;
  3387. -
  3388. - schedule_delayed_work(&hub->update_work, delay);
  3389. -}
  3390. -
  3391. -static int __maybe_unused ssam_hub_resume(struct device *dev)
  3392. -{
  3393. - struct ssam_hub *hub = dev_get_drvdata(dev);
  3394. -
  3395. - schedule_delayed_work(&hub->update_work, 0);
  3396. - return 0;
  3397. -}
  3398. -static SIMPLE_DEV_PM_OPS(ssam_hub_pm_ops, NULL, ssam_hub_resume);
  3399. -
  3400. -static int ssam_hub_setup(struct ssam_device *sdev, struct ssam_hub *hub)
  3401. -{
  3402. - int status;
  3403. -
  3404. - hub->sdev = sdev;
  3405. - hub->state = SSAM_HUB_UNINITIALIZED;
  3406. -
  3407. - INIT_DELAYED_WORK(&hub->update_work, ssam_hub_update_workfn);
  3408. -
  3409. - ssam_device_set_drvdata(sdev, hub);
  3410. -
  3411. - status = ssam_device_notifier_register(sdev, &hub->notif);
  3412. - if (status)
  3413. - return status;
  3414. -
  3415. - schedule_delayed_work(&hub->update_work, 0);
  3416. - return 0;
  3417. -}
  3418. -
  3419. -static void ssam_hub_remove(struct ssam_device *sdev)
  3420. -{
  3421. - struct ssam_hub *hub = ssam_device_get_drvdata(sdev);
  3422. -
  3423. - ssam_device_notifier_unregister(sdev, &hub->notif);
  3424. - cancel_delayed_work_sync(&hub->update_work);
  3425. - ssam_remove_clients(&sdev->dev);
  3426. -}
  3427. -
  3428. -
  3429. -/* -- SSAM base-hub driver. ------------------------------------------------- */
  3430. -
  3431. -/*
  3432. - * Some devices (especially battery) may need a bit of time to be fully usable
  3433. - * after being (re-)connected. This delay has been determined via
  3434. - * experimentation.
  3435. - */
  3436. -#define SSAM_BASE_UPDATE_CONNECT_DELAY msecs_to_jiffies(2500)
  3437. -
  3438. -SSAM_DEFINE_SYNC_REQUEST_R(ssam_bas_query_opmode, u8, {
  3439. - .target_category = SSAM_SSH_TC_BAS,
  3440. - .target_id = 0x01,
  3441. - .command_id = 0x0d,
  3442. - .instance_id = 0x00,
  3443. -});
  3444. -
  3445. -#define SSAM_BAS_OPMODE_TABLET 0x00
  3446. -#define SSAM_EVENT_BAS_CID_CONNECTION 0x0c
  3447. -
  3448. -static int ssam_base_hub_query_state(struct ssam_hub *hub, enum ssam_hub_state *state)
  3449. -{
  3450. - u8 opmode;
  3451. - int status;
  3452. -
  3453. - status = ssam_retry(ssam_bas_query_opmode, hub->sdev->ctrl, &opmode);
  3454. - if (status < 0) {
  3455. - dev_err(&hub->sdev->dev, "failed to query base state: %d\n", status);
  3456. - return status;
  3457. - }
  3458. -
  3459. - if (opmode != SSAM_BAS_OPMODE_TABLET)
  3460. - *state = SSAM_HUB_CONNECTED;
  3461. - else
  3462. - *state = SSAM_HUB_DISCONNECTED;
  3463. -
  3464. - return 0;
  3465. -}
  3466. -
  3467. -static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
  3468. -{
  3469. - struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
  3470. -
  3471. - if (event->command_id != SSAM_EVENT_BAS_CID_CONNECTION)
  3472. - return 0;
  3473. -
  3474. - if (event->length < 1) {
  3475. - dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length);
  3476. - return 0;
  3477. - }
  3478. -
  3479. - ssam_hub_update(hub, event->data[0]);
  3480. -
  3481. - /*
  3482. - * Do not return SSAM_NOTIF_HANDLED: The event should be picked up and
  3483. - * consumed by the detachment system driver. We're just a (more or less)
  3484. - * silent observer.
  3485. - */
  3486. - return 0;
  3487. -}
  3488. -
  3489. -static int ssam_base_hub_probe(struct ssam_device *sdev)
  3490. -{
  3491. - struct ssam_hub *hub;
  3492. -
  3493. - hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL);
  3494. - if (!hub)
  3495. - return -ENOMEM;
  3496. -
  3497. - hub->notif.base.priority = INT_MAX; /* This notifier should run first. */
  3498. - hub->notif.base.fn = ssam_base_hub_notif;
  3499. - hub->notif.event.reg = SSAM_EVENT_REGISTRY_SAM;
  3500. - hub->notif.event.id.target_category = SSAM_SSH_TC_BAS,
  3501. - hub->notif.event.id.instance = 0,
  3502. - hub->notif.event.mask = SSAM_EVENT_MASK_NONE;
  3503. - hub->notif.event.flags = SSAM_EVENT_SEQUENCED;
  3504. -
  3505. - hub->connect_delay = SSAM_BASE_UPDATE_CONNECT_DELAY;
  3506. - hub->get_state = ssam_base_hub_query_state;
  3507. -
  3508. - return ssam_hub_setup(sdev, hub);
  3509. -}
  3510. -
  3511. -static const struct ssam_device_id ssam_base_hub_match[] = {
  3512. - { SSAM_VDEV(HUB, 0x02, SSAM_SSH_TC_BAS, 0x00) },
  3513. - { },
  3514. -};
  3515. -
  3516. -static struct ssam_device_driver ssam_base_hub_driver = {
  3517. - .probe = ssam_base_hub_probe,
  3518. - .remove = ssam_hub_remove,
  3519. - .match_table = ssam_base_hub_match,
  3520. - .driver = {
  3521. - .name = "surface_aggregator_base_hub",
  3522. - .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  3523. - .pm = &ssam_hub_pm_ops,
  3524. - },
  3525. -};
  3526. -
  3527. -
  3528. -/* -- SSAM KIP-subsystem hub driver. ---------------------------------------- */
  3529. -
  3530. -/*
  3531. - * Some devices may need a bit of time to be fully usable after being
  3532. - * (re-)connected. This delay has been determined via experimentation.
  3533. - */
  3534. -#define SSAM_KIP_UPDATE_CONNECT_DELAY msecs_to_jiffies(250)
  3535. -
  3536. -#define SSAM_EVENT_KIP_CID_CONNECTION 0x2c
  3537. -
  3538. -SSAM_DEFINE_SYNC_REQUEST_R(__ssam_kip_get_connection_state, u8, {
  3539. - .target_category = SSAM_SSH_TC_KIP,
  3540. - .target_id = 0x01,
  3541. - .command_id = 0x2c,
  3542. - .instance_id = 0x00,
  3543. -});
  3544. -
  3545. -static int ssam_kip_get_connection_state(struct ssam_hub *hub, enum ssam_hub_state *state)
  3546. -{
  3547. - int status;
  3548. - u8 connected;
  3549. -
  3550. - status = ssam_retry(__ssam_kip_get_connection_state, hub->sdev->ctrl, &connected);
  3551. - if (status < 0) {
  3552. - dev_err(&hub->sdev->dev, "failed to query KIP connection state: %d\n", status);
  3553. - return status;
  3554. - }
  3555. -
  3556. - *state = connected ? SSAM_HUB_CONNECTED : SSAM_HUB_DISCONNECTED;
  3557. - return 0;
  3558. -}
  3559. -
  3560. -static u32 ssam_kip_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
  3561. -{
  3562. - struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
  3563. -
  3564. - if (event->command_id != SSAM_EVENT_KIP_CID_CONNECTION)
  3565. - return 0; /* Return "unhandled". */
  3566. -
  3567. - if (event->length < 1) {
  3568. - dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length);
  3569. - return 0;
  3570. - }
  3571. -
  3572. - ssam_hub_update(hub, event->data[0]);
  3573. - return SSAM_NOTIF_HANDLED;
  3574. -}
  3575. -
  3576. -static int ssam_kip_hub_probe(struct ssam_device *sdev)
  3577. -{
  3578. - struct ssam_hub *hub;
  3579. -
  3580. - hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL);
  3581. - if (!hub)
  3582. - return -ENOMEM;
  3583. -
  3584. - hub->notif.base.priority = INT_MAX; /* This notifier should run first. */
  3585. - hub->notif.base.fn = ssam_kip_hub_notif;
  3586. - hub->notif.event.reg = SSAM_EVENT_REGISTRY_SAM;
  3587. - hub->notif.event.id.target_category = SSAM_SSH_TC_KIP,
  3588. - hub->notif.event.id.instance = 0,
  3589. - hub->notif.event.mask = SSAM_EVENT_MASK_TARGET;
  3590. - hub->notif.event.flags = SSAM_EVENT_SEQUENCED;
  3591. -
  3592. - hub->connect_delay = SSAM_KIP_UPDATE_CONNECT_DELAY;
  3593. - hub->get_state = ssam_kip_get_connection_state;
  3594. -
  3595. - return ssam_hub_setup(sdev, hub);
  3596. -}
  3597. -
  3598. -static const struct ssam_device_id ssam_kip_hub_match[] = {
  3599. - { SSAM_VDEV(HUB, 0x01, SSAM_SSH_TC_KIP, 0x00) },
  3600. - { },
  3601. -};
  3602. -
  3603. -static struct ssam_device_driver ssam_kip_hub_driver = {
  3604. - .probe = ssam_kip_hub_probe,
  3605. - .remove = ssam_hub_remove,
  3606. - .match_table = ssam_kip_hub_match,
  3607. - .driver = {
  3608. - .name = "surface_kip_hub",
  3609. - .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  3610. - .pm = &ssam_hub_pm_ops,
  3611. - },
  3612. -};
  3613. -
  3614. -
  3615. /* -- SSAM platform/meta-hub driver. ---------------------------------------- */
  3616. static const struct acpi_device_id ssam_platform_hub_match[] = {
  3617. @@ -727,44 +395,7 @@ static struct platform_driver ssam_platform_hub_driver = {
  3618. .probe_type = PROBE_PREFER_ASYNCHRONOUS,
  3619. },
  3620. };
  3621. -
  3622. -
  3623. -/* -- Module initialization. ------------------------------------------------ */
  3624. -
  3625. -static int __init ssam_device_hub_init(void)
  3626. -{
  3627. - int status;
  3628. -
  3629. - status = platform_driver_register(&ssam_platform_hub_driver);
  3630. - if (status)
  3631. - goto err_platform;
  3632. -
  3633. - status = ssam_device_driver_register(&ssam_base_hub_driver);
  3634. - if (status)
  3635. - goto err_base;
  3636. -
  3637. - status = ssam_device_driver_register(&ssam_kip_hub_driver);
  3638. - if (status)
  3639. - goto err_kip;
  3640. -
  3641. - return 0;
  3642. -
  3643. -err_kip:
  3644. - ssam_device_driver_unregister(&ssam_base_hub_driver);
  3645. -err_base:
  3646. - platform_driver_unregister(&ssam_platform_hub_driver);
  3647. -err_platform:
  3648. - return status;
  3649. -}
  3650. -module_init(ssam_device_hub_init);
  3651. -
  3652. -static void __exit ssam_device_hub_exit(void)
  3653. -{
  3654. - ssam_device_driver_unregister(&ssam_kip_hub_driver);
  3655. - ssam_device_driver_unregister(&ssam_base_hub_driver);
  3656. - platform_driver_unregister(&ssam_platform_hub_driver);
  3657. -}
  3658. -module_exit(ssam_device_hub_exit);
  3659. +module_platform_driver(ssam_platform_hub_driver);
  3660. MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
  3661. MODULE_DESCRIPTION("Device-registry for Surface System Aggregator Module");
  3662. --
  3663. 2.37.2
  3664. From 19b914283b8e6567b0deb085053a8a781c1ad0fa Mon Sep 17 00:00:00 2001
  3665. From: Maximilian Luz <luzmaximilian@gmail.com>
  3666. Date: Sat, 21 May 2022 00:57:40 +0200
  3667. Subject: [PATCH] platform/surface: Update copyright year of various drivers
  3668. Update the copyright of various Surface drivers to the current year.
  3669. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  3670. Patchset: surface-sam
  3671. ---
  3672. drivers/platform/surface/aggregator/Kconfig | 2 +-
  3673. drivers/platform/surface/aggregator/Makefile | 2 +-
  3674. drivers/platform/surface/aggregator/bus.c | 2 +-
  3675. drivers/platform/surface/aggregator/bus.h | 2 +-
  3676. drivers/platform/surface/aggregator/controller.c | 2 +-
  3677. drivers/platform/surface/aggregator/controller.h | 2 +-
  3678. drivers/platform/surface/aggregator/core.c | 2 +-
  3679. drivers/platform/surface/aggregator/ssh_msgb.h | 2 +-
  3680. drivers/platform/surface/aggregator/ssh_packet_layer.c | 2 +-
  3681. drivers/platform/surface/aggregator/ssh_packet_layer.h | 2 +-
  3682. drivers/platform/surface/aggregator/ssh_parser.c | 2 +-
  3683. drivers/platform/surface/aggregator/ssh_parser.h | 2 +-
  3684. drivers/platform/surface/aggregator/ssh_request_layer.c | 2 +-
  3685. drivers/platform/surface/aggregator/ssh_request_layer.h | 2 +-
  3686. drivers/platform/surface/aggregator/trace.h | 2 +-
  3687. drivers/platform/surface/surface_acpi_notify.c | 2 +-
  3688. drivers/platform/surface/surface_aggregator_cdev.c | 2 +-
  3689. drivers/platform/surface/surface_aggregator_registry.c | 2 +-
  3690. drivers/platform/surface/surface_dtx.c | 2 +-
  3691. drivers/platform/surface/surface_gpe.c | 2 +-
  3692. drivers/platform/surface/surface_hotplug.c | 2 +-
  3693. drivers/platform/surface/surface_platform_profile.c | 2 +-
  3694. 22 files changed, 22 insertions(+), 22 deletions(-)
  3695. diff --git a/drivers/platform/surface/aggregator/Kconfig b/drivers/platform/surface/aggregator/Kconfig
  3696. index cab020324256..c114f9dd5fe1 100644
  3697. --- a/drivers/platform/surface/aggregator/Kconfig
  3698. +++ b/drivers/platform/surface/aggregator/Kconfig
  3699. @@ -1,5 +1,5 @@
  3700. # SPDX-License-Identifier: GPL-2.0+
  3701. -# Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3702. +# Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3703. menuconfig SURFACE_AGGREGATOR
  3704. tristate "Microsoft Surface System Aggregator Module Subsystem and Drivers"
  3705. diff --git a/drivers/platform/surface/aggregator/Makefile b/drivers/platform/surface/aggregator/Makefile
  3706. index c0d550eda5cd..fdf664a217f9 100644
  3707. --- a/drivers/platform/surface/aggregator/Makefile
  3708. +++ b/drivers/platform/surface/aggregator/Makefile
  3709. @@ -1,5 +1,5 @@
  3710. # SPDX-License-Identifier: GPL-2.0+
  3711. -# Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3712. +# Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3713. # For include/trace/define_trace.h to include trace.h
  3714. CFLAGS_core.o = -I$(src)
  3715. diff --git a/drivers/platform/surface/aggregator/bus.c b/drivers/platform/surface/aggregator/bus.c
  3716. index 4bba60884bb5..96986042a257 100644
  3717. --- a/drivers/platform/surface/aggregator/bus.c
  3718. +++ b/drivers/platform/surface/aggregator/bus.c
  3719. @@ -2,7 +2,7 @@
  3720. /*
  3721. * Surface System Aggregator Module bus and device integration.
  3722. *
  3723. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3724. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3725. */
  3726. #include <linux/device.h>
  3727. diff --git a/drivers/platform/surface/aggregator/bus.h b/drivers/platform/surface/aggregator/bus.h
  3728. index 6964ee84e79c..5b4dbf21906c 100644
  3729. --- a/drivers/platform/surface/aggregator/bus.h
  3730. +++ b/drivers/platform/surface/aggregator/bus.h
  3731. @@ -2,7 +2,7 @@
  3732. /*
  3733. * Surface System Aggregator Module bus and device integration.
  3734. *
  3735. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3736. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3737. */
  3738. #ifndef _SURFACE_AGGREGATOR_BUS_H
  3739. diff --git a/drivers/platform/surface/aggregator/controller.c b/drivers/platform/surface/aggregator/controller.c
  3740. index 6de834b52b63..43e765199137 100644
  3741. --- a/drivers/platform/surface/aggregator/controller.c
  3742. +++ b/drivers/platform/surface/aggregator/controller.c
  3743. @@ -2,7 +2,7 @@
  3744. /*
  3745. * Main SSAM/SSH controller structure and functionality.
  3746. *
  3747. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3748. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3749. */
  3750. #include <linux/acpi.h>
  3751. diff --git a/drivers/platform/surface/aggregator/controller.h b/drivers/platform/surface/aggregator/controller.h
  3752. index a0963c3562ff..f0d987abc51e 100644
  3753. --- a/drivers/platform/surface/aggregator/controller.h
  3754. +++ b/drivers/platform/surface/aggregator/controller.h
  3755. @@ -2,7 +2,7 @@
  3756. /*
  3757. * Main SSAM/SSH controller structure and functionality.
  3758. *
  3759. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3760. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3761. */
  3762. #ifndef _SURFACE_AGGREGATOR_CONTROLLER_H
  3763. diff --git a/drivers/platform/surface/aggregator/core.c b/drivers/platform/surface/aggregator/core.c
  3764. index a62c5dfe42d6..1a6373dea109 100644
  3765. --- a/drivers/platform/surface/aggregator/core.c
  3766. +++ b/drivers/platform/surface/aggregator/core.c
  3767. @@ -7,7 +7,7 @@
  3768. * Handles communication via requests as well as enabling, disabling, and
  3769. * relaying of events.
  3770. *
  3771. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3772. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3773. */
  3774. #include <linux/acpi.h>
  3775. diff --git a/drivers/platform/surface/aggregator/ssh_msgb.h b/drivers/platform/surface/aggregator/ssh_msgb.h
  3776. index e562958ffdf0..f3ecad92eefd 100644
  3777. --- a/drivers/platform/surface/aggregator/ssh_msgb.h
  3778. +++ b/drivers/platform/surface/aggregator/ssh_msgb.h
  3779. @@ -2,7 +2,7 @@
  3780. /*
  3781. * SSH message builder functions.
  3782. *
  3783. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3784. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3785. */
  3786. #ifndef _SURFACE_AGGREGATOR_SSH_MSGB_H
  3787. diff --git a/drivers/platform/surface/aggregator/ssh_packet_layer.c b/drivers/platform/surface/aggregator/ssh_packet_layer.c
  3788. index 8a4451c1ffe5..6748fe4ac5d5 100644
  3789. --- a/drivers/platform/surface/aggregator/ssh_packet_layer.c
  3790. +++ b/drivers/platform/surface/aggregator/ssh_packet_layer.c
  3791. @@ -2,7 +2,7 @@
  3792. /*
  3793. * SSH packet transport layer.
  3794. *
  3795. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3796. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3797. */
  3798. #include <asm/unaligned.h>
  3799. diff --git a/drivers/platform/surface/aggregator/ssh_packet_layer.h b/drivers/platform/surface/aggregator/ssh_packet_layer.h
  3800. index 2eb329f0b91a..64633522f971 100644
  3801. --- a/drivers/platform/surface/aggregator/ssh_packet_layer.h
  3802. +++ b/drivers/platform/surface/aggregator/ssh_packet_layer.h
  3803. @@ -2,7 +2,7 @@
  3804. /*
  3805. * SSH packet transport layer.
  3806. *
  3807. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3808. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3809. */
  3810. #ifndef _SURFACE_AGGREGATOR_SSH_PACKET_LAYER_H
  3811. diff --git a/drivers/platform/surface/aggregator/ssh_parser.c b/drivers/platform/surface/aggregator/ssh_parser.c
  3812. index b77912f8f13b..a6f668694365 100644
  3813. --- a/drivers/platform/surface/aggregator/ssh_parser.c
  3814. +++ b/drivers/platform/surface/aggregator/ssh_parser.c
  3815. @@ -2,7 +2,7 @@
  3816. /*
  3817. * SSH message parser.
  3818. *
  3819. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3820. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3821. */
  3822. #include <asm/unaligned.h>
  3823. diff --git a/drivers/platform/surface/aggregator/ssh_parser.h b/drivers/platform/surface/aggregator/ssh_parser.h
  3824. index 3bd6e180fd16..801d8fa69fb5 100644
  3825. --- a/drivers/platform/surface/aggregator/ssh_parser.h
  3826. +++ b/drivers/platform/surface/aggregator/ssh_parser.h
  3827. @@ -2,7 +2,7 @@
  3828. /*
  3829. * SSH message parser.
  3830. *
  3831. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3832. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3833. */
  3834. #ifndef _SURFACE_AGGREGATOR_SSH_PARSER_H
  3835. diff --git a/drivers/platform/surface/aggregator/ssh_request_layer.c b/drivers/platform/surface/aggregator/ssh_request_layer.c
  3836. index 790f7f0eee98..f5565570f16c 100644
  3837. --- a/drivers/platform/surface/aggregator/ssh_request_layer.c
  3838. +++ b/drivers/platform/surface/aggregator/ssh_request_layer.c
  3839. @@ -2,7 +2,7 @@
  3840. /*
  3841. * SSH request transport layer.
  3842. *
  3843. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3844. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3845. */
  3846. #include <asm/unaligned.h>
  3847. diff --git a/drivers/platform/surface/aggregator/ssh_request_layer.h b/drivers/platform/surface/aggregator/ssh_request_layer.h
  3848. index 9c3cbae2d4bd..4e387a031351 100644
  3849. --- a/drivers/platform/surface/aggregator/ssh_request_layer.h
  3850. +++ b/drivers/platform/surface/aggregator/ssh_request_layer.h
  3851. @@ -2,7 +2,7 @@
  3852. /*
  3853. * SSH request transport layer.
  3854. *
  3855. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3856. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3857. */
  3858. #ifndef _SURFACE_AGGREGATOR_SSH_REQUEST_LAYER_H
  3859. diff --git a/drivers/platform/surface/aggregator/trace.h b/drivers/platform/surface/aggregator/trace.h
  3860. index cc9e73fbc18e..2a2c17771d01 100644
  3861. --- a/drivers/platform/surface/aggregator/trace.h
  3862. +++ b/drivers/platform/surface/aggregator/trace.h
  3863. @@ -2,7 +2,7 @@
  3864. /*
  3865. * Trace points for SSAM/SSH.
  3866. *
  3867. - * Copyright (C) 2020-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3868. + * Copyright (C) 2020-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3869. */
  3870. #undef TRACE_SYSTEM
  3871. diff --git a/drivers/platform/surface/surface_acpi_notify.c b/drivers/platform/surface/surface_acpi_notify.c
  3872. index 7b758f8cc137..b0a83255d060 100644
  3873. --- a/drivers/platform/surface/surface_acpi_notify.c
  3874. +++ b/drivers/platform/surface/surface_acpi_notify.c
  3875. @@ -8,7 +8,7 @@
  3876. * notifications sent from ACPI via the SAN interface by providing them to any
  3877. * registered external driver.
  3878. *
  3879. - * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
  3880. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3881. */
  3882. #include <asm/unaligned.h>
  3883. diff --git a/drivers/platform/surface/surface_aggregator_cdev.c b/drivers/platform/surface/surface_aggregator_cdev.c
  3884. index 30fb50fde450..492c82e69182 100644
  3885. --- a/drivers/platform/surface/surface_aggregator_cdev.c
  3886. +++ b/drivers/platform/surface/surface_aggregator_cdev.c
  3887. @@ -3,7 +3,7 @@
  3888. * Provides user-space access to the SSAM EC via the /dev/surface/aggregator
  3889. * misc device. Intended for debugging and development.
  3890. *
  3891. - * Copyright (C) 2020-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3892. + * Copyright (C) 2020-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3893. */
  3894. #include <linux/fs.h>
  3895. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  3896. index 0cbb7f3a6b2d..d5655f6a4a41 100644
  3897. --- a/drivers/platform/surface/surface_aggregator_registry.c
  3898. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  3899. @@ -6,7 +6,7 @@
  3900. * cannot be auto-detected. Provides device-hubs and performs instantiation
  3901. * for these devices.
  3902. *
  3903. - * Copyright (C) 2020-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3904. + * Copyright (C) 2020-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3905. */
  3906. #include <linux/acpi.h>
  3907. diff --git a/drivers/platform/surface/surface_dtx.c b/drivers/platform/surface/surface_dtx.c
  3908. index 1203b9a82993..ed36944467f9 100644
  3909. --- a/drivers/platform/surface/surface_dtx.c
  3910. +++ b/drivers/platform/surface/surface_dtx.c
  3911. @@ -8,7 +8,7 @@
  3912. * acknowledge (to speed things up), abort (e.g. in case the dGPU is still in
  3913. * use), or request detachment via user-space.
  3914. *
  3915. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3916. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3917. */
  3918. #include <linux/fs.h>
  3919. diff --git a/drivers/platform/surface/surface_gpe.c b/drivers/platform/surface/surface_gpe.c
  3920. index ec66fde28e75..27365cbe1ee9 100644
  3921. --- a/drivers/platform/surface/surface_gpe.c
  3922. +++ b/drivers/platform/surface/surface_gpe.c
  3923. @@ -4,7 +4,7 @@
  3924. * properly configuring the respective GPEs. Required for wakeup via lid on
  3925. * newer Intel-based Microsoft Surface devices.
  3926. *
  3927. - * Copyright (C) 2020 Maximilian Luz <luzmaximilian@gmail.com>
  3928. + * Copyright (C) 2020-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3929. */
  3930. #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  3931. diff --git a/drivers/platform/surface/surface_hotplug.c b/drivers/platform/surface/surface_hotplug.c
  3932. index cfcc15cfbacb..f004a2495201 100644
  3933. --- a/drivers/platform/surface/surface_hotplug.c
  3934. +++ b/drivers/platform/surface/surface_hotplug.c
  3935. @@ -10,7 +10,7 @@
  3936. * Event signaling is handled via ACPI, which will generate the appropriate
  3937. * device-check notifications to be picked up by the PCIe hot-plug driver.
  3938. *
  3939. - * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
  3940. + * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3941. */
  3942. #include <linux/acpi.h>
  3943. diff --git a/drivers/platform/surface/surface_platform_profile.c b/drivers/platform/surface/surface_platform_profile.c
  3944. index 6373d3b5eb7f..fbf2e11fd6ce 100644
  3945. --- a/drivers/platform/surface/surface_platform_profile.c
  3946. +++ b/drivers/platform/surface/surface_platform_profile.c
  3947. @@ -3,7 +3,7 @@
  3948. * Surface Platform Profile / Performance Mode driver for Surface System
  3949. * Aggregator Module (thermal subsystem).
  3950. *
  3951. - * Copyright (C) 2021 Maximilian Luz <luzmaximilian@gmail.com>
  3952. + * Copyright (C) 2021-2022 Maximilian Luz <luzmaximilian@gmail.com>
  3953. */
  3954. #include <asm/unaligned.h>
  3955. --
  3956. 2.37.2
  3957. From 19a402021f13a0b2382271189e1dc017205ada1f Mon Sep 17 00:00:00 2001
  3958. From: Maximilian Luz <luzmaximilian@gmail.com>
  3959. Date: Sat, 25 Jun 2022 20:42:00 +0200
  3960. Subject: [PATCH] platform/surface: aggregator_registry: Rename HID device
  3961. nodes based on their function
  3962. Rename HID device nodes based on their function. In particular, these
  3963. are nodes for firmware updates via the CFU mechanism (component firmware
  3964. update), HID based sensors, and a USB-C USCI client.
  3965. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  3966. Patchset: surface-sam
  3967. ---
  3968. .../surface/surface_aggregator_registry.c | 18 +++++++++---------
  3969. 1 file changed, 9 insertions(+), 9 deletions(-)
  3970. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  3971. index d5655f6a4a41..b325fa0c5ee0 100644
  3972. --- a/drivers/platform/surface/surface_aggregator_registry.c
  3973. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  3974. @@ -104,14 +104,14 @@ static const struct software_node ssam_node_hid_tid1_touchpad = {
  3975. .parent = &ssam_node_root,
  3976. };
  3977. -/* HID device instance 6 (TID1, unknown HID device). */
  3978. -static const struct software_node ssam_node_hid_tid1_iid6 = {
  3979. +/* HID device instance 6 (TID1, HID sensor collection). */
  3980. +static const struct software_node ssam_node_hid_tid1_sensors = {
  3981. .name = "ssam:01:15:01:06:00",
  3982. .parent = &ssam_node_root,
  3983. };
  3984. -/* HID device instance 7 (TID1, unknown HID device). */
  3985. -static const struct software_node ssam_node_hid_tid1_iid7 = {
  3986. +/* HID device instance 7 (TID1, UCM USCI HID client). */
  3987. +static const struct software_node ssam_node_hid_tid1_ucm_usci = {
  3988. .name = "ssam:01:15:01:07:00",
  3989. .parent = &ssam_node_root,
  3990. };
  3991. @@ -182,8 +182,8 @@ static const struct software_node ssam_node_hid_kip_touchpad = {
  3992. .parent = &ssam_node_hub_kip,
  3993. };
  3994. -/* HID device instance 5 (KIP hub, unknown HID device). */
  3995. -static const struct software_node ssam_node_hid_kip_iid5 = {
  3996. +/* HID device instance 5 (KIP hub, type-cover firmware update). */
  3997. +static const struct software_node ssam_node_hid_kip_fwupd = {
  3998. .name = "ssam:01:15:02:05:00",
  3999. .parent = &ssam_node_hub_kip,
  4000. };
  4001. @@ -244,8 +244,8 @@ static const struct software_node *ssam_node_group_sls[] = {
  4002. &ssam_node_hid_tid1_keyboard,
  4003. &ssam_node_hid_tid1_penstash,
  4004. &ssam_node_hid_tid1_touchpad,
  4005. - &ssam_node_hid_tid1_iid6,
  4006. - &ssam_node_hid_tid1_iid7,
  4007. + &ssam_node_hid_tid1_sensors,
  4008. + &ssam_node_hid_tid1_ucm_usci,
  4009. &ssam_node_hid_tid1_sysctrl,
  4010. NULL,
  4011. };
  4012. @@ -278,7 +278,7 @@ static const struct software_node *ssam_node_group_sp8[] = {
  4013. &ssam_node_hid_kip_keyboard,
  4014. &ssam_node_hid_kip_penstash,
  4015. &ssam_node_hid_kip_touchpad,
  4016. - &ssam_node_hid_kip_iid5,
  4017. + &ssam_node_hid_kip_fwupd,
  4018. NULL,
  4019. };
  4020. --
  4021. 2.37.2
  4022. From 20db0502d55279d6b4cca93ebd7ff1b2920f320c Mon Sep 17 00:00:00 2001
  4023. From: Maximilian Luz <luzmaximilian@gmail.com>
  4024. Date: Sat, 25 Jun 2022 20:52:47 +0200
  4025. Subject: [PATCH] platform/surface: aggregator_registry: Rename HID device
  4026. nodes based on new findings
  4027. On Windows, the HID devices with target ID 1 are grouped as "Surface Hot
  4028. Plug - SAM". Rename their device nodes in the registry to reflect that
  4029. and update the comments accordingly.
  4030. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  4031. Patchset: surface-sam
  4032. ---
  4033. .../surface/surface_aggregator_registry.c | 36 +++++++++----------
  4034. 1 file changed, 18 insertions(+), 18 deletions(-)
  4035. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  4036. index b325fa0c5ee0..3aa825b5aa26 100644
  4037. --- a/drivers/platform/surface/surface_aggregator_registry.c
  4038. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  4039. @@ -86,38 +86,38 @@ static const struct software_node ssam_node_bas_dtx = {
  4040. .parent = &ssam_node_root,
  4041. };
  4042. -/* HID keyboard (TID1). */
  4043. -static const struct software_node ssam_node_hid_tid1_keyboard = {
  4044. +/* HID keyboard (SAM, TID=1). */
  4045. +static const struct software_node ssam_node_hid_sam_keyboard = {
  4046. .name = "ssam:01:15:01:01:00",
  4047. .parent = &ssam_node_root,
  4048. };
  4049. -/* HID pen stash (TID1; pen taken / stashed away evens). */
  4050. -static const struct software_node ssam_node_hid_tid1_penstash = {
  4051. +/* HID pen stash (SAM, TID=1; pen taken / stashed away evens). */
  4052. +static const struct software_node ssam_node_hid_sam_penstash = {
  4053. .name = "ssam:01:15:01:02:00",
  4054. .parent = &ssam_node_root,
  4055. };
  4056. -/* HID touchpad (TID1). */
  4057. -static const struct software_node ssam_node_hid_tid1_touchpad = {
  4058. +/* HID touchpad (SAM, TID=1). */
  4059. +static const struct software_node ssam_node_hid_sam_touchpad = {
  4060. .name = "ssam:01:15:01:03:00",
  4061. .parent = &ssam_node_root,
  4062. };
  4063. -/* HID device instance 6 (TID1, HID sensor collection). */
  4064. -static const struct software_node ssam_node_hid_tid1_sensors = {
  4065. +/* HID device instance 6 (SAM, TID=1, HID sensor collection). */
  4066. +static const struct software_node ssam_node_hid_sam_sensors = {
  4067. .name = "ssam:01:15:01:06:00",
  4068. .parent = &ssam_node_root,
  4069. };
  4070. -/* HID device instance 7 (TID1, UCM USCI HID client). */
  4071. -static const struct software_node ssam_node_hid_tid1_ucm_usci = {
  4072. +/* HID device instance 7 (SAM, TID=1, UCM USCI HID client). */
  4073. +static const struct software_node ssam_node_hid_sam_ucm_usci = {
  4074. .name = "ssam:01:15:01:07:00",
  4075. .parent = &ssam_node_root,
  4076. };
  4077. -/* HID system controls (TID1). */
  4078. -static const struct software_node ssam_node_hid_tid1_sysctrl = {
  4079. +/* HID system controls (SAM, TID=1). */
  4080. +static const struct software_node ssam_node_hid_sam_sysctrl = {
  4081. .name = "ssam:01:15:01:08:00",
  4082. .parent = &ssam_node_root,
  4083. };
  4084. @@ -241,12 +241,12 @@ static const struct software_node *ssam_node_group_sls[] = {
  4085. &ssam_node_bat_main,
  4086. &ssam_node_tmp_pprof,
  4087. &ssam_node_pos_tablet_switch,
  4088. - &ssam_node_hid_tid1_keyboard,
  4089. - &ssam_node_hid_tid1_penstash,
  4090. - &ssam_node_hid_tid1_touchpad,
  4091. - &ssam_node_hid_tid1_sensors,
  4092. - &ssam_node_hid_tid1_ucm_usci,
  4093. - &ssam_node_hid_tid1_sysctrl,
  4094. + &ssam_node_hid_sam_keyboard,
  4095. + &ssam_node_hid_sam_penstash,
  4096. + &ssam_node_hid_sam_touchpad,
  4097. + &ssam_node_hid_sam_sensors,
  4098. + &ssam_node_hid_sam_ucm_usci,
  4099. + &ssam_node_hid_sam_sysctrl,
  4100. NULL,
  4101. };
  4102. --
  4103. 2.37.2
  4104. From 4680063aaad14e3083227e1e66d16f2c8c46da33 Mon Sep 17 00:00:00 2001
  4105. From: Maximilian Luz <luzmaximilian@gmail.com>
  4106. Date: Sat, 25 Jun 2022 20:54:59 +0200
  4107. Subject: [PATCH] platform/surface: aggregator_registry: Add HID devices for
  4108. sensors and USCI client to SP8
  4109. Add software nodes for the HID sensor collection and the UCM USCI HID
  4110. client to the Surface Pro 8. In contrast to the type-cover devices,
  4111. these devices are directly attached to the SAM controller, without any
  4112. hub.
  4113. This enables support for HID-based sensors, including the ones used for
  4114. automatic screen rotation, on the Surface Pro 8.
  4115. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  4116. Patchset: surface-sam
  4117. ---
  4118. drivers/platform/surface/surface_aggregator_registry.c | 2 ++
  4119. 1 file changed, 2 insertions(+)
  4120. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  4121. index 3aa825b5aa26..4c2f9f789354 100644
  4122. --- a/drivers/platform/surface/surface_aggregator_registry.c
  4123. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  4124. @@ -279,6 +279,8 @@ static const struct software_node *ssam_node_group_sp8[] = {
  4125. &ssam_node_hid_kip_penstash,
  4126. &ssam_node_hid_kip_touchpad,
  4127. &ssam_node_hid_kip_fwupd,
  4128. + &ssam_node_hid_sam_sensors,
  4129. + &ssam_node_hid_sam_ucm_usci,
  4130. NULL,
  4131. };
  4132. --
  4133. 2.37.2
  4134. From 72f14fa3dd5b2a5dd209a696ee3fb7562720a5d0 Mon Sep 17 00:00:00 2001
  4135. From: Maximilian Luz <luzmaximilian@gmail.com>
  4136. Date: Fri, 8 Jul 2022 03:34:44 +0200
  4137. Subject: [PATCH] platform/surface: aggregator_registry: Add support for
  4138. Surface Laptop Go 2
  4139. The Surface Laptop Go 2 seems to have the same SAM client devices as the
  4140. Surface Laptop Go 1, so re-use its node group.
  4141. Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
  4142. Patchset: surface-sam
  4143. ---
  4144. drivers/platform/surface/surface_aggregator_registry.c | 3 +++
  4145. 1 file changed, 3 insertions(+)
  4146. diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
  4147. index 4c2f9f789354..49426b6e6b19 100644
  4148. --- a/drivers/platform/surface/surface_aggregator_registry.c
  4149. +++ b/drivers/platform/surface/surface_aggregator_registry.c
  4150. @@ -327,6 +327,9 @@ static const struct acpi_device_id ssam_platform_hub_match[] = {
  4151. /* Surface Laptop Go 1 */
  4152. { "MSHW0118", (unsigned long)ssam_node_group_slg1 },
  4153. + /* Surface Laptop Go 2 */
  4154. + { "MSHW0290", (unsigned long)ssam_node_group_slg1 },
  4155. +
  4156. /* Surface Laptop Studio */
  4157. { "MSHW0123", (unsigned long)ssam_node_group_sls },
  4158. --
  4159. 2.37.2