cam_cpas_hw.c 62 KB

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