cam_cpas_soc.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/device.h>
  6. #include <linux/of.h>
  7. #include <linux/module.h>
  8. #include <linux/kernel.h>
  9. #include <linux/platform_device.h>
  10. #include <linux/slab.h>
  11. #include "cam_cpas_api.h"
  12. #include "cam_cpas_hw_intf.h"
  13. #include "cam_cpas_hw.h"
  14. #include "cam_cpas_soc.h"
  15. static uint cpas_dump;
  16. module_param(cpas_dump, uint, 0644);
  17. void cam_cpas_dump_axi_vote_info(
  18. const struct cam_cpas_client *cpas_client,
  19. const char *identifier,
  20. struct cam_axi_vote *axi_vote)
  21. {
  22. int i;
  23. if (!cpas_dump)
  24. return;
  25. if (!axi_vote || (axi_vote->num_paths >
  26. CAM_CPAS_MAX_PATHS_PER_CLIENT)) {
  27. CAM_ERR(CAM_PERF, "Invalid num_paths %d",
  28. axi_vote ? axi_vote->num_paths : -1);
  29. return;
  30. }
  31. for (i = 0; i < axi_vote->num_paths; i++) {
  32. CAM_INFO(CAM_PERF,
  33. "Client [%s][%d] : [%s], Path=[%d] [%d], camnoc[%llu], mnoc_ab[%llu], mnoc_ib[%llu]",
  34. cpas_client->data.identifier, cpas_client->data.cell_index,
  35. identifier,
  36. axi_vote->axi_path[i].path_data_type,
  37. axi_vote->axi_path[i].transac_type,
  38. axi_vote->axi_path[i].camnoc_bw,
  39. axi_vote->axi_path[i].mnoc_ab_bw,
  40. axi_vote->axi_path[i].mnoc_ib_bw);
  41. }
  42. }
  43. void cam_cpas_util_debug_parse_data(
  44. struct cam_cpas_private_soc *soc_private)
  45. {
  46. int i, j;
  47. struct cam_cpas_tree_node *curr_node = NULL;
  48. if (!cpas_dump)
  49. return;
  50. for (i = 0; i < CAM_CPAS_MAX_TREE_NODES; i++) {
  51. if (!soc_private->tree_node[i])
  52. break;
  53. curr_node = soc_private->tree_node[i];
  54. CAM_INFO(CAM_CPAS,
  55. "NODE cell_idx: %d, level: %d, name: %s, axi_port_idx: %d, merge_type: %d, parent_name: %s",
  56. curr_node->cell_idx, curr_node->level_idx,
  57. curr_node->node_name, curr_node->axi_port_idx,
  58. curr_node->merge_type, curr_node->parent_node ?
  59. curr_node->parent_node->node_name : "no parent");
  60. if (curr_node->level_idx)
  61. continue;
  62. CAM_INFO(CAM_CPAS, "path_type: %d, transac_type: %s",
  63. curr_node->path_data_type,
  64. cam_cpas_axi_util_trans_type_to_string(
  65. curr_node->path_trans_type));
  66. for (j = 0; j < CAM_CPAS_PATH_DATA_MAX; j++) {
  67. CAM_INFO(CAM_CPAS, "Constituent path: %d",
  68. curr_node->constituent_paths[j] ? j : -1);
  69. }
  70. }
  71. CAM_INFO(CAM_CPAS, "NUMBER OF NODES PARSED: %d", i);
  72. }
  73. int cam_cpas_node_tree_cleanup(struct cam_cpas *cpas_core,
  74. struct cam_cpas_private_soc *soc_private)
  75. {
  76. int i = 0;
  77. for (i = 0; i < CAM_CPAS_MAX_TREE_NODES; i++) {
  78. if (soc_private->tree_node[i]) {
  79. of_node_put(soc_private->tree_node[i]->tree_dev_node);
  80. kfree(soc_private->tree_node[i]);
  81. soc_private->tree_node[i] = NULL;
  82. }
  83. }
  84. for (i = 0; i < CAM_CPAS_MAX_TREE_LEVELS; i++) {
  85. if (soc_private->level_node[i]) {
  86. of_node_put(soc_private->level_node[i]);
  87. soc_private->level_node[i] = NULL;
  88. }
  89. }
  90. if (soc_private->camera_bus_node) {
  91. of_node_put(soc_private->camera_bus_node);
  92. soc_private->camera_bus_node = NULL;
  93. }
  94. mutex_destroy(&cpas_core->tree_lock);
  95. return 0;
  96. }
  97. static int cam_cpas_util_path_type_to_idx(uint32_t *path_data_type)
  98. {
  99. if (*path_data_type >= CAM_CPAS_PATH_DATA_CONSO_OFFSET)
  100. *path_data_type = CAM_CPAS_MAX_GRAN_PATHS_PER_CLIENT +
  101. (*path_data_type % CAM_CPAS_MAX_GRAN_PATHS_PER_CLIENT);
  102. else
  103. *path_data_type %= CAM_CPAS_MAX_GRAN_PATHS_PER_CLIENT;
  104. if (*path_data_type >= CAM_CPAS_PATH_DATA_MAX) {
  105. CAM_ERR(CAM_CPAS, "index Invalid: %d", path_data_type);
  106. return -EINVAL;
  107. }
  108. return 0;
  109. }
  110. static int cam_cpas_parse_node_tree(struct cam_cpas *cpas_core,
  111. struct device_node *of_node, struct cam_cpas_private_soc *soc_private)
  112. {
  113. struct device_node *camera_bus_node;
  114. struct device_node *level_node;
  115. struct device_node *curr_node;
  116. struct device_node *parent_node;
  117. struct device_node *mnoc_node;
  118. int mnoc_idx = 0;
  119. uint32_t path_idx;
  120. bool camnoc_max_needed = false;
  121. struct cam_cpas_tree_node *curr_node_ptr = NULL;
  122. struct cam_cpas_client *curr_client = NULL;
  123. const char *client_name = NULL;
  124. uint32_t client_idx = 0, cell_idx = 0, level_idx = 0;
  125. int rc = 0, count = 0, i;
  126. camera_bus_node = of_find_node_by_name(of_node, "camera-bus-nodes");
  127. if (!camera_bus_node) {
  128. CAM_ERR(CAM_CPAS, "Camera Bus node not found in cpas DT node");
  129. return -EINVAL;
  130. }
  131. soc_private->camera_bus_node = camera_bus_node;
  132. for_each_available_child_of_node(camera_bus_node, level_node) {
  133. rc = of_property_read_u32(level_node, "level-index",
  134. &level_idx);
  135. if (rc) {
  136. CAM_ERR(CAM_CPAS, "Error reading level idx rc: %d", rc);
  137. return rc;
  138. }
  139. if (level_idx >= CAM_CPAS_MAX_TREE_LEVELS) {
  140. CAM_ERR(CAM_CPAS, "Invalid level idx: %d", level_idx);
  141. return -EINVAL;
  142. }
  143. soc_private->level_node[level_idx] = level_node;
  144. camnoc_max_needed = of_property_read_bool(level_node,
  145. "camnoc-max-needed");
  146. for_each_available_child_of_node(level_node, curr_node) {
  147. curr_node_ptr =
  148. kzalloc(sizeof(struct cam_cpas_tree_node),
  149. GFP_KERNEL);
  150. if (!curr_node_ptr)
  151. return -ENOMEM;
  152. curr_node_ptr->tree_dev_node = curr_node;
  153. rc = of_property_read_u32(curr_node, "cell-index",
  154. &curr_node_ptr->cell_idx);
  155. if (rc) {
  156. CAM_ERR(CAM_CPAS, "Node index not found");
  157. return rc;
  158. }
  159. if (curr_node_ptr->cell_idx >=
  160. CAM_CPAS_MAX_TREE_NODES) {
  161. CAM_ERR(CAM_CPAS, "Invalid cell idx: %d",
  162. cell_idx);
  163. return -EINVAL;
  164. }
  165. soc_private->tree_node[curr_node_ptr->cell_idx] =
  166. curr_node_ptr;
  167. curr_node_ptr->level_idx = level_idx;
  168. rc = of_property_read_string(curr_node, "node-name",
  169. &curr_node_ptr->node_name);
  170. if (rc) {
  171. CAM_ERR(CAM_CPAS,
  172. "failed to read node-name rc=%d",
  173. rc);
  174. return rc;
  175. }
  176. curr_node_ptr->camnoc_max_needed = camnoc_max_needed;
  177. rc = of_property_read_u32(curr_node, "bus-width-factor",
  178. &curr_node_ptr->bus_width_factor);
  179. if (rc)
  180. curr_node_ptr->bus_width_factor = 1;
  181. rc = of_property_read_u32(curr_node,
  182. "traffic-merge-type",
  183. &curr_node_ptr->merge_type);
  184. curr_node_ptr->axi_port_idx = -1;
  185. mnoc_node = of_find_node_by_name(curr_node,
  186. "qcom,axi-port-mnoc");
  187. if (mnoc_node) {
  188. if (mnoc_idx >= CAM_CPAS_MAX_AXI_PORTS)
  189. return -EINVAL;
  190. cpas_core->axi_port[mnoc_idx].axi_port_node
  191. = mnoc_node;
  192. if (soc_private->bus_icc_based) {
  193. struct of_phandle_args src_args = {0},
  194. dst_args = {0};
  195. rc = of_property_read_string(mnoc_node,
  196. "interconnect-names",
  197. &cpas_core->axi_port[mnoc_idx]
  198. .bus_client.common_data.name);
  199. if (rc) {
  200. CAM_ERR(CAM_CPAS,
  201. "failed to read interconnect-names rc=%d",
  202. rc);
  203. return rc;
  204. }
  205. rc = of_parse_phandle_with_args(
  206. mnoc_node, "interconnects",
  207. "#interconnect-cells", 0,
  208. &src_args);
  209. if (rc) {
  210. CAM_ERR(CAM_CPAS,
  211. "failed to read axi bus src info rc=%d",
  212. rc);
  213. return -EINVAL;
  214. }
  215. of_node_put(src_args.np);
  216. if (src_args.args_count != 1) {
  217. CAM_ERR(CAM_CPAS,
  218. "Invalid number of axi src args: %d",
  219. src_args.args_count);
  220. return -EINVAL;
  221. }
  222. cpas_core->axi_port[mnoc_idx].bus_client
  223. .common_data.src_id = src_args.args[0];
  224. rc = of_parse_phandle_with_args(
  225. mnoc_node, "interconnects",
  226. "#interconnect-cells", 1,
  227. &dst_args);
  228. if (rc) {
  229. CAM_ERR(CAM_CPAS,
  230. "failed to read axi bus dst info rc=%d",
  231. rc);
  232. return -EINVAL;
  233. }
  234. of_node_put(dst_args.np);
  235. if (dst_args.args_count != 1) {
  236. CAM_ERR(CAM_CPAS,
  237. "Invalid number of axi dst args: %d",
  238. dst_args.args_count);
  239. return -EINVAL;
  240. }
  241. cpas_core->axi_port[mnoc_idx].bus_client
  242. .common_data.dst_id = dst_args.args[0];
  243. cpas_core->axi_port[mnoc_idx].bus_client
  244. .common_data.num_usecases = 2;
  245. } else {
  246. rc = of_property_read_string(
  247. curr_node, "qcom,axi-port-name",
  248. &cpas_core->axi_port[mnoc_idx]
  249. .bus_client.common_data.name);
  250. if (rc) {
  251. CAM_ERR(CAM_CPAS,
  252. "failed to read mnoc-port-name rc=%d",
  253. rc);
  254. return rc;
  255. }
  256. }
  257. cpas_core->axi_port
  258. [mnoc_idx].ib_bw_voting_needed
  259. = of_property_read_bool(curr_node,
  260. "ib-bw-voting-needed");
  261. curr_node_ptr->axi_port_idx = mnoc_idx;
  262. mnoc_idx++;
  263. cpas_core->num_axi_ports++;
  264. }
  265. rc = of_property_read_string(curr_node,
  266. "client-name", &client_name);
  267. if (!rc) {
  268. rc = of_property_read_u32(curr_node,
  269. "traffic-data", &curr_node_ptr->path_data_type);
  270. if (rc) {
  271. CAM_ERR(CAM_CPAS,
  272. "Path Data type not found");
  273. return rc;
  274. }
  275. rc = cam_cpas_util_path_type_to_idx(
  276. &curr_node_ptr->path_data_type);
  277. if (rc)
  278. return rc;
  279. rc = of_property_read_u32(curr_node,
  280. "traffic-transaction-type",
  281. &curr_node_ptr->path_trans_type);
  282. if (rc) {
  283. CAM_ERR(CAM_CPAS,
  284. "Path Transac type not found");
  285. return rc;
  286. }
  287. if (curr_node_ptr->path_trans_type >=
  288. CAM_CPAS_TRANSACTION_MAX) {
  289. CAM_ERR(CAM_CPAS,
  290. "Invalid transac type: %d",
  291. curr_node_ptr->path_trans_type);
  292. return -EINVAL;
  293. }
  294. count = of_property_count_u32_elems(curr_node,
  295. "constituent-paths");
  296. for (i = 0; i < count; i++) {
  297. rc = of_property_read_u32_index(
  298. curr_node, "constituent-paths",
  299. i, &path_idx);
  300. if (rc) {
  301. CAM_ERR(CAM_CPAS,
  302. "No constituent path at %d", i);
  303. return rc;
  304. }
  305. rc = cam_cpas_util_path_type_to_idx(
  306. &path_idx);
  307. if (rc)
  308. return rc;
  309. curr_node_ptr->constituent_paths
  310. [path_idx] = true;
  311. }
  312. rc = cam_common_util_get_string_index(
  313. soc_private->client_name,
  314. soc_private->num_clients,
  315. client_name, &client_idx);
  316. if (rc) {
  317. CAM_ERR(CAM_CPAS,
  318. "client name not found in list: %s",
  319. client_name);
  320. return rc;
  321. }
  322. if (client_idx >= CAM_CPAS_MAX_CLIENTS)
  323. return -EINVAL;
  324. curr_client =
  325. cpas_core->cpas_client[client_idx];
  326. curr_client->tree_node_valid = true;
  327. curr_client->tree_node
  328. [curr_node_ptr->path_data_type]
  329. [curr_node_ptr->path_trans_type] =
  330. curr_node_ptr;
  331. CAM_DBG(CAM_CPAS,
  332. "CLIENT NODE ADDED: %d %d %s",
  333. curr_node_ptr->path_data_type,
  334. curr_node_ptr->path_trans_type,
  335. client_name);
  336. }
  337. parent_node = of_parse_phandle(curr_node,
  338. "parent-node", 0);
  339. if (parent_node) {
  340. of_property_read_u32(parent_node, "cell-index",
  341. &cell_idx);
  342. curr_node_ptr->parent_node =
  343. soc_private->tree_node[cell_idx];
  344. } else {
  345. CAM_DBG(CAM_CPAS,
  346. "no parent node at this level");
  347. }
  348. }
  349. }
  350. mutex_init(&cpas_core->tree_lock);
  351. cam_cpas_util_debug_parse_data(soc_private);
  352. return 0;
  353. }
  354. int cam_cpas_get_hw_features(struct platform_device *pdev,
  355. struct cam_cpas_private_soc *soc_private)
  356. {
  357. struct device_node *of_node;
  358. void *fuse;
  359. uint32_t fuse_addr, fuse_bit;
  360. uint32_t fuse_val = 0, feature_bit_pos;
  361. int count = 0, i = 0;
  362. of_node = pdev->dev.of_node;
  363. count = of_property_count_u32_elems(of_node, "cam_hw_fuse");
  364. for (i = 0; (i + 3) <= count; i = i + 3) {
  365. of_property_read_u32_index(of_node, "cam_hw_fuse", i,
  366. &feature_bit_pos);
  367. of_property_read_u32_index(of_node, "cam_hw_fuse", i + 1,
  368. &fuse_addr);
  369. of_property_read_u32_index(of_node, "cam_hw_fuse", i + 2,
  370. &fuse_bit);
  371. CAM_INFO(CAM_CPAS, "feature_bit 0x%x addr 0x%x, bit %d",
  372. feature_bit_pos, fuse_addr, fuse_bit);
  373. fuse = ioremap(fuse_addr, 4);
  374. if (fuse) {
  375. fuse_val = cam_io_r(fuse);
  376. if (fuse_val & BIT(fuse_bit))
  377. soc_private->feature_mask |= feature_bit_pos;
  378. else
  379. soc_private->feature_mask &= ~feature_bit_pos;
  380. }
  381. CAM_INFO(CAM_CPAS, "fuse %pK, fuse_val %x, feature_mask %x",
  382. fuse, fuse_val, soc_private->feature_mask);
  383. }
  384. return 0;
  385. }
  386. int cam_cpas_get_custom_dt_info(struct cam_hw_info *cpas_hw,
  387. struct platform_device *pdev, struct cam_cpas_private_soc *soc_private)
  388. {
  389. struct device_node *of_node;
  390. struct of_phandle_args src_args = {0}, dst_args = {0};
  391. int count = 0, i = 0, rc = 0, num_bw_values = 0, num_levels = 0;
  392. struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
  393. if (!soc_private || !pdev) {
  394. CAM_ERR(CAM_CPAS, "invalid input arg %pK %pK",
  395. soc_private, pdev);
  396. return -EINVAL;
  397. }
  398. of_node = pdev->dev.of_node;
  399. soc_private->feature_mask = 0xFFFFFFFF;
  400. rc = of_property_read_string(of_node, "arch-compat",
  401. &soc_private->arch_compat);
  402. if (rc) {
  403. CAM_ERR(CAM_CPAS, "device %s failed to read arch-compat",
  404. pdev->name);
  405. return rc;
  406. }
  407. cam_cpas_get_hw_features(pdev, soc_private);
  408. soc_private->camnoc_axi_min_ib_bw = 0;
  409. rc = of_property_read_u64(of_node,
  410. "camnoc-axi-min-ib-bw",
  411. &soc_private->camnoc_axi_min_ib_bw);
  412. if (rc == -EOVERFLOW) {
  413. soc_private->camnoc_axi_min_ib_bw = 0;
  414. rc = of_property_read_u32(of_node,
  415. "camnoc-axi-min-ib-bw",
  416. (u32 *)&soc_private->camnoc_axi_min_ib_bw);
  417. }
  418. if (rc) {
  419. CAM_DBG(CAM_CPAS,
  420. "failed to read camnoc-axi-min-ib-bw rc:%d", rc);
  421. soc_private->camnoc_axi_min_ib_bw =
  422. CAM_CPAS_AXI_MIN_CAMNOC_IB_BW;
  423. }
  424. CAM_DBG(CAM_CPAS, "camnoc-axi-min-ib-bw = %llu",
  425. soc_private->camnoc_axi_min_ib_bw);
  426. soc_private->client_id_based = of_property_read_bool(of_node,
  427. "client-id-based");
  428. soc_private->bus_icc_based = of_property_read_bool(of_node,
  429. "interconnects");
  430. if (soc_private->bus_icc_based) {
  431. rc = of_property_read_string(of_node, "interconnect-names",
  432. &cpas_core->ahb_bus_client.common_data.name);
  433. if (rc) {
  434. CAM_ERR(CAM_CPAS,
  435. "device %s failed to read interconnect-names",
  436. pdev->name);
  437. return rc;
  438. }
  439. rc = of_parse_phandle_with_args(of_node, "interconnects",
  440. "#interconnect-cells", 0, &src_args);
  441. if (rc) {
  442. CAM_ERR(CAM_CPAS,
  443. "device %s failed to read ahb bus src info",
  444. pdev->name);
  445. return rc;
  446. }
  447. of_node_put(src_args.np);
  448. if (src_args.args_count != 1) {
  449. CAM_ERR(CAM_CPAS,
  450. "Invalid number of ahb src args: %d",
  451. src_args.args_count);
  452. return -EINVAL;
  453. }
  454. cpas_core->ahb_bus_client.common_data.src_id = src_args.args[0];
  455. rc = of_parse_phandle_with_args(of_node, "interconnects",
  456. "#interconnect-cells", 1, &dst_args);
  457. if (rc) {
  458. CAM_ERR(CAM_CPAS,
  459. "device %s failed to read ahb bus dst info",
  460. pdev->name);
  461. return rc;
  462. }
  463. of_node_put(dst_args.np);
  464. if (dst_args.args_count != 1) {
  465. CAM_ERR(CAM_CPAS,
  466. "Invalid number of ahb dst args: %d",
  467. dst_args.args_count);
  468. return -EINVAL;
  469. }
  470. cpas_core->ahb_bus_client.common_data.dst_id = dst_args.args[0];
  471. rc = of_property_read_u32(of_node, "cam-ahb-num-cases",
  472. &cpas_core->ahb_bus_client.common_data.num_usecases);
  473. if (rc) {
  474. CAM_ERR(CAM_CPAS,
  475. "device %s failed to read ahb num usecases",
  476. pdev->name);
  477. return rc;
  478. }
  479. if (cpas_core->ahb_bus_client.common_data.num_usecases >
  480. CAM_SOC_BUS_MAX_NUM_USECASES) {
  481. CAM_ERR(CAM_UTIL, "Invalid number of usecases: %d",
  482. cpas_core->ahb_bus_client.common_data
  483. .num_usecases);
  484. return -EINVAL;
  485. }
  486. num_bw_values = of_property_count_u32_elems(of_node,
  487. "cam-ahb-bw-KBps");
  488. if (num_bw_values <= 0) {
  489. CAM_ERR(CAM_UTIL, "Error counting ahb bw values");
  490. return -EINVAL;
  491. }
  492. CAM_DBG(CAM_CPAS, "AHB: num bw values %d", num_bw_values);
  493. num_levels = (num_bw_values / 2);
  494. if (num_levels !=
  495. cpas_core->ahb_bus_client.common_data.num_usecases) {
  496. CAM_ERR(CAM_UTIL, "Invalid number of levels: %d",
  497. num_bw_values/2);
  498. return -EINVAL;
  499. }
  500. for (i = 0; i < num_levels; i++) {
  501. rc = of_property_read_u32_index(of_node,
  502. "cam-ahb-bw-KBps",
  503. (i * 2),
  504. (uint32_t *) &cpas_core->ahb_bus_client
  505. .common_data.bw_pair[i].ab);
  506. if (rc) {
  507. CAM_ERR(CAM_UTIL,
  508. "Error reading ab bw value, rc=%d",
  509. rc);
  510. return rc;
  511. }
  512. rc = of_property_read_u32_index(of_node,
  513. "cam-ahb-bw-KBps",
  514. ((i * 2) + 1),
  515. (uint32_t *) &cpas_core->ahb_bus_client
  516. .common_data.bw_pair[i].ib);
  517. if (rc) {
  518. CAM_ERR(CAM_UTIL,
  519. "Error reading ib bw value, rc=%d",
  520. rc);
  521. return rc;
  522. }
  523. CAM_DBG(CAM_CPAS,
  524. "AHB: Level: %d, ab_value %llu, ib_value: %llu",
  525. i, cpas_core->ahb_bus_client.common_data
  526. .bw_pair[i].ab, cpas_core->ahb_bus_client
  527. .common_data.bw_pair[i].ib);
  528. }
  529. }
  530. count = of_property_count_strings(of_node, "client-names");
  531. if (count <= 0) {
  532. CAM_ERR(CAM_CPAS, "no client-names found");
  533. count = 0;
  534. return -EINVAL;
  535. } else if (count > CAM_CPAS_MAX_CLIENTS) {
  536. CAM_ERR(CAM_CPAS, "Number of clients %d greater than max %d",
  537. count, CAM_CPAS_MAX_CLIENTS);
  538. count = 0;
  539. return -EINVAL;
  540. }
  541. soc_private->num_clients = count;
  542. CAM_DBG(CAM_CPAS,
  543. "arch-compat=%s, client_id_based = %d, num_clients=%d",
  544. soc_private->arch_compat, soc_private->client_id_based,
  545. soc_private->num_clients);
  546. for (i = 0; i < soc_private->num_clients; i++) {
  547. rc = of_property_read_string_index(of_node,
  548. "client-names", i, &soc_private->client_name[i]);
  549. if (rc) {
  550. CAM_ERR(CAM_CPAS, "no client-name at cnt=%d", i);
  551. return -EINVAL;
  552. }
  553. cpas_core->cpas_client[i] =
  554. kzalloc(sizeof(struct cam_cpas_client), GFP_KERNEL);
  555. if (!cpas_core->cpas_client[i]) {
  556. rc = -ENOMEM;
  557. goto cleanup_clients;
  558. }
  559. CAM_DBG(CAM_CPAS, "Client[%d] : %s", i,
  560. soc_private->client_name[i]);
  561. }
  562. soc_private->control_camnoc_axi_clk = of_property_read_bool(of_node,
  563. "control-camnoc-axi-clk");
  564. if (soc_private->control_camnoc_axi_clk == true) {
  565. rc = of_property_read_u32(of_node, "camnoc-bus-width",
  566. &soc_private->camnoc_bus_width);
  567. if (rc || (soc_private->camnoc_bus_width == 0)) {
  568. CAM_ERR(CAM_CPAS, "Bus width not found rc=%d, %d",
  569. rc, soc_private->camnoc_bus_width);
  570. goto cleanup_clients;
  571. }
  572. rc = of_property_read_u32(of_node,
  573. "camnoc-axi-clk-bw-margin-perc",
  574. &soc_private->camnoc_axi_clk_bw_margin);
  575. if (rc) {
  576. /* this is not fatal, overwrite rc */
  577. rc = 0;
  578. soc_private->camnoc_axi_clk_bw_margin = 0;
  579. }
  580. }
  581. CAM_DBG(CAM_CPAS,
  582. "control_camnoc_axi_clk=%d, width=%d, margin=%d",
  583. soc_private->control_camnoc_axi_clk,
  584. soc_private->camnoc_bus_width,
  585. soc_private->camnoc_axi_clk_bw_margin);
  586. count = of_property_count_u32_elems(of_node, "vdd-corners");
  587. if ((count > 0) && (count <= CAM_REGULATOR_LEVEL_MAX) &&
  588. (of_property_count_strings(of_node, "vdd-corner-ahb-mapping") ==
  589. count)) {
  590. const char *ahb_string;
  591. for (i = 0; i < count; i++) {
  592. rc = of_property_read_u32_index(of_node, "vdd-corners",
  593. i, &soc_private->vdd_ahb[i].vdd_corner);
  594. if (rc) {
  595. CAM_ERR(CAM_CPAS,
  596. "vdd-corners failed at index=%d", i);
  597. rc = -ENODEV;
  598. goto cleanup_clients;
  599. }
  600. rc = of_property_read_string_index(of_node,
  601. "vdd-corner-ahb-mapping", i, &ahb_string);
  602. if (rc) {
  603. CAM_ERR(CAM_CPAS,
  604. "no ahb-mapping at index=%d", i);
  605. rc = -ENODEV;
  606. goto cleanup_clients;
  607. }
  608. rc = cam_soc_util_get_level_from_string(ahb_string,
  609. &soc_private->vdd_ahb[i].ahb_level);
  610. if (rc) {
  611. CAM_ERR(CAM_CPAS,
  612. "invalid ahb-string at index=%d", i);
  613. rc = -EINVAL;
  614. goto cleanup_clients;
  615. }
  616. CAM_DBG(CAM_CPAS,
  617. "Vdd-AHB mapping [%d] : [%d] [%s] [%d]", i,
  618. soc_private->vdd_ahb[i].vdd_corner,
  619. ahb_string, soc_private->vdd_ahb[i].ahb_level);
  620. }
  621. soc_private->num_vdd_ahb_mapping = count;
  622. }
  623. rc = cam_cpas_parse_node_tree(cpas_core, of_node, soc_private);
  624. if (rc) {
  625. CAM_ERR(CAM_CPAS, "Node tree parsing failed rc: %d", rc);
  626. goto cleanup_tree;
  627. }
  628. return 0;
  629. cleanup_tree:
  630. cam_cpas_node_tree_cleanup(cpas_core, soc_private);
  631. cleanup_clients:
  632. cam_cpas_util_client_cleanup(cpas_hw);
  633. return rc;
  634. }
  635. int cam_cpas_soc_init_resources(struct cam_hw_soc_info *soc_info,
  636. irq_handler_t irq_handler, struct cam_hw_info *cpas_hw)
  637. {
  638. int rc = 0;
  639. rc = cam_soc_util_get_dt_properties(soc_info);
  640. if (rc) {
  641. CAM_ERR(CAM_CPAS, "failed in get_dt_properties, rc=%d", rc);
  642. return rc;
  643. }
  644. if (soc_info->irq_line && !irq_handler) {
  645. CAM_ERR(CAM_CPAS, "Invalid IRQ handler");
  646. return -EINVAL;
  647. }
  648. rc = cam_soc_util_request_platform_resource(soc_info, irq_handler,
  649. cpas_hw);
  650. if (rc) {
  651. CAM_ERR(CAM_CPAS, "failed in request_platform_resource, rc=%d",
  652. rc);
  653. return rc;
  654. }
  655. soc_info->soc_private = kzalloc(sizeof(struct cam_cpas_private_soc),
  656. GFP_KERNEL);
  657. if (!soc_info->soc_private) {
  658. rc = -ENOMEM;
  659. goto release_res;
  660. }
  661. rc = cam_cpas_get_custom_dt_info(cpas_hw, soc_info->pdev,
  662. soc_info->soc_private);
  663. if (rc) {
  664. CAM_ERR(CAM_CPAS, "failed in get_custom_info, rc=%d", rc);
  665. goto free_soc_private;
  666. }
  667. return rc;
  668. free_soc_private:
  669. kfree(soc_info->soc_private);
  670. release_res:
  671. cam_soc_util_release_platform_resource(soc_info);
  672. return rc;
  673. }
  674. int cam_cpas_soc_deinit_resources(struct cam_hw_soc_info *soc_info)
  675. {
  676. int rc;
  677. rc = cam_soc_util_release_platform_resource(soc_info);
  678. if (rc)
  679. CAM_ERR(CAM_CPAS, "release platform failed, rc=%d", rc);
  680. kfree(soc_info->soc_private);
  681. soc_info->soc_private = NULL;
  682. return rc;
  683. }
  684. int cam_cpas_soc_enable_resources(struct cam_hw_soc_info *soc_info,
  685. enum cam_vote_level default_level)
  686. {
  687. int rc = 0;
  688. rc = cam_soc_util_enable_platform_resource(soc_info, true,
  689. default_level, true);
  690. if (rc)
  691. CAM_ERR(CAM_CPAS, "enable platform resource failed, rc=%d", rc);
  692. return rc;
  693. }
  694. int cam_cpas_soc_disable_resources(struct cam_hw_soc_info *soc_info,
  695. bool disable_clocks, bool disable_irq)
  696. {
  697. int rc = 0;
  698. rc = cam_soc_util_disable_platform_resource(soc_info,
  699. disable_clocks, disable_irq);
  700. if (rc)
  701. CAM_ERR(CAM_CPAS, "disable platform failed, rc=%d", rc);
  702. return rc;
  703. }
  704. int cam_cpas_soc_disable_irq(struct cam_hw_soc_info *soc_info)
  705. {
  706. int rc = 0;
  707. rc = cam_soc_util_irq_disable(soc_info);
  708. if (rc)
  709. CAM_ERR(CAM_CPAS, "disable irq failed, rc=%d", rc);
  710. return rc;
  711. }