cam_cpas_hw.c 80 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/device.h>
  6. #include <linux/platform_device.h>
  7. #include <linux/of.h>
  8. #include <linux/pm_opp.h>
  9. #include <linux/slab.h>
  10. #include <linux/module.h>
  11. #include "cam_cpas_hw.h"
  12. #include "cam_cpas_hw_intf.h"
  13. #include "cam_cpas_soc.h"
  14. #include "cam_req_mgr_dev.h"
  15. #include "cam_smmu_api.h"
  16. #include "cam_compat.h"
  17. #include "cam_cpastop_hw.h"
  18. #define CAM_CPAS_LOG_BUF_LEN 512
  19. static uint cam_min_camnoc_ib_bw;
  20. module_param(cam_min_camnoc_ib_bw, uint, 0644);
  21. static void cam_cpas_update_monitor_array(struct cam_hw_info *cpas_hw,
  22. const char *identifier_string, int32_t identifier_value);
  23. static void cam_cpas_dump_monitor_array(
  24. struct cam_cpas *cpas_core);
  25. static void cam_cpas_process_bw_overrides(
  26. struct cam_cpas_bus_client *bus_client, uint64_t *ab, uint64_t *ib,
  27. const struct cam_cpas_debug_settings *cpas_settings)
  28. {
  29. uint64_t curr_ab = *ab;
  30. uint64_t curr_ib = *ib;
  31. size_t name_len = strlen(bus_client->common_data.name);
  32. if (!cpas_settings) {
  33. CAM_ERR(CAM_CPAS, "Invalid cpas debug settings");
  34. return;
  35. }
  36. if (strnstr(bus_client->common_data.name, "cam_hf_0", name_len)) {
  37. if (cpas_settings->mnoc_hf_0_ab_bw)
  38. *ab = cpas_settings->mnoc_hf_0_ab_bw;
  39. if (cpas_settings->mnoc_hf_0_ib_bw)
  40. *ib = cpas_settings->mnoc_hf_0_ib_bw;
  41. } else if (strnstr(bus_client->common_data.name, "cam_hf_1",
  42. name_len)) {
  43. if (cpas_settings->mnoc_hf_1_ab_bw)
  44. *ab = cpas_settings->mnoc_hf_1_ab_bw;
  45. if (cpas_settings->mnoc_hf_0_ib_bw)
  46. *ib = cpas_settings->mnoc_hf_1_ib_bw;
  47. } else if (strnstr(bus_client->common_data.name, "cam_sf_0",
  48. name_len)) {
  49. if (cpas_settings->mnoc_sf_0_ab_bw)
  50. *ab = cpas_settings->mnoc_sf_0_ab_bw;
  51. if (cpas_settings->mnoc_sf_0_ib_bw)
  52. *ib = cpas_settings->mnoc_sf_0_ib_bw;
  53. } else if (strnstr(bus_client->common_data.name, "cam_sf_1",
  54. name_len)) {
  55. if (cpas_settings->mnoc_sf_1_ab_bw)
  56. *ab = cpas_settings->mnoc_sf_1_ab_bw;
  57. if (cpas_settings->mnoc_sf_1_ib_bw)
  58. *ib = cpas_settings->mnoc_sf_1_ib_bw;
  59. } else if (strnstr(bus_client->common_data.name, "cam_sf_icp",
  60. name_len)) {
  61. if (cpas_settings->mnoc_sf_icp_ab_bw)
  62. *ab = cpas_settings->mnoc_sf_icp_ab_bw;
  63. if (cpas_settings->mnoc_sf_icp_ib_bw)
  64. *ib = cpas_settings->mnoc_sf_icp_ib_bw;
  65. } else {
  66. CAM_ERR(CAM_CPAS, "unknown mnoc port: %s, bw override failed",
  67. bus_client->common_data.name);
  68. return;
  69. }
  70. CAM_INFO(CAM_CPAS,
  71. "Overriding mnoc bw for: %s with ab: %llu, ib: %llu, curr_ab: %llu, curr_ib: %llu",
  72. bus_client->common_data.name, *ab, *ib, curr_ab, curr_ib);
  73. }
  74. int cam_cpas_util_reg_read(struct cam_hw_info *cpas_hw,
  75. enum cam_cpas_reg_base reg_base, struct cam_cpas_reg *reg_info)
  76. {
  77. struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
  78. struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info;
  79. uint32_t value;
  80. int reg_base_index;
  81. if (!reg_info->enable)
  82. return 0;
  83. reg_base_index = cpas_core->regbase_index[reg_base];
  84. if (reg_base_index == -1)
  85. return -EINVAL;
  86. value = cam_io_r_mb(
  87. soc_info->reg_map[reg_base_index].mem_base + reg_info->offset);
  88. CAM_INFO(CAM_CPAS, "Base[%d] Offset[0x%08x] Value[0x%08x]",
  89. reg_base, reg_info->offset, value);
  90. return 0;
  91. }
  92. int cam_cpas_util_reg_update(struct cam_hw_info *cpas_hw,
  93. enum cam_cpas_reg_base reg_base, struct cam_cpas_reg *reg_info)
  94. {
  95. struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
  96. struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info;
  97. uint32_t value;
  98. int reg_base_index;
  99. if (reg_info->enable == false)
  100. return 0;
  101. reg_base_index = cpas_core->regbase_index[reg_base];
  102. if (reg_base_index == -1)
  103. return -EINVAL;
  104. if (reg_info->masked_value) {
  105. value = cam_io_r_mb(
  106. soc_info->reg_map[reg_base_index].mem_base +
  107. reg_info->offset);
  108. value = value & (~reg_info->mask);
  109. value = value | (reg_info->value << reg_info->shift);
  110. } else {
  111. value = reg_info->value;
  112. }
  113. CAM_DBG(CAM_CPAS, "Base[%d] Offset[0x%08x] Value[0x%08x]",
  114. reg_base, reg_info->offset, value);
  115. cam_io_w_mb(value, soc_info->reg_map[reg_base_index].mem_base +
  116. reg_info->offset);
  117. return 0;
  118. }
  119. static int cam_cpas_util_vote_bus_client_level(
  120. struct cam_cpas_bus_client *bus_client, unsigned int level)
  121. {
  122. int rc = 0;
  123. if (!bus_client->valid) {
  124. CAM_ERR(CAM_CPAS, "bus client not valid");
  125. rc = -EINVAL;
  126. goto end;
  127. }
  128. if (level >= CAM_MAX_VOTE) {
  129. CAM_ERR(CAM_CPAS,
  130. "Invalid votelevel=%d,usecases=%d,Bus client=[%s]",
  131. level, bus_client->common_data.num_usecases,
  132. bus_client->common_data.name);
  133. return -EINVAL;
  134. }
  135. if (level == bus_client->curr_vote_level)
  136. goto end;
  137. rc = cam_soc_bus_client_update_request(bus_client->soc_bus_client,
  138. level);
  139. if (rc) {
  140. CAM_ERR(CAM_CPAS, "Client: %s update request failed rc: %d",
  141. bus_client->common_data.name, rc);
  142. goto end;
  143. }
  144. bus_client->curr_vote_level = level;
  145. end:
  146. return rc;
  147. }
  148. static int cam_cpas_util_vote_bus_client_bw(
  149. struct cam_cpas_bus_client *bus_client, uint64_t ab, uint64_t ib,
  150. bool camnoc_bw, uint64_t *applied_ab, uint64_t *applied_ib)
  151. {
  152. int rc = 0;
  153. uint64_t min_camnoc_ib_bw = CAM_CPAS_AXI_MIN_CAMNOC_IB_BW;
  154. const struct camera_debug_settings *cam_debug = NULL;
  155. if (!bus_client->valid) {
  156. CAM_ERR(CAM_CPAS, "bus client: %s not valid",
  157. bus_client->common_data.name);
  158. rc = -EINVAL;
  159. goto end;
  160. }
  161. if (cam_min_camnoc_ib_bw > 0)
  162. min_camnoc_ib_bw = (uint64_t)cam_min_camnoc_ib_bw * 1000000L;
  163. CAM_DBG(CAM_CPAS,
  164. "Bus_client: %s, cam_min_camnoc_ib_bw = %d, min_camnoc_ib_bw=%llu",
  165. bus_client->common_data.name, cam_min_camnoc_ib_bw,
  166. min_camnoc_ib_bw);
  167. mutex_lock(&bus_client->lock);
  168. if (camnoc_bw) {
  169. if ((ab > 0) && (ab < CAM_CPAS_AXI_MIN_CAMNOC_AB_BW))
  170. ab = CAM_CPAS_AXI_MIN_CAMNOC_AB_BW;
  171. if ((ib > 0) && (ib < min_camnoc_ib_bw))
  172. ib = min_camnoc_ib_bw;
  173. } else {
  174. if ((ab > 0) && (ab < CAM_CPAS_AXI_MIN_MNOC_AB_BW))
  175. ab = CAM_CPAS_AXI_MIN_MNOC_AB_BW;
  176. if ((ib > 0) && (ib < CAM_CPAS_AXI_MIN_MNOC_IB_BW))
  177. ib = CAM_CPAS_AXI_MIN_MNOC_IB_BW;
  178. }
  179. cam_debug = cam_debug_get_settings();
  180. if (cam_debug && (cam_debug->cpas_settings.mnoc_hf_0_ab_bw ||
  181. cam_debug->cpas_settings.mnoc_hf_0_ib_bw ||
  182. cam_debug->cpas_settings.mnoc_hf_1_ab_bw ||
  183. cam_debug->cpas_settings.mnoc_hf_1_ib_bw ||
  184. cam_debug->cpas_settings.mnoc_sf_0_ab_bw ||
  185. cam_debug->cpas_settings.mnoc_sf_0_ib_bw ||
  186. cam_debug->cpas_settings.mnoc_sf_1_ab_bw ||
  187. cam_debug->cpas_settings.mnoc_sf_1_ib_bw ||
  188. cam_debug->cpas_settings.mnoc_sf_icp_ab_bw ||
  189. cam_debug->cpas_settings.mnoc_sf_icp_ib_bw))
  190. cam_cpas_process_bw_overrides(bus_client, &ab, &ib,
  191. &cam_debug->cpas_settings);
  192. rc = cam_soc_bus_client_update_bw(bus_client->soc_bus_client, ab, ib);
  193. if (rc) {
  194. CAM_ERR(CAM_CPAS,
  195. "Update bw failed, ab[%llu] ib[%llu]",
  196. ab, ib);
  197. goto unlock_client;
  198. }
  199. if (applied_ab)
  200. *applied_ab = ab;
  201. if (applied_ib)
  202. *applied_ib = ib;
  203. unlock_client:
  204. mutex_unlock(&bus_client->lock);
  205. end:
  206. return rc;
  207. }
  208. static int cam_cpas_util_register_bus_client(
  209. struct cam_hw_soc_info *soc_info, struct device_node *dev_node,
  210. struct cam_cpas_bus_client *bus_client)
  211. {
  212. int rc = 0;
  213. rc = cam_soc_bus_client_register(soc_info->pdev, dev_node,
  214. &bus_client->soc_bus_client, &bus_client->common_data);
  215. if (rc) {
  216. CAM_ERR(CAM_CPAS, "Bus client: %s registertion failed ,rc: %d",
  217. bus_client->common_data.name, rc);
  218. return rc;
  219. }
  220. bus_client->curr_vote_level = 0;
  221. bus_client->valid = true;
  222. mutex_init(&bus_client->lock);
  223. return 0;
  224. }
  225. static int cam_cpas_util_unregister_bus_client(
  226. struct cam_cpas_bus_client *bus_client)
  227. {
  228. if (!bus_client->valid) {
  229. CAM_ERR(CAM_CPAS, "bus client not valid");
  230. return -EINVAL;
  231. }
  232. cam_soc_bus_client_unregister(&bus_client->soc_bus_client);
  233. bus_client->curr_vote_level = 0;
  234. bus_client->valid = false;
  235. mutex_destroy(&bus_client->lock);
  236. return 0;
  237. }
  238. static int cam_cpas_util_axi_cleanup(struct cam_cpas *cpas_core,
  239. struct cam_hw_soc_info *soc_info)
  240. {
  241. int i = 0;
  242. if (cpas_core->num_axi_ports > CAM_CPAS_MAX_AXI_PORTS) {
  243. CAM_ERR(CAM_CPAS, "Invalid num_axi_ports: %d",
  244. cpas_core->num_axi_ports);
  245. return -EINVAL;
  246. }
  247. if (cpas_core->num_camnoc_axi_ports > CAM_CPAS_MAX_AXI_PORTS) {
  248. CAM_ERR(CAM_CPAS, "Invalid num_camnoc_axi_ports: %d",
  249. cpas_core->num_camnoc_axi_ports);
  250. return -EINVAL;
  251. }
  252. for (i = 0; i < cpas_core->num_axi_ports; i++) {
  253. cam_cpas_util_unregister_bus_client(
  254. &cpas_core->axi_port[i].bus_client);
  255. of_node_put(cpas_core->axi_port[i].axi_port_node);
  256. cpas_core->axi_port[i].axi_port_node = NULL;
  257. }
  258. for (i = 0; i < cpas_core->num_camnoc_axi_ports; i++) {
  259. cam_cpas_util_unregister_bus_client(
  260. &cpas_core->camnoc_axi_port[i].bus_client);
  261. of_node_put(cpas_core->camnoc_axi_port[i].axi_port_node);
  262. cpas_core->camnoc_axi_port[i].axi_port_node = NULL;
  263. }
  264. return 0;
  265. }
  266. static int cam_cpas_util_axi_setup(struct cam_cpas *cpas_core,
  267. struct cam_hw_soc_info *soc_info)
  268. {
  269. int i = 0, rc = 0;
  270. struct device_node *axi_port_mnoc_node = NULL;
  271. struct device_node *axi_port_camnoc_node = NULL;
  272. if (cpas_core->num_axi_ports > CAM_CPAS_MAX_AXI_PORTS) {
  273. CAM_ERR(CAM_CPAS, "Invalid num_axi_ports: %d",
  274. cpas_core->num_axi_ports);
  275. return -EINVAL;
  276. }
  277. for (i = 0; i < cpas_core->num_axi_ports; i++) {
  278. axi_port_mnoc_node = cpas_core->axi_port[i].axi_port_node;
  279. rc = cam_cpas_util_register_bus_client(soc_info,
  280. axi_port_mnoc_node, &cpas_core->axi_port[i].bus_client);
  281. if (rc)
  282. goto bus_register_fail;
  283. }
  284. for (i = 0; i < cpas_core->num_camnoc_axi_ports; i++) {
  285. axi_port_camnoc_node =
  286. cpas_core->camnoc_axi_port[i].axi_port_node;
  287. rc = cam_cpas_util_register_bus_client(soc_info,
  288. axi_port_camnoc_node,
  289. &cpas_core->camnoc_axi_port[i].bus_client);
  290. if (rc)
  291. goto bus_register_fail;
  292. }
  293. return 0;
  294. bus_register_fail:
  295. of_node_put(cpas_core->axi_port[i].axi_port_node);
  296. return rc;
  297. }
  298. static int cam_cpas_util_vote_default_ahb_axi(struct cam_hw_info *cpas_hw,
  299. int enable)
  300. {
  301. int rc, i = 0;
  302. struct cam_cpas *cpas_core = (struct cam_cpas *)cpas_hw->core_info;
  303. uint64_t ab_bw, ib_bw;
  304. uint64_t applied_ab_bw = 0, applied_ib_bw = 0;
  305. rc = cam_cpas_util_vote_bus_client_level(&cpas_core->ahb_bus_client,
  306. (enable == true) ? CAM_SVS_VOTE : CAM_SUSPEND_VOTE);
  307. if (rc) {
  308. CAM_ERR(CAM_CPAS, "Failed in AHB vote, enable=%d, rc=%d",
  309. enable, rc);
  310. return rc;
  311. }
  312. if (enable) {
  313. ab_bw = CAM_CPAS_DEFAULT_AXI_BW;
  314. ib_bw = CAM_CPAS_DEFAULT_AXI_BW;
  315. } else {
  316. ab_bw = 0;
  317. ib_bw = 0;
  318. }
  319. for (i = 0; i < cpas_core->num_axi_ports; i++) {
  320. rc = cam_cpas_util_vote_bus_client_bw(
  321. &cpas_core->axi_port[i].bus_client,
  322. ab_bw, ib_bw, false, &applied_ab_bw, &applied_ib_bw);
  323. if (rc) {
  324. CAM_ERR(CAM_CPAS,
  325. "Failed in mnoc vote, enable=%d, rc=%d",
  326. enable, rc);
  327. goto remove_ahb_vote;
  328. }
  329. cpas_core->axi_port[i].applied_ab_bw = applied_ab_bw;
  330. cpas_core->axi_port[i].applied_ib_bw = applied_ib_bw;
  331. }
  332. return 0;
  333. remove_ahb_vote:
  334. cam_cpas_util_vote_bus_client_level(&cpas_core->ahb_bus_client,
  335. CAM_SUSPEND_VOTE);
  336. return rc;
  337. }
  338. static int cam_cpas_hw_reg_write(struct cam_hw_info *cpas_hw,
  339. uint32_t client_handle, enum cam_cpas_reg_base reg_base,
  340. uint32_t offset, bool mb, uint32_t value)
  341. {
  342. struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info;
  343. struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
  344. struct cam_cpas_client *cpas_client = NULL;
  345. int reg_base_index = cpas_core->regbase_index[reg_base];
  346. uint32_t client_indx = CAM_CPAS_GET_CLIENT_IDX(client_handle);
  347. int rc = 0;
  348. if (reg_base_index < 0 || reg_base_index >= soc_info->num_reg_map) {
  349. CAM_ERR(CAM_CPAS,
  350. "Invalid reg_base=%d, reg_base_index=%d, num_map=%d",
  351. reg_base, reg_base_index, soc_info->num_reg_map);
  352. return -EINVAL;
  353. }
  354. if (!CAM_CPAS_CLIENT_VALID(client_indx))
  355. return -EINVAL;
  356. mutex_lock(&cpas_core->client_mutex[client_indx]);
  357. cpas_client = cpas_core->cpas_client[client_indx];
  358. if (!CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) {
  359. CAM_ERR(CAM_CPAS, "client=[%d][%s][%d] has not started",
  360. client_indx, cpas_client->data.identifier,
  361. cpas_client->data.cell_index);
  362. rc = -EPERM;
  363. goto unlock_client;
  364. }
  365. if (mb)
  366. cam_io_w_mb(value,
  367. soc_info->reg_map[reg_base_index].mem_base + offset);
  368. else
  369. cam_io_w(value,
  370. soc_info->reg_map[reg_base_index].mem_base + offset);
  371. unlock_client:
  372. mutex_unlock(&cpas_core->client_mutex[client_indx]);
  373. return rc;
  374. }
  375. static int cam_cpas_hw_reg_read(struct cam_hw_info *cpas_hw,
  376. uint32_t client_handle, enum cam_cpas_reg_base reg_base,
  377. uint32_t offset, bool mb, uint32_t *value)
  378. {
  379. struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info;
  380. struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
  381. struct cam_cpas_client *cpas_client = NULL;
  382. int reg_base_index = cpas_core->regbase_index[reg_base];
  383. uint32_t reg_value;
  384. uint32_t client_indx = CAM_CPAS_GET_CLIENT_IDX(client_handle);
  385. int rc = 0;
  386. if (!value)
  387. return -EINVAL;
  388. if (reg_base_index < 0 || reg_base_index >= soc_info->num_reg_map) {
  389. CAM_ERR(CAM_CPAS,
  390. "Invalid reg_base=%d, reg_base_index=%d, num_map=%d",
  391. reg_base, reg_base_index, soc_info->num_reg_map);
  392. return -EINVAL;
  393. }
  394. if (!CAM_CPAS_CLIENT_VALID(client_indx))
  395. return -EINVAL;
  396. cpas_client = cpas_core->cpas_client[client_indx];
  397. if (!CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) {
  398. CAM_ERR(CAM_CPAS, "client=[%d][%s][%d] has not started",
  399. client_indx, cpas_client->data.identifier,
  400. cpas_client->data.cell_index);
  401. return -EPERM;
  402. }
  403. if (mb)
  404. reg_value = cam_io_r_mb(
  405. soc_info->reg_map[reg_base_index].mem_base + offset);
  406. else
  407. reg_value = cam_io_r(
  408. soc_info->reg_map[reg_base_index].mem_base + offset);
  409. *value = reg_value;
  410. return rc;
  411. }
  412. static int cam_cpas_hw_dump_camnoc_buff_fill_info(
  413. struct cam_hw_info *cpas_hw,
  414. uint32_t client_handle)
  415. {
  416. int rc = 0, i;
  417. uint32_t val = 0;
  418. struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
  419. struct cam_camnoc_info *camnoc_info =
  420. (struct cam_camnoc_info *) cpas_core->camnoc_info;
  421. char log_buf[CAM_CPAS_LOG_BUF_LEN] = {0};
  422. size_t len = 0;
  423. if (!camnoc_info) {
  424. CAM_ERR(CAM_CPAS, "Invalid camnoc info for hw_version: 0x%x",
  425. cpas_hw->soc_info.hw_version);
  426. return -EINVAL;
  427. }
  428. for (i = 0; i < camnoc_info->specific_size; i++) {
  429. if ((!camnoc_info->specific[i].enable) ||
  430. (!camnoc_info->specific[i].maxwr_low.enable))
  431. continue;
  432. rc = cam_cpas_hw_reg_read(cpas_hw, client_handle,
  433. CAM_CPAS_REG_CAMNOC,
  434. camnoc_info->specific[i].maxwr_low.offset, true, &val);
  435. if (rc)
  436. break;
  437. len += scnprintf((log_buf + len), (CAM_CPAS_LOG_BUF_LEN - len),
  438. " %s:[%d %d]", camnoc_info->specific[i].port_name,
  439. (val & 0x7FF), (val & 0x7F0000) >> 16);
  440. }
  441. CAM_INFO(CAM_CPAS, "CAMNOC Fill level [Queued Pending] %s", log_buf);
  442. return rc;
  443. }
  444. static int cam_cpas_util_set_camnoc_axi_clk_rate(
  445. struct cam_hw_info *cpas_hw)
  446. {
  447. struct cam_cpas_private_soc *soc_private =
  448. (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private;
  449. struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
  450. struct cam_cpas_tree_node *tree_node = NULL;
  451. int rc = 0, i = 0;
  452. const struct camera_debug_settings *cam_debug = NULL;
  453. CAM_DBG(CAM_CPAS, "control_camnoc_axi_clk=%d",
  454. soc_private->control_camnoc_axi_clk);
  455. if (soc_private->control_camnoc_axi_clk) {
  456. struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info;
  457. uint64_t required_camnoc_bw = 0, intermediate_result = 0;
  458. int64_t clk_rate = 0;
  459. for (i = 0; i < CAM_CPAS_MAX_TREE_NODES; i++) {
  460. tree_node = soc_private->tree_node[i];
  461. if (!tree_node ||
  462. !tree_node->camnoc_max_needed)
  463. continue;
  464. if (required_camnoc_bw < (tree_node->camnoc_bw *
  465. tree_node->bus_width_factor)) {
  466. required_camnoc_bw = tree_node->camnoc_bw *
  467. tree_node->bus_width_factor;
  468. }
  469. }
  470. intermediate_result = required_camnoc_bw *
  471. soc_private->camnoc_axi_clk_bw_margin;
  472. do_div(intermediate_result, 100);
  473. required_camnoc_bw += intermediate_result;
  474. if (cpas_core->streamon_clients && (required_camnoc_bw == 0)) {
  475. CAM_DBG(CAM_CPAS,
  476. "Set min vote if streamon_clients is non-zero : streamon_clients=%d",
  477. cpas_core->streamon_clients);
  478. required_camnoc_bw = CAM_CPAS_DEFAULT_AXI_BW;
  479. }
  480. if ((required_camnoc_bw > 0) &&
  481. (required_camnoc_bw <
  482. soc_private->camnoc_axi_min_ib_bw))
  483. required_camnoc_bw = soc_private->camnoc_axi_min_ib_bw;
  484. cam_debug = cam_debug_get_settings();
  485. if (cam_debug && cam_debug->cpas_settings.camnoc_bw) {
  486. if (cam_debug->cpas_settings.camnoc_bw <
  487. soc_private->camnoc_bus_width)
  488. required_camnoc_bw =
  489. soc_private->camnoc_bus_width;
  490. else
  491. required_camnoc_bw =
  492. cam_debug->cpas_settings.camnoc_bw;
  493. CAM_INFO(CAM_CPAS, "Overriding camnoc bw: %llu",
  494. required_camnoc_bw);
  495. }
  496. intermediate_result = required_camnoc_bw;
  497. do_div(intermediate_result, soc_private->camnoc_bus_width);
  498. clk_rate = intermediate_result;
  499. CAM_DBG(CAM_CPAS,
  500. "Setting camnoc axi clk rate[BW Clk] : [%llu %lld]",
  501. required_camnoc_bw, clk_rate);
  502. /*
  503. * CPAS hw is not powered on for the first client.
  504. * Also, clk_rate will be overwritten with default
  505. * value while power on. So, skipping this for first
  506. * client.
  507. */
  508. if (cpas_core->streamon_clients) {
  509. rc = cam_soc_util_set_src_clk_rate(soc_info, clk_rate);
  510. if (rc)
  511. CAM_ERR(CAM_CPAS,
  512. "Failed in setting camnoc axi clk %llu %lld %d",
  513. required_camnoc_bw, clk_rate, rc);
  514. cpas_core->applied_camnoc_axi_rate = clk_rate;
  515. }
  516. }
  517. return rc;
  518. }
  519. static int cam_cpas_util_translate_client_paths(
  520. struct cam_axi_vote *axi_vote)
  521. {
  522. int i;
  523. uint32_t *path_data_type = NULL;
  524. if (!axi_vote)
  525. return -EINVAL;
  526. for (i = 0; i < axi_vote->num_paths; i++) {
  527. path_data_type = &axi_vote->axi_path[i].path_data_type;
  528. /* Update path_data_type from UAPI value to internal value */
  529. if (*path_data_type >= CAM_CPAS_PATH_DATA_CONSO_OFFSET)
  530. *path_data_type = CAM_CPAS_MAX_GRAN_PATHS_PER_CLIENT +
  531. (*path_data_type %
  532. CAM_CPAS_MAX_GRAN_PATHS_PER_CLIENT);
  533. else
  534. *path_data_type %= CAM_CPAS_MAX_GRAN_PATHS_PER_CLIENT;
  535. if (*path_data_type >= CAM_CPAS_PATH_DATA_MAX) {
  536. CAM_ERR(CAM_CPAS, "index Invalid: %d", path_data_type);
  537. return -EINVAL;
  538. }
  539. }
  540. return 0;
  541. }
  542. static int cam_cpas_axi_consolidate_path_votes(
  543. struct cam_cpas_client *cpas_client,
  544. struct cam_axi_vote *axi_vote)
  545. {
  546. int rc = 0, i, k, l;
  547. struct cam_axi_vote *con_axi_vote = &cpas_client->axi_vote;
  548. bool path_found = false, cons_entry_found;
  549. struct cam_cpas_tree_node *curr_tree_node = NULL;
  550. struct cam_cpas_tree_node *sum_tree_node = NULL;
  551. uint32_t transac_type;
  552. uint32_t path_data_type;
  553. struct cam_axi_per_path_bw_vote *axi_path;
  554. con_axi_vote->num_paths = 0;
  555. for (i = 0; i < axi_vote->num_paths; i++) {
  556. path_found = false;
  557. path_data_type = axi_vote->axi_path[i].path_data_type;
  558. transac_type = axi_vote->axi_path[i].transac_type;
  559. if ((path_data_type >= CAM_CPAS_PATH_DATA_MAX) ||
  560. (transac_type >= CAM_CPAS_TRANSACTION_MAX)) {
  561. CAM_ERR(CAM_CPAS, "Invalid path or transac type: %d %d",
  562. path_data_type, transac_type);
  563. return -EINVAL;
  564. }
  565. axi_path = &con_axi_vote->axi_path[con_axi_vote->num_paths];
  566. curr_tree_node =
  567. cpas_client->tree_node[path_data_type][transac_type];
  568. if (curr_tree_node) {
  569. path_found = true;
  570. memcpy(axi_path, &axi_vote->axi_path[i],
  571. sizeof(struct cam_axi_per_path_bw_vote));
  572. con_axi_vote->num_paths++;
  573. continue;
  574. }
  575. for (k = 0; k < CAM_CPAS_PATH_DATA_MAX; k++) {
  576. sum_tree_node = cpas_client->tree_node[k][transac_type];
  577. if (!sum_tree_node)
  578. continue;
  579. if (sum_tree_node->constituent_paths[path_data_type]) {
  580. path_found = true;
  581. /*
  582. * Check if corresponding consolidated path
  583. * entry is already added into consolidated list
  584. */
  585. cons_entry_found = false;
  586. for (l = 0; l < con_axi_vote->num_paths; l++) {
  587. if ((con_axi_vote->axi_path[l]
  588. .path_data_type == k) &&
  589. (con_axi_vote->axi_path[l]
  590. .transac_type == transac_type)) {
  591. cons_entry_found = true;
  592. con_axi_vote->axi_path[l]
  593. .camnoc_bw +=
  594. axi_vote->axi_path[i]
  595. .camnoc_bw;
  596. con_axi_vote->axi_path[l]
  597. .mnoc_ab_bw +=
  598. axi_vote->axi_path[i]
  599. .mnoc_ab_bw;
  600. con_axi_vote->axi_path[l]
  601. .mnoc_ib_bw +=
  602. axi_vote->axi_path[i]
  603. .mnoc_ib_bw;
  604. break;
  605. }
  606. }
  607. /* If not found, add a new entry */
  608. if (!cons_entry_found) {
  609. axi_path->path_data_type = k;
  610. axi_path->transac_type = transac_type;
  611. axi_path->camnoc_bw =
  612. axi_vote->axi_path[i].camnoc_bw;
  613. axi_path->mnoc_ab_bw =
  614. axi_vote->axi_path[i].mnoc_ab_bw;
  615. axi_path->mnoc_ib_bw =
  616. axi_vote->axi_path[i].mnoc_ib_bw;
  617. con_axi_vote->num_paths++;
  618. }
  619. break;
  620. }
  621. }
  622. if (!path_found) {
  623. CAM_ERR(CAM_CPAS,
  624. "Client [%s][%d] Consolidated path not found for path=%d, transac=%d",
  625. cpas_client->data.identifier,
  626. cpas_client->data.cell_index,
  627. path_data_type, transac_type);
  628. return -EINVAL;
  629. }
  630. }
  631. return rc;
  632. }
  633. static int cam_cpas_update_axi_vote_bw(
  634. struct cam_hw_info *cpas_hw,
  635. struct cam_cpas_tree_node *cpas_tree_node,
  636. bool *mnoc_axi_port_updated,
  637. bool *camnoc_axi_port_updated)
  638. {
  639. struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
  640. struct cam_cpas_private_soc *soc_private =
  641. (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private;
  642. if (cpas_tree_node->axi_port_idx >= CAM_CPAS_MAX_AXI_PORTS) {
  643. CAM_ERR(CAM_CPAS, "Invalid axi_port_idx: %d",
  644. cpas_tree_node->axi_port_idx);
  645. return -EINVAL;
  646. }
  647. cpas_core->axi_port[cpas_tree_node->axi_port_idx].ab_bw =
  648. cpas_tree_node->mnoc_ab_bw;
  649. cpas_core->axi_port[cpas_tree_node->axi_port_idx].ib_bw =
  650. cpas_tree_node->mnoc_ib_bw;
  651. mnoc_axi_port_updated[cpas_tree_node->axi_port_idx] = true;
  652. if (soc_private->control_camnoc_axi_clk)
  653. return 0;
  654. cpas_core->camnoc_axi_port[cpas_tree_node->axi_port_idx].camnoc_bw =
  655. cpas_tree_node->camnoc_bw;
  656. camnoc_axi_port_updated[cpas_tree_node->camnoc_axi_port_idx] = true;
  657. return 0;
  658. }
  659. static int cam_cpas_camnoc_set_vote_axi_clk_rate(
  660. struct cam_hw_info *cpas_hw,
  661. bool *camnoc_axi_port_updated)
  662. {
  663. struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
  664. struct cam_cpas_private_soc *soc_private =
  665. (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private;
  666. int i;
  667. int rc = 0;
  668. struct cam_cpas_axi_port *camnoc_axi_port = NULL;
  669. uint64_t camnoc_bw;
  670. uint64_t applied_ab = 0, applied_ib = 0;
  671. if (soc_private->control_camnoc_axi_clk) {
  672. rc = cam_cpas_util_set_camnoc_axi_clk_rate(cpas_hw);
  673. if (rc)
  674. CAM_ERR(CAM_CPAS,
  675. "Failed in setting axi clk rate rc=%d", rc);
  676. return rc;
  677. }
  678. /* Below code is executed if we just vote and do not set the clk rate
  679. * for camnoc
  680. */
  681. if (cpas_core->num_camnoc_axi_ports > CAM_CPAS_MAX_AXI_PORTS) {
  682. CAM_ERR(CAM_CPAS, "Invalid num_camnoc_axi_ports: %d",
  683. cpas_core->num_camnoc_axi_ports);
  684. return -EINVAL;
  685. }
  686. for (i = 0; i < cpas_core->num_camnoc_axi_ports; i++) {
  687. if (camnoc_axi_port_updated[i])
  688. camnoc_axi_port = &cpas_core->camnoc_axi_port[i];
  689. else
  690. continue;
  691. CAM_DBG(CAM_PERF, "Port[%s] : camnoc_bw=%lld",
  692. camnoc_axi_port->axi_port_name,
  693. camnoc_axi_port->camnoc_bw);
  694. if (camnoc_axi_port->camnoc_bw)
  695. camnoc_bw = camnoc_axi_port->camnoc_bw;
  696. else if (camnoc_axi_port->additional_bw)
  697. camnoc_bw = camnoc_axi_port->additional_bw;
  698. else if (cpas_core->streamon_clients)
  699. camnoc_bw = CAM_CPAS_DEFAULT_AXI_BW;
  700. else
  701. camnoc_bw = 0;
  702. rc = cam_cpas_util_vote_bus_client_bw(
  703. &camnoc_axi_port->bus_client,
  704. 0, camnoc_bw, true, &applied_ab, &applied_ib);
  705. CAM_DBG(CAM_CPAS,
  706. "camnoc vote camnoc_bw[%llu] rc=%d %s",
  707. camnoc_bw, rc, camnoc_axi_port->axi_port_name);
  708. if (rc) {
  709. CAM_ERR(CAM_CPAS,
  710. "Failed in camnoc vote camnoc_bw[%llu] rc=%d",
  711. camnoc_bw, rc);
  712. break;
  713. }
  714. camnoc_axi_port->applied_ab_bw = applied_ab;
  715. camnoc_axi_port->applied_ib_bw = applied_ib;
  716. }
  717. return rc;
  718. }
  719. static int cam_cpas_util_apply_client_axi_vote(
  720. struct cam_hw_info *cpas_hw,
  721. struct cam_cpas_client *cpas_client,
  722. struct cam_axi_vote *axi_vote)
  723. {
  724. struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
  725. struct cam_axi_vote *con_axi_vote = NULL;
  726. struct cam_cpas_axi_port *mnoc_axi_port = NULL;
  727. struct cam_cpas_tree_node *curr_tree_node = NULL;
  728. struct cam_cpas_tree_node *par_tree_node = NULL;
  729. uint32_t transac_type;
  730. uint32_t path_data_type;
  731. bool mnoc_axi_port_updated[CAM_CPAS_MAX_AXI_PORTS] = {false};
  732. bool camnoc_axi_port_updated[CAM_CPAS_MAX_AXI_PORTS] = {false};
  733. uint64_t mnoc_ab_bw = 0, mnoc_ib_bw = 0,
  734. curr_camnoc_old = 0, curr_mnoc_ab_old = 0, curr_mnoc_ib_old = 0,
  735. par_camnoc_old = 0, par_mnoc_ab_old = 0, par_mnoc_ib_old = 0;
  736. int rc = 0, i = 0;
  737. uint64_t applied_ab = 0, applied_ib = 0;
  738. mutex_lock(&cpas_core->tree_lock);
  739. if (!cpas_client->tree_node_valid) {
  740. /*
  741. * This is by assuming apply_client_axi_vote is called
  742. * for these clients from only cpas_start, cpas_stop.
  743. * not called from hw_update_axi_vote
  744. */
  745. for (i = 0; i < cpas_core->num_axi_ports; i++) {
  746. if (axi_vote->axi_path[0].mnoc_ab_bw) {
  747. /* start case */
  748. cpas_core->axi_port[i].additional_bw +=
  749. CAM_CPAS_DEFAULT_AXI_BW;
  750. } else {
  751. /* stop case */
  752. cpas_core->axi_port[i].additional_bw -=
  753. CAM_CPAS_DEFAULT_AXI_BW;
  754. }
  755. mnoc_axi_port_updated[i] = true;
  756. }
  757. for (i = 0; i < cpas_core->num_camnoc_axi_ports; i++) {
  758. if (axi_vote->axi_path[0].camnoc_bw) {
  759. /* start case */
  760. cpas_core->camnoc_axi_port[i].additional_bw +=
  761. CAM_CPAS_DEFAULT_AXI_BW;
  762. } else {
  763. /* stop case */
  764. cpas_core->camnoc_axi_port[i].additional_bw -=
  765. CAM_CPAS_DEFAULT_AXI_BW;
  766. }
  767. camnoc_axi_port_updated[i] = true;
  768. }
  769. goto vote_start_clients;
  770. }
  771. rc = cam_cpas_axi_consolidate_path_votes(cpas_client, axi_vote);
  772. if (rc) {
  773. CAM_ERR(CAM_PERF, "Failed in bw consolidation, Client [%s][%d]",
  774. cpas_client->data.identifier,
  775. cpas_client->data.cell_index);
  776. goto unlock_tree;
  777. }
  778. con_axi_vote = &cpas_client->axi_vote;
  779. cam_cpas_dump_axi_vote_info(cpas_client, "Consolidated Vote",
  780. con_axi_vote);
  781. /* Traverse through node tree and update bw vote values */
  782. for (i = 0; i < con_axi_vote->num_paths; i++) {
  783. path_data_type =
  784. con_axi_vote->axi_path[i].path_data_type;
  785. transac_type =
  786. con_axi_vote->axi_path[i].transac_type;
  787. curr_tree_node = cpas_client->tree_node[path_data_type]
  788. [transac_type];
  789. if (con_axi_vote->axi_path[i].mnoc_ab_bw == 0)
  790. con_axi_vote->axi_path[i].mnoc_ab_bw =
  791. con_axi_vote->axi_path[i].camnoc_bw;
  792. if (con_axi_vote->axi_path[i].camnoc_bw == 0)
  793. con_axi_vote->axi_path[i].camnoc_bw =
  794. con_axi_vote->axi_path[i].mnoc_ab_bw;
  795. if ((curr_tree_node->camnoc_bw ==
  796. con_axi_vote->axi_path[i].camnoc_bw) &&
  797. (curr_tree_node->mnoc_ab_bw ==
  798. con_axi_vote->axi_path[i].mnoc_ab_bw) &&
  799. (curr_tree_node->mnoc_ib_bw ==
  800. con_axi_vote->axi_path[i].mnoc_ib_bw))
  801. continue;
  802. curr_camnoc_old = curr_tree_node->camnoc_bw;
  803. curr_mnoc_ab_old = curr_tree_node->mnoc_ab_bw;
  804. curr_mnoc_ib_old = curr_tree_node->mnoc_ib_bw;
  805. curr_tree_node->camnoc_bw =
  806. con_axi_vote->axi_path[i].camnoc_bw;
  807. curr_tree_node->mnoc_ab_bw =
  808. con_axi_vote->axi_path[i].mnoc_ab_bw;
  809. curr_tree_node->mnoc_ib_bw =
  810. con_axi_vote->axi_path[i].mnoc_ib_bw;
  811. while (curr_tree_node->parent_node) {
  812. par_tree_node = curr_tree_node->parent_node;
  813. par_camnoc_old = par_tree_node->camnoc_bw;
  814. par_mnoc_ab_old = par_tree_node->mnoc_ab_bw;
  815. par_mnoc_ib_old = par_tree_node->mnoc_ib_bw;
  816. par_tree_node->mnoc_ab_bw -= curr_mnoc_ab_old;
  817. par_tree_node->mnoc_ab_bw += curr_tree_node->mnoc_ab_bw;
  818. par_tree_node->mnoc_ib_bw -= curr_mnoc_ib_old;
  819. par_tree_node->mnoc_ib_bw += curr_tree_node->mnoc_ib_bw;
  820. if (par_tree_node->merge_type ==
  821. CAM_CPAS_TRAFFIC_MERGE_SUM) {
  822. par_tree_node->camnoc_bw -=
  823. curr_camnoc_old;
  824. par_tree_node->camnoc_bw +=
  825. curr_tree_node->camnoc_bw;
  826. } else if (par_tree_node->merge_type ==
  827. CAM_CPAS_TRAFFIC_MERGE_SUM_INTERLEAVE) {
  828. par_tree_node->camnoc_bw -=
  829. (curr_camnoc_old / 2);
  830. par_tree_node->camnoc_bw +=
  831. (curr_tree_node->camnoc_bw / 2);
  832. } else {
  833. CAM_ERR(CAM_CPAS, "Invalid Merge type");
  834. rc = -EINVAL;
  835. goto unlock_tree;
  836. }
  837. if (!par_tree_node->parent_node) {
  838. if ((par_tree_node->axi_port_idx < 0) ||
  839. (par_tree_node->axi_port_idx >=
  840. CAM_CPAS_MAX_AXI_PORTS)) {
  841. CAM_ERR(CAM_CPAS,
  842. "AXI port index invalid");
  843. rc = -EINVAL;
  844. goto unlock_tree;
  845. }
  846. rc = cam_cpas_update_axi_vote_bw(cpas_hw,
  847. par_tree_node,
  848. mnoc_axi_port_updated,
  849. camnoc_axi_port_updated);
  850. if (rc) {
  851. CAM_ERR(CAM_CPAS,
  852. "Update Vote failed");
  853. goto unlock_tree;
  854. }
  855. }
  856. curr_tree_node = par_tree_node;
  857. curr_camnoc_old = par_camnoc_old;
  858. curr_mnoc_ab_old = par_mnoc_ab_old;
  859. curr_mnoc_ib_old = par_mnoc_ib_old;
  860. }
  861. }
  862. if (!par_tree_node) {
  863. CAM_DBG(CAM_CPAS, "No change in BW for all paths");
  864. rc = 0;
  865. goto unlock_tree;
  866. }
  867. vote_start_clients:
  868. for (i = 0; i < cpas_core->num_axi_ports; i++) {
  869. if (mnoc_axi_port_updated[i])
  870. mnoc_axi_port = &cpas_core->axi_port[i];
  871. else
  872. continue;
  873. CAM_DBG(CAM_PERF,
  874. "Port[%s] : ab=%lld ib=%lld additional=%lld, streamon_clients=%d",
  875. mnoc_axi_port->axi_port_name, mnoc_axi_port->ab_bw,
  876. mnoc_axi_port->ib_bw, mnoc_axi_port->additional_bw,
  877. cpas_core->streamon_clients);
  878. if (mnoc_axi_port->ab_bw)
  879. mnoc_ab_bw = mnoc_axi_port->ab_bw;
  880. else if (mnoc_axi_port->additional_bw)
  881. mnoc_ab_bw = mnoc_axi_port->additional_bw;
  882. else if (cpas_core->streamon_clients)
  883. mnoc_ab_bw = CAM_CPAS_DEFAULT_AXI_BW;
  884. else
  885. mnoc_ab_bw = 0;
  886. if (cpas_core->axi_port[i].ib_bw_voting_needed)
  887. mnoc_ib_bw = mnoc_axi_port->ib_bw;
  888. else
  889. mnoc_ib_bw = 0;
  890. rc = cam_cpas_util_vote_bus_client_bw(
  891. &mnoc_axi_port->bus_client,
  892. mnoc_ab_bw, mnoc_ib_bw, false, &applied_ab,
  893. &applied_ib);
  894. if (rc) {
  895. CAM_ERR(CAM_CPAS,
  896. "Failed in mnoc vote ab[%llu] ib[%llu] rc=%d",
  897. mnoc_ab_bw, mnoc_ib_bw, rc);
  898. goto unlock_tree;
  899. }
  900. mnoc_axi_port->applied_ab_bw = applied_ab;
  901. mnoc_axi_port->applied_ib_bw = applied_ib;
  902. }
  903. rc = cam_cpas_camnoc_set_vote_axi_clk_rate(
  904. cpas_hw, camnoc_axi_port_updated);
  905. if (rc)
  906. CAM_ERR(CAM_CPAS, "Failed in setting axi clk rate rc=%d", rc);
  907. unlock_tree:
  908. mutex_unlock(&cpas_core->tree_lock);
  909. return rc;
  910. }
  911. static int cam_cpas_util_apply_default_axi_vote(
  912. struct cam_hw_info *cpas_hw, bool enable)
  913. {
  914. struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
  915. struct cam_cpas_axi_port *axi_port = NULL;
  916. uint64_t mnoc_ab_bw = 0, mnoc_ib_bw = 0;
  917. int rc = 0, i = 0;
  918. mutex_lock(&cpas_core->tree_lock);
  919. for (i = 0; i < cpas_core->num_axi_ports; i++) {
  920. if (!cpas_core->axi_port[i].ab_bw ||
  921. !cpas_core->axi_port[i].ib_bw)
  922. axi_port = &cpas_core->axi_port[i];
  923. else
  924. continue;
  925. if (enable)
  926. mnoc_ib_bw = CAM_CPAS_DEFAULT_AXI_BW;
  927. else
  928. mnoc_ib_bw = 0;
  929. CAM_DBG(CAM_CPAS, "Port=[%s] :ab[%llu] ib[%llu]",
  930. axi_port->axi_port_name, mnoc_ab_bw, mnoc_ib_bw);
  931. rc = cam_cpas_util_vote_bus_client_bw(&axi_port->bus_client,
  932. mnoc_ab_bw, mnoc_ib_bw, false, &axi_port->applied_ab_bw,
  933. &axi_port->applied_ib_bw);
  934. if (rc) {
  935. CAM_ERR(CAM_CPAS,
  936. "Failed in mnoc vote ab[%llu] ib[%llu] rc=%d",
  937. mnoc_ab_bw, mnoc_ib_bw, rc);
  938. goto unlock_tree;
  939. }
  940. }
  941. unlock_tree:
  942. mutex_unlock(&cpas_core->tree_lock);
  943. return rc;
  944. }
  945. static int cam_cpas_hw_update_axi_vote(struct cam_hw_info *cpas_hw,
  946. uint32_t client_handle, struct cam_axi_vote *client_axi_vote)
  947. {
  948. struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
  949. struct cam_cpas_client *cpas_client = NULL;
  950. struct cam_axi_vote *axi_vote = NULL;
  951. uint32_t client_indx = CAM_CPAS_GET_CLIENT_IDX(client_handle);
  952. int rc = 0;
  953. if (!client_axi_vote) {
  954. CAM_ERR(CAM_CPAS, "Invalid arg, client_handle=%d",
  955. client_handle);
  956. return -EINVAL;
  957. }
  958. if (!CAM_CPAS_CLIENT_VALID(client_indx))
  959. return -EINVAL;
  960. mutex_lock(&cpas_hw->hw_mutex);
  961. mutex_lock(&cpas_core->client_mutex[client_indx]);
  962. axi_vote = kmemdup(client_axi_vote, sizeof(struct cam_axi_vote),
  963. GFP_KERNEL);
  964. if (!axi_vote) {
  965. CAM_ERR(CAM_CPAS, "Out of memory");
  966. mutex_unlock(&cpas_core->client_mutex[client_indx]);
  967. mutex_unlock(&cpas_hw->hw_mutex);
  968. return -ENOMEM;
  969. }
  970. cam_cpas_dump_axi_vote_info(cpas_core->cpas_client[client_indx],
  971. "Incoming Vote", axi_vote);
  972. cpas_client = cpas_core->cpas_client[client_indx];
  973. if (!CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) {
  974. CAM_ERR(CAM_CPAS, "client=[%d][%s][%d] has not started",
  975. client_indx, cpas_client->data.identifier,
  976. cpas_client->data.cell_index);
  977. rc = -EPERM;
  978. goto unlock_client;
  979. }
  980. rc = cam_cpas_util_translate_client_paths(axi_vote);
  981. if (rc) {
  982. CAM_ERR(CAM_CPAS,
  983. "Unable to translate per path votes rc: %d", rc);
  984. goto unlock_client;
  985. }
  986. cam_cpas_dump_axi_vote_info(cpas_core->cpas_client[client_indx],
  987. "Translated Vote", axi_vote);
  988. rc = cam_cpas_util_apply_client_axi_vote(cpas_hw,
  989. cpas_core->cpas_client[client_indx], axi_vote);
  990. /* Log an entry whenever there is an AXI update - after updating */
  991. cam_cpas_update_monitor_array(cpas_hw, "CPAS AXI post-update",
  992. client_indx);
  993. unlock_client:
  994. cam_free_clear((void *)axi_vote);
  995. axi_vote = NULL;
  996. mutex_unlock(&cpas_core->client_mutex[client_indx]);
  997. mutex_unlock(&cpas_hw->hw_mutex);
  998. return rc;
  999. }
  1000. static int cam_cpas_util_get_ahb_level(struct cam_hw_info *cpas_hw,
  1001. struct device *dev, unsigned long freq, enum cam_vote_level *req_level)
  1002. {
  1003. struct cam_cpas_private_soc *soc_private =
  1004. (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private;
  1005. struct dev_pm_opp *opp;
  1006. unsigned int corner;
  1007. enum cam_vote_level level = CAM_SVS_VOTE;
  1008. unsigned long corner_freq = freq;
  1009. int i;
  1010. if (!dev || !req_level) {
  1011. CAM_ERR(CAM_CPAS, "Invalid params %pK, %pK", dev, req_level);
  1012. return -EINVAL;
  1013. }
  1014. opp = dev_pm_opp_find_freq_ceil(dev, &corner_freq);
  1015. if (IS_ERR(opp)) {
  1016. CAM_DBG(CAM_CPAS, "OPP Ceil not available for freq :%ld, %pK",
  1017. corner_freq, opp);
  1018. *req_level = CAM_TURBO_VOTE;
  1019. return 0;
  1020. }
  1021. corner = dev_pm_opp_get_voltage(opp);
  1022. for (i = 0; i < soc_private->num_vdd_ahb_mapping; i++)
  1023. if (corner == soc_private->vdd_ahb[i].vdd_corner)
  1024. level = soc_private->vdd_ahb[i].ahb_level;
  1025. CAM_DBG(CAM_CPAS,
  1026. "From OPP table : freq=[%ld][%ld], corner=%d, level=%d",
  1027. freq, corner_freq, corner, level);
  1028. *req_level = level;
  1029. return 0;
  1030. }
  1031. static int cam_cpas_util_apply_client_ahb_vote(struct cam_hw_info *cpas_hw,
  1032. struct cam_cpas_client *cpas_client, struct cam_ahb_vote *ahb_vote,
  1033. enum cam_vote_level *applied_level)
  1034. {
  1035. struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
  1036. struct cam_cpas_bus_client *ahb_bus_client = &cpas_core->ahb_bus_client;
  1037. enum cam_vote_level required_level;
  1038. enum cam_vote_level highest_level;
  1039. int i, rc = 0;
  1040. if (!ahb_bus_client->valid) {
  1041. CAM_ERR(CAM_CPAS, "AHB Bus client not valid");
  1042. return -EINVAL;
  1043. }
  1044. if (ahb_vote->type == CAM_VOTE_DYNAMIC) {
  1045. rc = cam_cpas_util_get_ahb_level(cpas_hw, cpas_client->data.dev,
  1046. ahb_vote->vote.freq, &required_level);
  1047. if (rc)
  1048. return rc;
  1049. } else {
  1050. required_level = ahb_vote->vote.level;
  1051. }
  1052. if (cpas_client->ahb_level == required_level)
  1053. return 0;
  1054. mutex_lock(&ahb_bus_client->lock);
  1055. cpas_client->ahb_level = required_level;
  1056. CAM_DBG(CAM_CPAS, "Client[%s] required level[%d], curr_level[%d]",
  1057. ahb_bus_client->common_data.name, required_level,
  1058. ahb_bus_client->curr_vote_level);
  1059. if (required_level == ahb_bus_client->curr_vote_level)
  1060. goto unlock_bus_client;
  1061. highest_level = required_level;
  1062. for (i = 0; i < cpas_core->num_clients; i++) {
  1063. if (cpas_core->cpas_client[i] && (highest_level <
  1064. cpas_core->cpas_client[i]->ahb_level))
  1065. highest_level = cpas_core->cpas_client[i]->ahb_level;
  1066. }
  1067. CAM_DBG(CAM_CPAS, "Required highest_level[%d]", highest_level);
  1068. if (!cpas_core->ahb_bus_scaling_disable) {
  1069. rc = cam_cpas_util_vote_bus_client_level(ahb_bus_client,
  1070. highest_level);
  1071. if (rc) {
  1072. CAM_ERR(CAM_CPAS, "Failed in ahb vote, level=%d, rc=%d",
  1073. highest_level, rc);
  1074. goto unlock_bus_client;
  1075. }
  1076. }
  1077. if (cpas_core->streamon_clients) {
  1078. rc = cam_soc_util_set_clk_rate_level(&cpas_hw->soc_info,
  1079. highest_level, true);
  1080. if (rc) {
  1081. CAM_ERR(CAM_CPAS,
  1082. "Failed in scaling clock rate level %d for AHB",
  1083. highest_level);
  1084. goto unlock_bus_client;
  1085. }
  1086. }
  1087. if (applied_level)
  1088. *applied_level = highest_level;
  1089. unlock_bus_client:
  1090. mutex_unlock(&ahb_bus_client->lock);
  1091. return rc;
  1092. }
  1093. static int cam_cpas_hw_update_ahb_vote(struct cam_hw_info *cpas_hw,
  1094. uint32_t client_handle, struct cam_ahb_vote *client_ahb_vote)
  1095. {
  1096. struct cam_ahb_vote ahb_vote;
  1097. struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
  1098. struct cam_cpas_client *cpas_client = NULL;
  1099. uint32_t client_indx = CAM_CPAS_GET_CLIENT_IDX(client_handle);
  1100. int rc = 0;
  1101. if (!client_ahb_vote) {
  1102. CAM_ERR(CAM_CPAS, "Invalid input arg");
  1103. return -EINVAL;
  1104. }
  1105. ahb_vote = *client_ahb_vote;
  1106. if (ahb_vote.vote.level == 0) {
  1107. CAM_DBG(CAM_CPAS, "0 ahb vote from client %d",
  1108. client_handle);
  1109. ahb_vote.type = CAM_VOTE_ABSOLUTE;
  1110. ahb_vote.vote.level = CAM_SVS_VOTE;
  1111. }
  1112. if (!CAM_CPAS_CLIENT_VALID(client_indx))
  1113. return -EINVAL;
  1114. mutex_lock(&cpas_hw->hw_mutex);
  1115. mutex_lock(&cpas_core->client_mutex[client_indx]);
  1116. cpas_client = cpas_core->cpas_client[client_indx];
  1117. if (!CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) {
  1118. CAM_ERR(CAM_CPAS, "client=[%d][%s][%d] has not started",
  1119. client_indx, cpas_client->data.identifier,
  1120. cpas_client->data.cell_index);
  1121. rc = -EPERM;
  1122. goto unlock_client;
  1123. }
  1124. CAM_DBG(CAM_PERF,
  1125. "client=[%d][%s][%d] : type[%d], level[%d], freq[%ld], applied[%d]",
  1126. client_indx, cpas_client->data.identifier,
  1127. cpas_client->data.cell_index, ahb_vote.type,
  1128. ahb_vote.vote.level, ahb_vote.vote.freq,
  1129. cpas_core->cpas_client[client_indx]->ahb_level);
  1130. rc = cam_cpas_util_apply_client_ahb_vote(cpas_hw,
  1131. cpas_core->cpas_client[client_indx], &ahb_vote, NULL);
  1132. unlock_client:
  1133. mutex_unlock(&cpas_core->client_mutex[client_indx]);
  1134. mutex_unlock(&cpas_hw->hw_mutex);
  1135. return rc;
  1136. }
  1137. static int cam_cpas_util_create_vote_all_paths(
  1138. struct cam_cpas_client *cpas_client,
  1139. struct cam_axi_vote *axi_vote)
  1140. {
  1141. int i, j;
  1142. uint64_t camnoc_bw, mnoc_ab_bw, mnoc_ib_bw;
  1143. struct cam_axi_per_path_bw_vote *axi_path;
  1144. if (!cpas_client || !axi_vote)
  1145. return -EINVAL;
  1146. camnoc_bw = axi_vote->axi_path[0].camnoc_bw;
  1147. mnoc_ab_bw = axi_vote->axi_path[0].mnoc_ab_bw;
  1148. mnoc_ib_bw = axi_vote->axi_path[0].mnoc_ib_bw;
  1149. axi_vote->num_paths = 0;
  1150. for (i = 0; i < CAM_CPAS_TRANSACTION_MAX; i++) {
  1151. for (j = 0; j < CAM_CPAS_PATH_DATA_MAX; j++) {
  1152. if (cpas_client->tree_node[j][i]) {
  1153. axi_path =
  1154. &axi_vote->axi_path[axi_vote->num_paths];
  1155. axi_path->path_data_type = j;
  1156. axi_path->transac_type = i;
  1157. axi_path->camnoc_bw = camnoc_bw;
  1158. axi_path->mnoc_ab_bw = mnoc_ab_bw;
  1159. axi_path->mnoc_ib_bw = mnoc_ib_bw;
  1160. axi_vote->num_paths++;
  1161. }
  1162. }
  1163. }
  1164. return 0;
  1165. }
  1166. static int cam_cpas_hw_start(void *hw_priv, void *start_args,
  1167. uint32_t arg_size)
  1168. {
  1169. struct cam_hw_info *cpas_hw;
  1170. struct cam_cpas *cpas_core;
  1171. uint32_t client_indx;
  1172. struct cam_cpas_hw_cmd_start *cmd_hw_start;
  1173. struct cam_cpas_client *cpas_client;
  1174. struct cam_ahb_vote *ahb_vote;
  1175. struct cam_ahb_vote remove_ahb;
  1176. struct cam_axi_vote axi_vote = {0};
  1177. enum cam_vote_level applied_level = CAM_SVS_VOTE;
  1178. int rc, i = 0;
  1179. struct cam_cpas_private_soc *soc_private = NULL;
  1180. bool invalid_start = true;
  1181. if (!hw_priv || !start_args) {
  1182. CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK",
  1183. hw_priv, start_args);
  1184. return -EINVAL;
  1185. }
  1186. if (sizeof(struct cam_cpas_hw_cmd_start) != arg_size) {
  1187. CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %zd %d",
  1188. sizeof(struct cam_cpas_hw_cmd_start), arg_size);
  1189. return -EINVAL;
  1190. }
  1191. cpas_hw = (struct cam_hw_info *)hw_priv;
  1192. cpas_core = (struct cam_cpas *) cpas_hw->core_info;
  1193. soc_private = (struct cam_cpas_private_soc *)
  1194. cpas_hw->soc_info.soc_private;
  1195. cmd_hw_start = (struct cam_cpas_hw_cmd_start *)start_args;
  1196. client_indx = CAM_CPAS_GET_CLIENT_IDX(cmd_hw_start->client_handle);
  1197. ahb_vote = cmd_hw_start->ahb_vote;
  1198. if (!ahb_vote || !cmd_hw_start->axi_vote)
  1199. return -EINVAL;
  1200. if (!ahb_vote->vote.level) {
  1201. CAM_ERR(CAM_CPAS, "Invalid vote ahb[%d]",
  1202. ahb_vote->vote.level);
  1203. return -EINVAL;
  1204. }
  1205. memcpy(&axi_vote, cmd_hw_start->axi_vote, sizeof(struct cam_axi_vote));
  1206. for (i = 0; i < axi_vote.num_paths; i++) {
  1207. if ((axi_vote.axi_path[i].camnoc_bw != 0) ||
  1208. (axi_vote.axi_path[i].mnoc_ab_bw != 0) ||
  1209. (axi_vote.axi_path[i].mnoc_ib_bw != 0)) {
  1210. invalid_start = false;
  1211. break;
  1212. }
  1213. }
  1214. if (invalid_start) {
  1215. CAM_ERR(CAM_CPAS, "Zero start vote");
  1216. return -EINVAL;
  1217. }
  1218. if (!CAM_CPAS_CLIENT_VALID(client_indx))
  1219. return -EINVAL;
  1220. mutex_lock(&cpas_hw->hw_mutex);
  1221. mutex_lock(&cpas_core->client_mutex[client_indx]);
  1222. cpas_client = cpas_core->cpas_client[client_indx];
  1223. if (!CAM_CPAS_CLIENT_REGISTERED(cpas_core, client_indx)) {
  1224. CAM_ERR(CAM_CPAS, "client=[%d] is not registered",
  1225. client_indx);
  1226. rc = -EPERM;
  1227. goto error;
  1228. }
  1229. if (CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) {
  1230. CAM_ERR(CAM_CPAS, "client=[%d][%s][%d] is in start state",
  1231. client_indx, cpas_client->data.identifier,
  1232. cpas_client->data.cell_index);
  1233. rc = -EPERM;
  1234. goto error;
  1235. }
  1236. CAM_DBG(CAM_CPAS,
  1237. "AHB :client=[%d][%s][%d] type[%d], level[%d], applied[%d]",
  1238. client_indx, cpas_client->data.identifier,
  1239. cpas_client->data.cell_index,
  1240. ahb_vote->type, ahb_vote->vote.level, cpas_client->ahb_level);
  1241. rc = cam_cpas_util_apply_client_ahb_vote(cpas_hw, cpas_client,
  1242. ahb_vote, &applied_level);
  1243. if (rc)
  1244. goto error;
  1245. cam_cpas_dump_axi_vote_info(cpas_client, "CPAS Start Vote",
  1246. &axi_vote);
  1247. /*
  1248. * If client has indicated start bw to be applied on all paths
  1249. * of client, apply that otherwise apply whatever the client supplies
  1250. * for specific paths
  1251. */
  1252. if (axi_vote.axi_path[0].path_data_type ==
  1253. CAM_CPAS_API_PATH_DATA_STD_START) {
  1254. rc = cam_cpas_util_create_vote_all_paths(cpas_client,
  1255. &axi_vote);
  1256. } else {
  1257. rc = cam_cpas_util_translate_client_paths(&axi_vote);
  1258. }
  1259. if (rc) {
  1260. CAM_ERR(CAM_CPAS, "Unable to create or translate paths rc: %d",
  1261. rc);
  1262. goto remove_ahb_vote;
  1263. }
  1264. cam_cpas_dump_axi_vote_info(cpas_client, "CPAS Start Translated Vote",
  1265. &axi_vote);
  1266. rc = cam_cpas_util_apply_client_axi_vote(cpas_hw,
  1267. cpas_client, &axi_vote);
  1268. if (rc)
  1269. goto remove_ahb_vote;
  1270. if (cpas_core->streamon_clients == 0) {
  1271. rc = cam_cpas_util_apply_default_axi_vote(cpas_hw, true);
  1272. if (rc)
  1273. goto remove_ahb_vote;
  1274. atomic_set(&cpas_core->irq_count, 1);
  1275. rc = cam_cpas_soc_enable_resources(&cpas_hw->soc_info,
  1276. applied_level);
  1277. if (rc) {
  1278. atomic_set(&cpas_core->irq_count, 0);
  1279. CAM_ERR(CAM_CPAS, "enable_resorce failed, rc=%d", rc);
  1280. goto remove_axi_vote;
  1281. }
  1282. if (cpas_core->internal_ops.power_on) {
  1283. rc = cpas_core->internal_ops.power_on(cpas_hw);
  1284. if (rc) {
  1285. atomic_set(&cpas_core->irq_count, 0);
  1286. cam_cpas_soc_disable_resources(
  1287. &cpas_hw->soc_info, true, true);
  1288. CAM_ERR(CAM_CPAS,
  1289. "failed in power_on settings rc=%d",
  1290. rc);
  1291. goto remove_axi_vote;
  1292. }
  1293. }
  1294. CAM_DBG(CAM_CPAS, "irq_count=%d\n",
  1295. atomic_read(&cpas_core->irq_count));
  1296. cam_smmu_reset_cb_page_fault_cnt();
  1297. cpas_hw->hw_state = CAM_HW_STATE_POWER_UP;
  1298. }
  1299. cpas_client->started = true;
  1300. cpas_core->streamon_clients++;
  1301. CAM_DBG(CAM_CPAS, "client=[%d][%s][%d] streamon_clients=%d",
  1302. client_indx, cpas_client->data.identifier,
  1303. cpas_client->data.cell_index, cpas_core->streamon_clients);
  1304. mutex_unlock(&cpas_core->client_mutex[client_indx]);
  1305. mutex_unlock(&cpas_hw->hw_mutex);
  1306. return rc;
  1307. remove_axi_vote:
  1308. memset(&axi_vote, 0x0, sizeof(struct cam_axi_vote));
  1309. rc = cam_cpas_util_create_vote_all_paths(cpas_client, &axi_vote);
  1310. if (rc)
  1311. CAM_ERR(CAM_CPAS, "Unable to create per path votes rc: %d", rc);
  1312. cam_cpas_dump_axi_vote_info(cpas_client, "CPAS Start fail Vote",
  1313. &axi_vote);
  1314. rc = cam_cpas_util_apply_client_axi_vote(cpas_hw,
  1315. cpas_client, &axi_vote);
  1316. if (rc)
  1317. CAM_ERR(CAM_CPAS, "Unable remove votes rc: %d", rc);
  1318. remove_ahb_vote:
  1319. remove_ahb.type = CAM_VOTE_ABSOLUTE;
  1320. remove_ahb.vote.level = CAM_SUSPEND_VOTE;
  1321. rc = cam_cpas_util_apply_client_ahb_vote(cpas_hw, cpas_client,
  1322. &remove_ahb, NULL);
  1323. if (rc)
  1324. CAM_ERR(CAM_CPAS, "Removing AHB vote failed, rc=%d", rc);
  1325. error:
  1326. mutex_unlock(&cpas_core->client_mutex[client_indx]);
  1327. mutex_unlock(&cpas_hw->hw_mutex);
  1328. return rc;
  1329. }
  1330. static int _check_irq_count(struct cam_cpas *cpas_core)
  1331. {
  1332. return (atomic_read(&cpas_core->irq_count) > 0) ? 0 : 1;
  1333. }
  1334. static int cam_cpas_hw_stop(void *hw_priv, void *stop_args,
  1335. uint32_t arg_size)
  1336. {
  1337. struct cam_hw_info *cpas_hw;
  1338. struct cam_cpas *cpas_core;
  1339. uint32_t client_indx;
  1340. struct cam_cpas_hw_cmd_stop *cmd_hw_stop;
  1341. struct cam_cpas_client *cpas_client;
  1342. struct cam_ahb_vote ahb_vote;
  1343. struct cam_axi_vote axi_vote = {0};
  1344. struct cam_cpas_private_soc *soc_private = NULL;
  1345. int rc = 0;
  1346. long result;
  1347. int retry_camnoc_idle = 0;
  1348. if (!hw_priv || !stop_args) {
  1349. CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK",
  1350. hw_priv, stop_args);
  1351. return -EINVAL;
  1352. }
  1353. if (sizeof(struct cam_cpas_hw_cmd_stop) != arg_size) {
  1354. CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %zd %d",
  1355. sizeof(struct cam_cpas_hw_cmd_stop), arg_size);
  1356. return -EINVAL;
  1357. }
  1358. cpas_hw = (struct cam_hw_info *)hw_priv;
  1359. cpas_core = (struct cam_cpas *) cpas_hw->core_info;
  1360. soc_private = (struct cam_cpas_private_soc *)
  1361. cpas_hw->soc_info.soc_private;
  1362. cmd_hw_stop = (struct cam_cpas_hw_cmd_stop *)stop_args;
  1363. client_indx = CAM_CPAS_GET_CLIENT_IDX(cmd_hw_stop->client_handle);
  1364. if (!CAM_CPAS_CLIENT_VALID(client_indx))
  1365. return -EINVAL;
  1366. mutex_lock(&cpas_hw->hw_mutex);
  1367. mutex_lock(&cpas_core->client_mutex[client_indx]);
  1368. cpas_client = cpas_core->cpas_client[client_indx];
  1369. CAM_DBG(CAM_CPAS, "Client=[%d][%s][%d] streamon_clients=%d",
  1370. client_indx, cpas_client->data.identifier,
  1371. cpas_client->data.cell_index, cpas_core->streamon_clients);
  1372. if (!CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) {
  1373. CAM_ERR(CAM_CPAS, "Client=[%d][%s][%d] is not started",
  1374. client_indx, cpas_client->data.identifier,
  1375. cpas_client->data.cell_index);
  1376. rc = -EPERM;
  1377. goto done;
  1378. }
  1379. cpas_client->started = false;
  1380. cpas_core->streamon_clients--;
  1381. if (cpas_core->streamon_clients == 0) {
  1382. if (cpas_core->internal_ops.power_off) {
  1383. rc = cpas_core->internal_ops.power_off(cpas_hw);
  1384. if (rc) {
  1385. CAM_ERR(CAM_CPAS,
  1386. "failed in power_off settings rc=%d",
  1387. rc);
  1388. /* Do not return error, passthrough */
  1389. }
  1390. }
  1391. if (cpas_core->internal_ops.qchannel_handshake) {
  1392. rc = cpas_core->internal_ops.qchannel_handshake(
  1393. cpas_hw, false);
  1394. if (rc) {
  1395. CAM_ERR(CAM_CPAS,
  1396. "failed in qchannel_handshake rc=%d",
  1397. rc);
  1398. retry_camnoc_idle = 1;
  1399. /* Do not return error, passthrough */
  1400. }
  1401. }
  1402. rc = cam_cpas_soc_disable_irq(&cpas_hw->soc_info);
  1403. if (rc) {
  1404. CAM_ERR(CAM_CPAS, "disable_irq failed, rc=%d", rc);
  1405. goto done;
  1406. }
  1407. /* Wait for any IRQs still being handled */
  1408. atomic_dec(&cpas_core->irq_count);
  1409. result = wait_event_timeout(cpas_core->irq_count_wq,
  1410. _check_irq_count(cpas_core), HZ);
  1411. if (result == 0) {
  1412. CAM_ERR(CAM_CPAS, "Wait failed: irq_count=%d",
  1413. atomic_read(&cpas_core->irq_count));
  1414. }
  1415. /* try again incase camnoc is still not idle */
  1416. if (cpas_core->internal_ops.qchannel_handshake &&
  1417. retry_camnoc_idle) {
  1418. rc = cpas_core->internal_ops.qchannel_handshake(
  1419. cpas_hw, false);
  1420. if (rc) {
  1421. CAM_ERR(CAM_CPAS,
  1422. "failed in qchannel_handshake rc=%d",
  1423. rc);
  1424. /* Do not return error, passthrough */
  1425. }
  1426. }
  1427. rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info,
  1428. true, false);
  1429. if (rc) {
  1430. CAM_ERR(CAM_CPAS, "disable_resorce failed, rc=%d", rc);
  1431. goto done;
  1432. }
  1433. CAM_DBG(CAM_CPAS, "Disabled all the resources: irq_count=%d",
  1434. atomic_read(&cpas_core->irq_count));
  1435. cpas_hw->hw_state = CAM_HW_STATE_POWER_DOWN;
  1436. }
  1437. ahb_vote.type = CAM_VOTE_ABSOLUTE;
  1438. ahb_vote.vote.level = CAM_SUSPEND_VOTE;
  1439. rc = cam_cpas_util_apply_client_ahb_vote(cpas_hw, cpas_client,
  1440. &ahb_vote, NULL);
  1441. if (rc)
  1442. goto done;
  1443. rc = cam_cpas_util_create_vote_all_paths(cpas_client, &axi_vote);
  1444. if (rc) {
  1445. CAM_ERR(CAM_CPAS, "Unable to create per path votes rc: %d", rc);
  1446. goto done;
  1447. }
  1448. cam_cpas_dump_axi_vote_info(cpas_client, "CPAS Stop Vote", &axi_vote);
  1449. rc = cam_cpas_util_apply_client_axi_vote(cpas_hw,
  1450. cpas_client, &axi_vote);
  1451. if (rc)
  1452. goto done;
  1453. if (cpas_core->streamon_clients == 0)
  1454. rc = cam_cpas_util_apply_default_axi_vote(cpas_hw, false);
  1455. done:
  1456. mutex_unlock(&cpas_core->client_mutex[client_indx]);
  1457. mutex_unlock(&cpas_hw->hw_mutex);
  1458. return rc;
  1459. }
  1460. static int cam_cpas_hw_init(void *hw_priv, void *init_hw_args,
  1461. uint32_t arg_size)
  1462. {
  1463. struct cam_hw_info *cpas_hw;
  1464. struct cam_cpas *cpas_core;
  1465. int rc = 0;
  1466. if (!hw_priv || !init_hw_args) {
  1467. CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK",
  1468. hw_priv, init_hw_args);
  1469. return -EINVAL;
  1470. }
  1471. if (sizeof(struct cam_cpas_hw_caps) != arg_size) {
  1472. CAM_ERR(CAM_CPAS, "INIT HW size mismatch %zd %d",
  1473. sizeof(struct cam_cpas_hw_caps), arg_size);
  1474. return -EINVAL;
  1475. }
  1476. cpas_hw = (struct cam_hw_info *)hw_priv;
  1477. cpas_core = (struct cam_cpas *)cpas_hw->core_info;
  1478. if (cpas_core->internal_ops.init_hw_version) {
  1479. rc = cpas_core->internal_ops.init_hw_version(cpas_hw,
  1480. (struct cam_cpas_hw_caps *)init_hw_args);
  1481. }
  1482. return rc;
  1483. }
  1484. static int cam_cpas_hw_register_client(struct cam_hw_info *cpas_hw,
  1485. struct cam_cpas_register_params *register_params)
  1486. {
  1487. int rc;
  1488. char client_name[CAM_HW_IDENTIFIER_LENGTH + 3];
  1489. int32_t client_indx = -1;
  1490. struct cam_cpas *cpas_core = (struct cam_cpas *)cpas_hw->core_info;
  1491. struct cam_cpas_private_soc *soc_private =
  1492. (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private;
  1493. if ((!register_params) ||
  1494. (strlen(register_params->identifier) < 1)) {
  1495. CAM_ERR(CAM_CPAS, "Invalid cpas client identifier");
  1496. return -EINVAL;
  1497. }
  1498. CAM_DBG(CAM_CPAS, "Register params : identifier=%s, cell_index=%d",
  1499. register_params->identifier, register_params->cell_index);
  1500. if (soc_private->client_id_based)
  1501. snprintf(client_name, sizeof(client_name), "%s%d",
  1502. register_params->identifier,
  1503. register_params->cell_index);
  1504. else
  1505. snprintf(client_name, sizeof(client_name), "%s",
  1506. register_params->identifier);
  1507. mutex_lock(&cpas_hw->hw_mutex);
  1508. rc = cam_common_util_get_string_index(soc_private->client_name,
  1509. soc_private->num_clients, client_name, &client_indx);
  1510. mutex_lock(&cpas_core->client_mutex[client_indx]);
  1511. if (rc || !CAM_CPAS_CLIENT_VALID(client_indx) ||
  1512. CAM_CPAS_CLIENT_REGISTERED(cpas_core, client_indx)) {
  1513. CAM_ERR(CAM_CPAS,
  1514. "Inval client %s %d : %d %d %pK %d",
  1515. register_params->identifier,
  1516. register_params->cell_index,
  1517. CAM_CPAS_CLIENT_VALID(client_indx),
  1518. CAM_CPAS_CLIENT_REGISTERED(cpas_core, client_indx),
  1519. cpas_core->cpas_client[client_indx], rc);
  1520. mutex_unlock(&cpas_core->client_mutex[client_indx]);
  1521. mutex_unlock(&cpas_hw->hw_mutex);
  1522. return -EPERM;
  1523. }
  1524. register_params->client_handle =
  1525. CAM_CPAS_GET_CLIENT_HANDLE(client_indx);
  1526. memcpy(&cpas_core->cpas_client[client_indx]->data, register_params,
  1527. sizeof(struct cam_cpas_register_params));
  1528. cpas_core->registered_clients++;
  1529. cpas_core->cpas_client[client_indx]->registered = true;
  1530. CAM_DBG(CAM_CPAS, "client=[%d][%s][%d], registered_clients=%d",
  1531. client_indx,
  1532. cpas_core->cpas_client[client_indx]->data.identifier,
  1533. cpas_core->cpas_client[client_indx]->data.cell_index,
  1534. cpas_core->registered_clients);
  1535. mutex_unlock(&cpas_core->client_mutex[client_indx]);
  1536. mutex_unlock(&cpas_hw->hw_mutex);
  1537. return 0;
  1538. }
  1539. static int cam_cpas_hw_unregister_client(struct cam_hw_info *cpas_hw,
  1540. uint32_t client_handle)
  1541. {
  1542. struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
  1543. uint32_t client_indx = CAM_CPAS_GET_CLIENT_IDX(client_handle);
  1544. int rc = 0;
  1545. if (!CAM_CPAS_CLIENT_VALID(client_indx))
  1546. return -EINVAL;
  1547. mutex_lock(&cpas_hw->hw_mutex);
  1548. mutex_lock(&cpas_core->client_mutex[client_indx]);
  1549. if (!CAM_CPAS_CLIENT_REGISTERED(cpas_core, client_indx)) {
  1550. CAM_ERR(CAM_CPAS, "Client=[%d][%s][%d] not registered",
  1551. client_indx,
  1552. cpas_core->cpas_client[client_indx]->data.identifier,
  1553. cpas_core->cpas_client[client_indx]->data.cell_index);
  1554. rc = -EPERM;
  1555. goto done;
  1556. }
  1557. if (CAM_CPAS_CLIENT_STARTED(cpas_core, client_indx)) {
  1558. CAM_ERR(CAM_CPAS, "Client=[%d][%s][%d] is not stopped",
  1559. client_indx,
  1560. cpas_core->cpas_client[client_indx]->data.identifier,
  1561. cpas_core->cpas_client[client_indx]->data.cell_index);
  1562. rc = -EPERM;
  1563. goto done;
  1564. }
  1565. CAM_DBG(CAM_CPAS, "client=[%d][%s][%d], registered_clients=%d",
  1566. client_indx,
  1567. cpas_core->cpas_client[client_indx]->data.identifier,
  1568. cpas_core->cpas_client[client_indx]->data.cell_index,
  1569. cpas_core->registered_clients);
  1570. cpas_core->cpas_client[client_indx]->registered = false;
  1571. cpas_core->registered_clients--;
  1572. done:
  1573. mutex_unlock(&cpas_core->client_mutex[client_indx]);
  1574. mutex_unlock(&cpas_hw->hw_mutex);
  1575. return rc;
  1576. }
  1577. static int cam_cpas_hw_get_hw_info(void *hw_priv,
  1578. void *get_hw_cap_args, uint32_t arg_size)
  1579. {
  1580. struct cam_hw_info *cpas_hw;
  1581. struct cam_cpas *cpas_core;
  1582. struct cam_cpas_hw_caps *hw_caps;
  1583. struct cam_cpas_private_soc *soc_private;
  1584. if (!hw_priv || !get_hw_cap_args) {
  1585. CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK",
  1586. hw_priv, get_hw_cap_args);
  1587. return -EINVAL;
  1588. }
  1589. if (sizeof(struct cam_cpas_hw_caps) != arg_size) {
  1590. CAM_ERR(CAM_CPAS, "HW_CAPS size mismatch %zd %d",
  1591. sizeof(struct cam_cpas_hw_caps), arg_size);
  1592. return -EINVAL;
  1593. }
  1594. cpas_hw = (struct cam_hw_info *)hw_priv;
  1595. cpas_core = (struct cam_cpas *) cpas_hw->core_info;
  1596. hw_caps = (struct cam_cpas_hw_caps *)get_hw_cap_args;
  1597. *hw_caps = cpas_core->hw_caps;
  1598. /*Extract Fuse Info*/
  1599. soc_private = (struct cam_cpas_private_soc *)
  1600. cpas_hw->soc_info.soc_private;
  1601. hw_caps->fuse_info = soc_private->fuse_info;
  1602. CAM_INFO(CAM_CPAS, "fuse info->num_fuses %d",
  1603. hw_caps->fuse_info.num_fuses);
  1604. return 0;
  1605. }
  1606. static int cam_cpas_log_vote(struct cam_hw_info *cpas_hw)
  1607. {
  1608. struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
  1609. struct cam_cpas_private_soc *soc_private =
  1610. (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private;
  1611. uint32_t i;
  1612. struct cam_cpas_tree_node *curr_node;
  1613. struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info;
  1614. /*
  1615. * First print rpmh registers as early as possible to catch nearest
  1616. * state of rpmh after an issue (overflow) occurs.
  1617. */
  1618. if ((cpas_core->streamon_clients > 0) &&
  1619. (cpas_core->regbase_index[CAM_CPAS_REG_RPMH] != -1)) {
  1620. int reg_base_index =
  1621. cpas_core->regbase_index[CAM_CPAS_REG_RPMH];
  1622. void __iomem *rpmh_base =
  1623. soc_info->reg_map[reg_base_index].mem_base;
  1624. uint32_t offset_fe, offset_be;
  1625. uint32_t fe_val, be_val;
  1626. uint32_t *rpmh_info = &soc_private->rpmh_info[0];
  1627. uint32_t ddr_bcm_index =
  1628. soc_private->rpmh_info[CAM_RPMH_BCM_DDR_INDEX];
  1629. uint32_t mnoc_bcm_index =
  1630. soc_private->rpmh_info[CAM_RPMH_BCM_MNOC_INDEX];
  1631. /*
  1632. * print 12 registers from 0x4, 0x800 offsets -
  1633. * this will give ddr, mmnoc and other BCM info.
  1634. * i=0 for DDR, i=4 for mnoc, but double check for each chipset.
  1635. */
  1636. for (i = 0; i < rpmh_info[CAM_RPMH_NUMBER_OF_BCMS]; i++) {
  1637. if ((!cpas_core->full_state_dump) &&
  1638. (i != ddr_bcm_index) &&
  1639. (i != mnoc_bcm_index))
  1640. continue;
  1641. offset_fe = rpmh_info[CAM_RPMH_BCM_FE_OFFSET] +
  1642. (i * 0x4);
  1643. offset_be = rpmh_info[CAM_RPMH_BCM_BE_OFFSET] +
  1644. (i * 0x4);
  1645. fe_val = cam_io_r_mb(rpmh_base + offset_fe);
  1646. be_val = cam_io_r_mb(rpmh_base + offset_be);
  1647. CAM_INFO(CAM_CPAS,
  1648. "i=%d, FE[offset=0x%x, value=0x%x] BE[offset=0x%x, value=0x%x]",
  1649. i, offset_fe, fe_val, offset_be, be_val);
  1650. }
  1651. }
  1652. for (i = 0; i < cpas_core->num_axi_ports; i++) {
  1653. CAM_INFO(CAM_CPAS,
  1654. "[%s] ab_bw[%lld] ib_bw[%lld] additional_bw[%lld] applied_ab[%lld] applied_ib[%lld]",
  1655. cpas_core->axi_port[i].axi_port_name,
  1656. cpas_core->axi_port[i].ab_bw,
  1657. cpas_core->axi_port[i].ib_bw,
  1658. cpas_core->axi_port[i].additional_bw,
  1659. cpas_core->axi_port[i].applied_ab_bw,
  1660. cpas_core->axi_port[i].applied_ib_bw);
  1661. }
  1662. if (soc_private->control_camnoc_axi_clk) {
  1663. CAM_INFO(CAM_CPAS, "applied camnoc axi clk[%lld]",
  1664. cpas_core->applied_camnoc_axi_rate);
  1665. } else {
  1666. for (i = 0; i < cpas_core->num_camnoc_axi_ports; i++) {
  1667. CAM_INFO(CAM_CPAS,
  1668. "[%s] ab_bw[%lld] ib_bw[%lld] additional_bw[%lld] applied_ab[%lld] applied_ib[%lld]",
  1669. cpas_core->camnoc_axi_port[i].axi_port_name,
  1670. cpas_core->camnoc_axi_port[i].ab_bw,
  1671. cpas_core->camnoc_axi_port[i].ib_bw,
  1672. cpas_core->camnoc_axi_port[i].additional_bw,
  1673. cpas_core->camnoc_axi_port[i].applied_ab_bw,
  1674. cpas_core->camnoc_axi_port[i].applied_ib_bw);
  1675. }
  1676. }
  1677. CAM_INFO(CAM_CPAS, "ahb client curr vote level[%d]",
  1678. cpas_core->ahb_bus_client.curr_vote_level);
  1679. if (!cpas_core->full_state_dump) {
  1680. CAM_DBG(CAM_CPAS, "CPAS full state dump not enabled");
  1681. return 0;
  1682. }
  1683. /* This will traverse through all nodes in the tree and print stats*/
  1684. for (i = 0; i < CAM_CPAS_MAX_TREE_NODES; i++) {
  1685. if (!soc_private->tree_node[i])
  1686. continue;
  1687. curr_node = soc_private->tree_node[i];
  1688. CAM_INFO(CAM_CPAS,
  1689. "[%s] Cell[%d] level[%d] PortIdx[%d][%d] camnoc_bw[%d %d %lld %lld] mnoc_bw[%lld %lld]",
  1690. curr_node->node_name, curr_node->cell_idx,
  1691. curr_node->level_idx, curr_node->axi_port_idx,
  1692. curr_node->camnoc_axi_port_idx,
  1693. curr_node->camnoc_max_needed,
  1694. curr_node->bus_width_factor,
  1695. curr_node->camnoc_bw,
  1696. curr_node->camnoc_bw * curr_node->bus_width_factor,
  1697. curr_node->mnoc_ab_bw, curr_node->mnoc_ib_bw);
  1698. }
  1699. cam_cpas_dump_monitor_array(cpas_core);
  1700. if (cpas_core->internal_ops.print_poweron_settings)
  1701. cpas_core->internal_ops.print_poweron_settings(cpas_hw);
  1702. else
  1703. CAM_DBG(CAM_CPAS, "No ops for print_poweron_settings");
  1704. return 0;
  1705. }
  1706. static void cam_cpas_update_monitor_array(struct cam_hw_info *cpas_hw,
  1707. const char *identifier_string, int32_t identifier_value)
  1708. {
  1709. struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
  1710. struct cam_camnoc_info *camnoc_info =
  1711. (struct cam_camnoc_info *) cpas_core->camnoc_info;
  1712. struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info;
  1713. struct cam_cpas_private_soc *soc_private =
  1714. (struct cam_cpas_private_soc *) cpas_hw->soc_info.soc_private;
  1715. struct cam_cpas_monitor *entry;
  1716. int iterator;
  1717. int i, j = 0;
  1718. int reg_camnoc = cpas_core->regbase_index[CAM_CPAS_REG_CAMNOC];
  1719. uint32_t val = 0;
  1720. if (!camnoc_info) {
  1721. CAM_ERR(CAM_CPAS, "Invalid camnoc info for hw_version: 0x%x",
  1722. cpas_hw->soc_info.hw_version);
  1723. return;
  1724. }
  1725. CAM_CPAS_INC_MONITOR_HEAD(&cpas_core->monitor_head, &iterator);
  1726. entry = &cpas_core->monitor_entries[iterator];
  1727. ktime_get_real_ts64(&entry->timestamp);
  1728. strlcpy(entry->identifier_string, identifier_string,
  1729. sizeof(entry->identifier_string));
  1730. entry->identifier_value = identifier_value;
  1731. for (i = 0; i < cpas_core->num_axi_ports; i++) {
  1732. entry->axi_info[i].axi_port_name =
  1733. cpas_core->axi_port[i].axi_port_name;
  1734. entry->axi_info[i].ab_bw = cpas_core->axi_port[i].ab_bw;
  1735. entry->axi_info[i].ib_bw = cpas_core->axi_port[i].ib_bw;
  1736. entry->axi_info[i].camnoc_bw = cpas_core->axi_port[i].camnoc_bw;
  1737. entry->axi_info[i].applied_ab_bw =
  1738. cpas_core->axi_port[i].applied_ab_bw;
  1739. entry->axi_info[i].applied_ib_bw =
  1740. cpas_core->axi_port[i].applied_ib_bw;
  1741. }
  1742. entry->applied_camnoc_clk = cpas_core->applied_camnoc_axi_rate;
  1743. entry->applied_ahb_level = cpas_core->ahb_bus_client.curr_vote_level;
  1744. if ((cpas_core->streamon_clients > 0) &&
  1745. (cpas_core->regbase_index[CAM_CPAS_REG_RPMH] != -1) &&
  1746. soc_private->rpmh_info[CAM_RPMH_NUMBER_OF_BCMS]) {
  1747. int reg_base_index =
  1748. cpas_core->regbase_index[CAM_CPAS_REG_RPMH];
  1749. void __iomem *rpmh_base =
  1750. soc_info->reg_map[reg_base_index].mem_base;
  1751. uint32_t fe_ddr_offset =
  1752. soc_private->rpmh_info[CAM_RPMH_BCM_FE_OFFSET] +
  1753. (0x4 * soc_private->rpmh_info[CAM_RPMH_BCM_DDR_INDEX]);
  1754. uint32_t fe_mnoc_offset =
  1755. soc_private->rpmh_info[CAM_RPMH_BCM_FE_OFFSET] +
  1756. (0x4 * soc_private->rpmh_info[CAM_RPMH_BCM_MNOC_INDEX]);
  1757. uint32_t be_ddr_offset =
  1758. soc_private->rpmh_info[CAM_RPMH_BCM_BE_OFFSET] +
  1759. (0x4 * soc_private->rpmh_info[CAM_RPMH_BCM_DDR_INDEX]);
  1760. uint32_t be_mnoc_offset =
  1761. soc_private->rpmh_info[CAM_RPMH_BCM_BE_OFFSET] +
  1762. (0x4 * soc_private->rpmh_info[CAM_RPMH_BCM_MNOC_INDEX]);
  1763. uint32_t be_shub_offset =
  1764. soc_private->rpmh_info[CAM_RPMH_BCM_BE_OFFSET] +
  1765. (0x4 * 1); /* i=1 for SHUB, hardcode for now */
  1766. /*
  1767. * 0x4, 0x800 - DDR
  1768. * 0x800, 0x810 - mmnoc
  1769. */
  1770. entry->fe_ddr = cam_io_r_mb(rpmh_base + fe_ddr_offset);
  1771. entry->fe_mnoc = cam_io_r_mb(rpmh_base + fe_mnoc_offset);
  1772. entry->be_ddr = cam_io_r_mb(rpmh_base + be_ddr_offset);
  1773. entry->be_mnoc = cam_io_r_mb(rpmh_base + be_mnoc_offset);
  1774. entry->be_shub = cam_io_r_mb(rpmh_base + be_shub_offset);
  1775. CAM_DBG(CAM_CPAS,
  1776. "fe_ddr=0x%x, fe_mnoc=0x%x, be_ddr=0x%x, be_mnoc=0x%x",
  1777. entry->fe_ddr, entry->fe_mnoc, entry->be_ddr,
  1778. entry->be_mnoc);
  1779. }
  1780. for (i = 0; i < camnoc_info->specific_size; i++) {
  1781. if ((!camnoc_info->specific[i].enable) ||
  1782. (!camnoc_info->specific[i].maxwr_low.enable))
  1783. continue;
  1784. if (j >= CAM_CAMNOC_FILL_LVL_REG_INFO_MAX) {
  1785. CAM_WARN(CAM_CPAS,
  1786. "CPAS monitor reg info buffer full, max : %d", j);
  1787. break;
  1788. }
  1789. entry->camnoc_port_name[j] = camnoc_info->specific[i].port_name;
  1790. val = cam_io_r_mb(soc_info->reg_map[reg_camnoc].mem_base +
  1791. camnoc_info->specific[i].maxwr_low.offset);
  1792. entry->camnoc_fill_level[j] = val;
  1793. j++;
  1794. }
  1795. entry->num_camnoc_lvl_regs = j;
  1796. }
  1797. static void cam_cpas_dump_monitor_array(
  1798. struct cam_cpas *cpas_core)
  1799. {
  1800. int i = 0, j = 0;
  1801. int64_t state_head = 0;
  1802. uint32_t index, num_entries, oldest_entry;
  1803. uint64_t ms, tmp, hrs, min, sec;
  1804. struct cam_cpas_monitor *entry;
  1805. struct timespec64 curr_timestamp;
  1806. char log_buf[CAM_CPAS_LOG_BUF_LEN];
  1807. size_t len;
  1808. if (!cpas_core->full_state_dump)
  1809. return;
  1810. state_head = atomic64_read(&cpas_core->monitor_head);
  1811. if (state_head == -1) {
  1812. CAM_WARN(CAM_CPAS, "No valid entries in cpas monitor array");
  1813. return;
  1814. } else if (state_head < CAM_CPAS_MONITOR_MAX_ENTRIES) {
  1815. num_entries = state_head;
  1816. oldest_entry = 0;
  1817. } else {
  1818. num_entries = CAM_CPAS_MONITOR_MAX_ENTRIES;
  1819. div_u64_rem(state_head + 1,
  1820. CAM_CPAS_MONITOR_MAX_ENTRIES, &oldest_entry);
  1821. }
  1822. ktime_get_real_ts64(&curr_timestamp);
  1823. tmp = curr_timestamp.tv_sec;
  1824. ms = (curr_timestamp.tv_nsec) / 1000000;
  1825. sec = do_div(tmp, 60);
  1826. min = do_div(tmp, 60);
  1827. hrs = do_div(tmp, 24);
  1828. CAM_INFO(CAM_CPAS,
  1829. "**** %llu:%llu:%llu.%llu : ======== Dumping monitor information ===========",
  1830. hrs, min, sec, ms);
  1831. index = oldest_entry;
  1832. for (i = 0; i < num_entries; i++) {
  1833. entry = &cpas_core->monitor_entries[index];
  1834. tmp = entry->timestamp.tv_sec;
  1835. ms = (entry->timestamp.tv_nsec) / 1000000;
  1836. sec = do_div(tmp, 60);
  1837. min = do_div(tmp, 60);
  1838. hrs = do_div(tmp, 24);
  1839. memset(log_buf, 0, sizeof(log_buf));
  1840. len = 0;
  1841. CAM_INFO(CAM_CPAS,
  1842. "**** %llu:%llu:%llu.%llu : Index[%d] Identifier[%s][%d] camnoc=%lld, ahb=%d",
  1843. hrs, min, sec, ms,
  1844. index,
  1845. entry->identifier_string, entry->identifier_value,
  1846. entry->applied_camnoc_clk, entry->applied_ahb_level);
  1847. for (j = 0; j < cpas_core->num_axi_ports; j++) {
  1848. CAM_INFO(CAM_CPAS,
  1849. "MNOC BW [%s] : ab=%lld, ib=%lld, camnoc=%lld",
  1850. entry->axi_info[j].axi_port_name,
  1851. entry->axi_info[j].applied_ab_bw,
  1852. entry->axi_info[j].applied_ib_bw,
  1853. entry->axi_info[j].camnoc_bw);
  1854. }
  1855. if (cpas_core->regbase_index[CAM_CPAS_REG_RPMH] != -1) {
  1856. CAM_INFO(CAM_CPAS,
  1857. "fe_ddr=0x%x, fe_mnoc=0x%x, be_ddr=0x%x, be_mnoc=0x%x, be_shub=0x%x",
  1858. entry->fe_ddr, entry->fe_mnoc,
  1859. entry->be_ddr, entry->be_mnoc, entry->be_shub);
  1860. }
  1861. for (j = 0; j < entry->num_camnoc_lvl_regs; j++) {
  1862. len += scnprintf((log_buf + len),
  1863. (CAM_CPAS_LOG_BUF_LEN - len), " %s:[%d %d]",
  1864. entry->camnoc_port_name[j],
  1865. (entry->camnoc_fill_level[j] & 0x7FF),
  1866. (entry->camnoc_fill_level[j] & 0x7F0000) >> 16);
  1867. }
  1868. CAM_INFO(CAM_CPAS, "CAMNOC REG[Queued Pending] %s", log_buf);
  1869. index = (index + 1) % CAM_CPAS_MONITOR_MAX_ENTRIES;
  1870. }
  1871. }
  1872. static int cam_cpas_log_event(struct cam_hw_info *cpas_hw,
  1873. const char *identifier_string, int32_t identifier_value)
  1874. {
  1875. cam_cpas_update_monitor_array(cpas_hw, identifier_string,
  1876. identifier_value);
  1877. return 0;
  1878. }
  1879. static int cam_cpas_select_qos(struct cam_hw_info *cpas_hw,
  1880. uint32_t selection_mask)
  1881. {
  1882. struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
  1883. int rc = 0;
  1884. mutex_lock(&cpas_hw->hw_mutex);
  1885. if (cpas_hw->hw_state == CAM_HW_STATE_POWER_UP) {
  1886. CAM_ERR(CAM_CPAS,
  1887. "Hw already in power up state, can't change QoS settings");
  1888. rc = -EINVAL;
  1889. goto done;
  1890. }
  1891. if (cpas_core->internal_ops.setup_qos_settings) {
  1892. rc = cpas_core->internal_ops.setup_qos_settings(cpas_hw,
  1893. selection_mask);
  1894. if (rc)
  1895. CAM_ERR(CAM_CPAS, "Failed in changing QoS %d", rc);
  1896. } else {
  1897. CAM_WARN(CAM_CPAS, "No ops for qos_settings");
  1898. }
  1899. done:
  1900. mutex_unlock(&cpas_hw->hw_mutex);
  1901. return rc;
  1902. }
  1903. static int cam_cpas_activate_cache(
  1904. struct cam_hw_info *cpas_hw,
  1905. struct cam_sys_cache_info *cache_info)
  1906. {
  1907. int rc = 0;
  1908. mutex_lock(&cpas_hw->hw_mutex);
  1909. cache_info->ref_cnt++;
  1910. if (cache_info->ref_cnt > 1) {
  1911. mutex_unlock(&cpas_hw->hw_mutex);
  1912. CAM_DBG(CAM_CPAS, "Cache: %s has already been activated cnt: %d",
  1913. cache_info->name, cache_info->ref_cnt);
  1914. return rc;
  1915. }
  1916. rc = llcc_slice_activate(cache_info->slic_desc);
  1917. if (rc) {
  1918. CAM_ERR(CAM_CPAS, "Failed to activate cache:%s",
  1919. cache_info->name);
  1920. goto end;
  1921. }
  1922. mutex_unlock(&cpas_hw->hw_mutex);
  1923. CAM_DBG(CAM_CPAS, "Activated cache:%s", cache_info->name);
  1924. return rc;
  1925. end:
  1926. cache_info->ref_cnt--;
  1927. mutex_unlock(&cpas_hw->hw_mutex);
  1928. return rc;
  1929. }
  1930. static int cam_cpas_deactivate_cache(
  1931. struct cam_hw_info *cpas_hw,
  1932. struct cam_sys_cache_info *cache_info)
  1933. {
  1934. int rc = 0;
  1935. mutex_lock(&cpas_hw->hw_mutex);
  1936. if (!cache_info->ref_cnt) {
  1937. mutex_unlock(&cpas_hw->hw_mutex);
  1938. CAM_ERR(CAM_CPAS, "Unbalanced deactivate");
  1939. return -EFAULT;
  1940. }
  1941. cache_info->ref_cnt--;
  1942. if (cache_info->ref_cnt) {
  1943. mutex_unlock(&cpas_hw->hw_mutex);
  1944. CAM_DBG(CAM_CPAS, "activate cnt for: %s non-zero: %d",
  1945. cache_info->name, cache_info->ref_cnt);
  1946. return rc;
  1947. }
  1948. rc = llcc_slice_deactivate(cache_info->slic_desc);
  1949. if (rc)
  1950. CAM_ERR(CAM_CPAS, "Failed to deactivate cache:%s",
  1951. cache_info->name);
  1952. mutex_unlock(&cpas_hw->hw_mutex);
  1953. CAM_DBG(CAM_CPAS, "De-activated cache:%s", cache_info->name);
  1954. return rc;
  1955. }
  1956. static inline int cam_cpas_validate_cache_type(
  1957. uint32_t num_caches, enum cam_sys_cache_config_types type)
  1958. {
  1959. if ((!num_caches) || (type < 0) || (type >= num_caches))
  1960. return -EINVAL;
  1961. else
  1962. return 0;
  1963. }
  1964. static int cam_cpas_get_slice_id(
  1965. struct cam_hw_info *cpas_hw,
  1966. enum cam_sys_cache_config_types type)
  1967. {
  1968. struct cam_cpas_private_soc *soc_private =
  1969. (struct cam_cpas_private_soc *)cpas_hw->soc_info.soc_private;
  1970. uint32_t num_caches = soc_private->num_caches;
  1971. int scid = -1, i;
  1972. if (cam_cpas_validate_cache_type(num_caches, type))
  1973. goto end;
  1974. for (i = 0; i < num_caches; i++) {
  1975. if (type == soc_private->llcc_info[i].type) {
  1976. scid = soc_private->llcc_info[i].scid;
  1977. CAM_DBG(CAM_CPAS, "Cache:%s type:%d scid:%d",
  1978. soc_private->llcc_info[i].name, type, scid);
  1979. break;
  1980. }
  1981. }
  1982. end:
  1983. return scid;
  1984. }
  1985. static int cam_cpas_activate_cache_slice(
  1986. struct cam_hw_info *cpas_hw,
  1987. enum cam_sys_cache_config_types type)
  1988. {
  1989. struct cam_cpas_private_soc *soc_private =
  1990. (struct cam_cpas_private_soc *)cpas_hw->soc_info.soc_private;
  1991. uint32_t num_caches = soc_private->num_caches;
  1992. int rc = 0, i;
  1993. CAM_DBG(CAM_CPAS, "Activate type: %d", type);
  1994. if (cam_cpas_validate_cache_type(num_caches, type))
  1995. goto end;
  1996. for (i = 0; i < num_caches; i++) {
  1997. if (type == soc_private->llcc_info[i].type)
  1998. rc = cam_cpas_activate_cache(cpas_hw,
  1999. &soc_private->llcc_info[i]);
  2000. }
  2001. end:
  2002. return rc;
  2003. }
  2004. static int cam_cpas_deactivate_cache_slice(
  2005. struct cam_hw_info *cpas_hw,
  2006. enum cam_sys_cache_config_types type)
  2007. {
  2008. struct cam_cpas_private_soc *soc_private =
  2009. (struct cam_cpas_private_soc *)cpas_hw->soc_info.soc_private;
  2010. uint32_t num_caches = soc_private->num_caches;
  2011. int rc = 0, i;
  2012. CAM_DBG(CAM_CPAS, "De-activate type: %d", type);
  2013. if (cam_cpas_validate_cache_type(num_caches, type))
  2014. goto end;
  2015. for (i = 0; i < num_caches; i++) {
  2016. if (type == soc_private->llcc_info[i].type)
  2017. rc = cam_cpas_deactivate_cache(cpas_hw,
  2018. &soc_private->llcc_info[i]);
  2019. }
  2020. end:
  2021. return rc;
  2022. }
  2023. static int cam_cpas_hw_process_cmd(void *hw_priv,
  2024. uint32_t cmd_type, void *cmd_args, uint32_t arg_size)
  2025. {
  2026. int rc = -EINVAL;
  2027. if (!hw_priv || !cmd_args ||
  2028. (cmd_type >= CAM_CPAS_HW_CMD_INVALID)) {
  2029. CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK %d",
  2030. hw_priv, cmd_args, cmd_type);
  2031. return -EINVAL;
  2032. }
  2033. switch (cmd_type) {
  2034. case CAM_CPAS_HW_CMD_REGISTER_CLIENT: {
  2035. struct cam_cpas_register_params *register_params;
  2036. if (sizeof(struct cam_cpas_register_params) != arg_size) {
  2037. CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d",
  2038. cmd_type, arg_size);
  2039. break;
  2040. }
  2041. register_params = (struct cam_cpas_register_params *)cmd_args;
  2042. rc = cam_cpas_hw_register_client(hw_priv, register_params);
  2043. break;
  2044. }
  2045. case CAM_CPAS_HW_CMD_UNREGISTER_CLIENT: {
  2046. uint32_t *client_handle;
  2047. if (sizeof(uint32_t) != arg_size) {
  2048. CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d",
  2049. cmd_type, arg_size);
  2050. break;
  2051. }
  2052. client_handle = (uint32_t *)cmd_args;
  2053. rc = cam_cpas_hw_unregister_client(hw_priv, *client_handle);
  2054. break;
  2055. }
  2056. case CAM_CPAS_HW_CMD_REG_WRITE: {
  2057. struct cam_cpas_hw_cmd_reg_read_write *reg_write;
  2058. if (sizeof(struct cam_cpas_hw_cmd_reg_read_write) !=
  2059. arg_size) {
  2060. CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d",
  2061. cmd_type, arg_size);
  2062. break;
  2063. }
  2064. reg_write =
  2065. (struct cam_cpas_hw_cmd_reg_read_write *)cmd_args;
  2066. rc = cam_cpas_hw_reg_write(hw_priv, reg_write->client_handle,
  2067. reg_write->reg_base, reg_write->offset, reg_write->mb,
  2068. reg_write->value);
  2069. break;
  2070. }
  2071. case CAM_CPAS_HW_CMD_REG_READ: {
  2072. struct cam_cpas_hw_cmd_reg_read_write *reg_read;
  2073. if (sizeof(struct cam_cpas_hw_cmd_reg_read_write) !=
  2074. arg_size) {
  2075. CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d",
  2076. cmd_type, arg_size);
  2077. break;
  2078. }
  2079. reg_read =
  2080. (struct cam_cpas_hw_cmd_reg_read_write *)cmd_args;
  2081. rc = cam_cpas_hw_reg_read(hw_priv,
  2082. reg_read->client_handle, reg_read->reg_base,
  2083. reg_read->offset, reg_read->mb, &reg_read->value);
  2084. break;
  2085. }
  2086. case CAM_CPAS_HW_CMD_AHB_VOTE: {
  2087. struct cam_cpas_hw_cmd_ahb_vote *cmd_ahb_vote;
  2088. if (sizeof(struct cam_cpas_hw_cmd_ahb_vote) != arg_size) {
  2089. CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d",
  2090. cmd_type, arg_size);
  2091. break;
  2092. }
  2093. cmd_ahb_vote = (struct cam_cpas_hw_cmd_ahb_vote *)cmd_args;
  2094. rc = cam_cpas_hw_update_ahb_vote(hw_priv,
  2095. cmd_ahb_vote->client_handle, cmd_ahb_vote->ahb_vote);
  2096. break;
  2097. }
  2098. case CAM_CPAS_HW_CMD_AXI_VOTE: {
  2099. struct cam_cpas_hw_cmd_axi_vote *cmd_axi_vote;
  2100. if (sizeof(struct cam_cpas_hw_cmd_axi_vote) != arg_size) {
  2101. CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d",
  2102. cmd_type, arg_size);
  2103. break;
  2104. }
  2105. cmd_axi_vote = (struct cam_cpas_hw_cmd_axi_vote *)cmd_args;
  2106. rc = cam_cpas_hw_update_axi_vote(hw_priv,
  2107. cmd_axi_vote->client_handle, cmd_axi_vote->axi_vote);
  2108. break;
  2109. }
  2110. case CAM_CPAS_HW_CMD_LOG_VOTE: {
  2111. rc = cam_cpas_log_vote(hw_priv);
  2112. break;
  2113. }
  2114. case CAM_CPAS_HW_CMD_LOG_EVENT: {
  2115. struct cam_cpas_hw_cmd_notify_event *event;
  2116. if (sizeof(struct cam_cpas_hw_cmd_notify_event) != arg_size) {
  2117. CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d",
  2118. cmd_type, arg_size);
  2119. break;
  2120. }
  2121. event = (struct cam_cpas_hw_cmd_notify_event *)cmd_args;
  2122. rc = cam_cpas_log_event(hw_priv, event->identifier_string,
  2123. event->identifier_value);
  2124. break;
  2125. }
  2126. case CAM_CPAS_HW_CMD_SELECT_QOS: {
  2127. uint32_t *selection_mask;
  2128. if (sizeof(uint32_t) != arg_size) {
  2129. CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d",
  2130. cmd_type, arg_size);
  2131. break;
  2132. }
  2133. selection_mask = (uint32_t *)cmd_args;
  2134. rc = cam_cpas_select_qos(hw_priv, *selection_mask);
  2135. break;
  2136. }
  2137. case CAM_CPAS_HW_CMD_GET_SCID: {
  2138. enum cam_sys_cache_config_types type;
  2139. if (sizeof(enum cam_sys_cache_config_types) != arg_size) {
  2140. CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d",
  2141. cmd_type, arg_size);
  2142. break;
  2143. }
  2144. type = *((enum cam_sys_cache_config_types *) cmd_args);
  2145. rc = cam_cpas_get_slice_id(hw_priv, type);
  2146. }
  2147. break;
  2148. case CAM_CPAS_HW_CMD_ACTIVATE_LLC: {
  2149. enum cam_sys_cache_config_types type;
  2150. if (sizeof(enum cam_sys_cache_config_types) != arg_size) {
  2151. CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d",
  2152. cmd_type, arg_size);
  2153. break;
  2154. }
  2155. type = *((enum cam_sys_cache_config_types *) cmd_args);
  2156. rc = cam_cpas_activate_cache_slice(hw_priv, type);
  2157. }
  2158. break;
  2159. case CAM_CPAS_HW_CMD_DEACTIVATE_LLC: {
  2160. enum cam_sys_cache_config_types type;
  2161. if (sizeof(enum cam_sys_cache_config_types) != arg_size) {
  2162. CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d",
  2163. cmd_type, arg_size);
  2164. break;
  2165. }
  2166. type = *((enum cam_sys_cache_config_types *) cmd_args);
  2167. rc = cam_cpas_deactivate_cache_slice(hw_priv, type);
  2168. }
  2169. break;
  2170. case CAM_CPAS_HW_CMD_DUMP_BUFF_FILL_INFO: {
  2171. uint32_t *client_handle;
  2172. if (sizeof(uint32_t) != arg_size) {
  2173. CAM_ERR(CAM_CPAS, "cmd_type %d, size mismatch %d",
  2174. cmd_type, arg_size);
  2175. break;
  2176. }
  2177. client_handle = (uint32_t *)cmd_args;
  2178. rc = cam_cpas_hw_dump_camnoc_buff_fill_info(hw_priv,
  2179. *client_handle);
  2180. break;
  2181. }
  2182. default:
  2183. CAM_ERR(CAM_CPAS, "CPAS HW command not valid =%d", cmd_type);
  2184. break;
  2185. }
  2186. return rc;
  2187. }
  2188. static int cam_cpas_util_client_setup(struct cam_hw_info *cpas_hw)
  2189. {
  2190. struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
  2191. int i;
  2192. for (i = 0; i < CAM_CPAS_MAX_CLIENTS; i++) {
  2193. mutex_init(&cpas_core->client_mutex[i]);
  2194. }
  2195. return 0;
  2196. }
  2197. int cam_cpas_util_client_cleanup(struct cam_hw_info *cpas_hw)
  2198. {
  2199. struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
  2200. int i;
  2201. for (i = 0; i < CAM_CPAS_MAX_CLIENTS; i++) {
  2202. if (cpas_core->cpas_client[i] &&
  2203. cpas_core->cpas_client[i]->registered) {
  2204. cam_cpas_hw_unregister_client(cpas_hw, i);
  2205. }
  2206. kfree(cpas_core->cpas_client[i]);
  2207. cpas_core->cpas_client[i] = NULL;
  2208. mutex_destroy(&cpas_core->client_mutex[i]);
  2209. }
  2210. return 0;
  2211. }
  2212. static int cam_cpas_util_get_internal_ops(struct platform_device *pdev,
  2213. struct cam_hw_intf *hw_intf, struct cam_cpas_internal_ops *internal_ops)
  2214. {
  2215. struct device_node *of_node = pdev->dev.of_node;
  2216. int rc;
  2217. const char *compat_str = NULL;
  2218. rc = of_property_read_string_index(of_node, "arch-compat", 0,
  2219. (const char **)&compat_str);
  2220. if (rc) {
  2221. CAM_ERR(CAM_CPAS, "failed to get arch-compat rc=%d", rc);
  2222. return -EINVAL;
  2223. }
  2224. if (strnstr(compat_str, "camss_top", strlen(compat_str))) {
  2225. hw_intf->hw_type = CAM_HW_CAMSSTOP;
  2226. rc = cam_camsstop_get_internal_ops(internal_ops);
  2227. } else if (strnstr(compat_str, "cpas_top", strlen(compat_str))) {
  2228. hw_intf->hw_type = CAM_HW_CPASTOP;
  2229. rc = cam_cpastop_get_internal_ops(internal_ops);
  2230. } else {
  2231. CAM_ERR(CAM_CPAS, "arch-compat %s not supported", compat_str);
  2232. rc = -EINVAL;
  2233. }
  2234. return rc;
  2235. }
  2236. static int cam_cpas_util_create_debugfs(struct cam_cpas *cpas_core)
  2237. {
  2238. int rc = 0;
  2239. struct dentry *dbgfileptr = NULL;
  2240. dbgfileptr = debugfs_create_dir("camera_cpas", NULL);
  2241. if (!dbgfileptr) {
  2242. CAM_ERR(CAM_CPAS,"DebugFS could not create directory!");
  2243. rc = -ENOENT;
  2244. goto end;
  2245. }
  2246. /* Store parent inode for cleanup in caller */
  2247. cpas_core->dentry = dbgfileptr;
  2248. dbgfileptr = debugfs_create_bool("ahb_bus_scaling_disable", 0644,
  2249. cpas_core->dentry, &cpas_core->ahb_bus_scaling_disable);
  2250. dbgfileptr = debugfs_create_bool("full_state_dump", 0644,
  2251. cpas_core->dentry, &cpas_core->full_state_dump);
  2252. if (IS_ERR(dbgfileptr)) {
  2253. if (PTR_ERR(dbgfileptr) == -ENODEV)
  2254. CAM_WARN(CAM_CPAS, "DebugFS not enabled in kernel!");
  2255. else
  2256. rc = PTR_ERR(dbgfileptr);
  2257. }
  2258. end:
  2259. return rc;
  2260. }
  2261. int cam_cpas_hw_probe(struct platform_device *pdev,
  2262. struct cam_hw_intf **hw_intf)
  2263. {
  2264. int rc = 0;
  2265. int i;
  2266. struct cam_hw_info *cpas_hw = NULL;
  2267. struct cam_hw_intf *cpas_hw_intf = NULL;
  2268. struct cam_cpas *cpas_core = NULL;
  2269. struct cam_cpas_private_soc *soc_private;
  2270. struct cam_cpas_internal_ops *internal_ops;
  2271. cpas_hw_intf = kzalloc(sizeof(struct cam_hw_intf), GFP_KERNEL);
  2272. if (!cpas_hw_intf)
  2273. return -ENOMEM;
  2274. cpas_hw = kzalloc(sizeof(struct cam_hw_info), GFP_KERNEL);
  2275. if (!cpas_hw) {
  2276. kfree(cpas_hw_intf);
  2277. return -ENOMEM;
  2278. }
  2279. cpas_core = kzalloc(sizeof(struct cam_cpas), GFP_KERNEL);
  2280. if (!cpas_core) {
  2281. kfree(cpas_hw);
  2282. kfree(cpas_hw_intf);
  2283. return -ENOMEM;
  2284. }
  2285. for (i = 0; i < CAM_CPAS_REG_MAX; i++)
  2286. cpas_core->regbase_index[i] = -1;
  2287. cpas_hw_intf->hw_priv = cpas_hw;
  2288. cpas_hw->core_info = cpas_core;
  2289. cpas_hw->hw_state = CAM_HW_STATE_POWER_DOWN;
  2290. cpas_hw->soc_info.pdev = pdev;
  2291. cpas_hw->soc_info.dev = &pdev->dev;
  2292. cpas_hw->soc_info.dev_name = pdev->name;
  2293. cpas_hw->open_count = 0;
  2294. cpas_core->ahb_bus_scaling_disable = false;
  2295. cpas_core->full_state_dump = false;
  2296. atomic64_set(&cpas_core->monitor_head, -1);
  2297. mutex_init(&cpas_hw->hw_mutex);
  2298. spin_lock_init(&cpas_hw->hw_lock);
  2299. init_completion(&cpas_hw->hw_complete);
  2300. cpas_hw_intf->hw_ops.get_hw_caps = cam_cpas_hw_get_hw_info;
  2301. cpas_hw_intf->hw_ops.init = cam_cpas_hw_init;
  2302. cpas_hw_intf->hw_ops.deinit = NULL;
  2303. cpas_hw_intf->hw_ops.reset = NULL;
  2304. cpas_hw_intf->hw_ops.reserve = NULL;
  2305. cpas_hw_intf->hw_ops.release = NULL;
  2306. cpas_hw_intf->hw_ops.start = cam_cpas_hw_start;
  2307. cpas_hw_intf->hw_ops.stop = cam_cpas_hw_stop;
  2308. cpas_hw_intf->hw_ops.read = NULL;
  2309. cpas_hw_intf->hw_ops.write = NULL;
  2310. cpas_hw_intf->hw_ops.process_cmd = cam_cpas_hw_process_cmd;
  2311. cpas_core->work_queue = alloc_workqueue("cam-cpas",
  2312. WQ_UNBOUND | WQ_MEM_RECLAIM, CAM_CPAS_INFLIGHT_WORKS);
  2313. if (!cpas_core->work_queue) {
  2314. rc = -ENOMEM;
  2315. goto release_mem;
  2316. }
  2317. internal_ops = &cpas_core->internal_ops;
  2318. rc = cam_cpas_util_get_internal_ops(pdev, cpas_hw_intf, internal_ops);
  2319. if (rc)
  2320. goto release_workq;
  2321. rc = cam_cpas_soc_init_resources(&cpas_hw->soc_info,
  2322. internal_ops->handle_irq, cpas_hw);
  2323. if (rc)
  2324. goto release_workq;
  2325. soc_private = (struct cam_cpas_private_soc *)
  2326. cpas_hw->soc_info.soc_private;
  2327. cpas_core->num_clients = soc_private->num_clients;
  2328. atomic_set(&cpas_core->irq_count, 0);
  2329. init_waitqueue_head(&cpas_core->irq_count_wq);
  2330. if (internal_ops->setup_regbase) {
  2331. rc = internal_ops->setup_regbase(&cpas_hw->soc_info,
  2332. cpas_core->regbase_index, CAM_CPAS_REG_MAX);
  2333. if (rc)
  2334. goto deinit_platform_res;
  2335. }
  2336. rc = cam_cpas_util_client_setup(cpas_hw);
  2337. if (rc) {
  2338. CAM_ERR(CAM_CPAS, "failed in client setup, rc=%d", rc);
  2339. goto deinit_platform_res;
  2340. }
  2341. rc = cam_cpas_util_register_bus_client(&cpas_hw->soc_info,
  2342. cpas_hw->soc_info.pdev->dev.of_node,
  2343. &cpas_core->ahb_bus_client);
  2344. if (rc) {
  2345. CAM_ERR(CAM_CPAS, "failed in ahb setup, rc=%d", rc);
  2346. goto client_cleanup;
  2347. }
  2348. rc = cam_cpas_util_axi_setup(cpas_core, &cpas_hw->soc_info);
  2349. if (rc) {
  2350. CAM_ERR(CAM_CPAS, "failed in axi setup, rc=%d", rc);
  2351. goto ahb_cleanup;
  2352. }
  2353. /* Need to vote first before enabling clocks */
  2354. rc = cam_cpas_util_vote_default_ahb_axi(cpas_hw, true);
  2355. if (rc)
  2356. goto axi_cleanup;
  2357. rc = cam_cpas_soc_enable_resources(&cpas_hw->soc_info, CAM_SVS_VOTE);
  2358. if (rc) {
  2359. CAM_ERR(CAM_CPAS, "failed in soc_enable_resources, rc=%d", rc);
  2360. goto remove_default_vote;
  2361. }
  2362. if (internal_ops->get_hw_info) {
  2363. rc = internal_ops->get_hw_info(cpas_hw, &cpas_core->hw_caps);
  2364. if (rc) {
  2365. CAM_ERR(CAM_CPAS, "failed in get_hw_info, rc=%d", rc);
  2366. goto disable_soc_res;
  2367. }
  2368. } else {
  2369. CAM_ERR(CAM_CPAS, "Invalid get_hw_info");
  2370. goto disable_soc_res;
  2371. }
  2372. rc = cam_cpas_hw_init(cpas_hw_intf->hw_priv,
  2373. &cpas_core->hw_caps, sizeof(struct cam_cpas_hw_caps));
  2374. if (rc)
  2375. goto disable_soc_res;
  2376. rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info, true, true);
  2377. if (rc) {
  2378. CAM_ERR(CAM_CPAS, "failed in soc_disable_resources, rc=%d", rc);
  2379. goto remove_default_vote;
  2380. }
  2381. rc = cam_cpas_util_vote_default_ahb_axi(cpas_hw, false);
  2382. if (rc)
  2383. goto axi_cleanup;
  2384. rc = cam_cpas_util_create_debugfs(cpas_core);
  2385. *hw_intf = cpas_hw_intf;
  2386. return 0;
  2387. disable_soc_res:
  2388. cam_cpas_soc_disable_resources(&cpas_hw->soc_info, true, true);
  2389. remove_default_vote:
  2390. cam_cpas_util_vote_default_ahb_axi(cpas_hw, false);
  2391. axi_cleanup:
  2392. cam_cpas_util_axi_cleanup(cpas_core, &cpas_hw->soc_info);
  2393. ahb_cleanup:
  2394. cam_cpas_util_unregister_bus_client(&cpas_core->ahb_bus_client);
  2395. client_cleanup:
  2396. cam_cpas_util_client_cleanup(cpas_hw);
  2397. cam_cpas_node_tree_cleanup(cpas_core, cpas_hw->soc_info.soc_private);
  2398. deinit_platform_res:
  2399. cam_cpas_soc_deinit_resources(&cpas_hw->soc_info);
  2400. release_workq:
  2401. flush_workqueue(cpas_core->work_queue);
  2402. destroy_workqueue(cpas_core->work_queue);
  2403. release_mem:
  2404. mutex_destroy(&cpas_hw->hw_mutex);
  2405. kfree(cpas_core);
  2406. kfree(cpas_hw);
  2407. kfree(cpas_hw_intf);
  2408. CAM_ERR(CAM_CPAS, "failed in hw probe");
  2409. return rc;
  2410. }
  2411. int cam_cpas_hw_remove(struct cam_hw_intf *cpas_hw_intf)
  2412. {
  2413. struct cam_hw_info *cpas_hw;
  2414. struct cam_cpas *cpas_core;
  2415. if (!cpas_hw_intf) {
  2416. CAM_ERR(CAM_CPAS, "cpas interface not initialized");
  2417. return -EINVAL;
  2418. }
  2419. cpas_hw = (struct cam_hw_info *)cpas_hw_intf->hw_priv;
  2420. cpas_core = (struct cam_cpas *)cpas_hw->core_info;
  2421. if (cpas_hw->hw_state == CAM_HW_STATE_POWER_UP) {
  2422. CAM_ERR(CAM_CPAS, "cpas hw is in power up state");
  2423. return -EINVAL;
  2424. }
  2425. cam_cpas_util_axi_cleanup(cpas_core, &cpas_hw->soc_info);
  2426. cam_cpas_node_tree_cleanup(cpas_core, cpas_hw->soc_info.soc_private);
  2427. cam_cpas_util_unregister_bus_client(&cpas_core->ahb_bus_client);
  2428. cam_cpas_util_client_cleanup(cpas_hw);
  2429. cam_cpas_soc_deinit_resources(&cpas_hw->soc_info);
  2430. debugfs_remove_recursive(cpas_core->dentry);
  2431. cpas_core->dentry = NULL;
  2432. flush_workqueue(cpas_core->work_queue);
  2433. destroy_workqueue(cpas_core->work_queue);
  2434. mutex_destroy(&cpas_hw->hw_mutex);
  2435. kfree(cpas_core);
  2436. kfree(cpas_hw);
  2437. kfree(cpas_hw_intf);
  2438. return 0;
  2439. }