cam_cpas_hw.c 74 KB

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