cam_cpas_soc.c 22 KB

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