cam_cdm_soc.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
  4. */
  5. #include <linux/delay.h>
  6. #include <linux/io.h>
  7. #include <linux/of.h>
  8. #include <linux/module.h>
  9. #include <linux/timer.h>
  10. #include <linux/kernel.h>
  11. #include "cam_soc_util.h"
  12. #include "cam_smmu_api.h"
  13. #include "cam_cdm.h"
  14. #include "cam_soc_util.h"
  15. #include "cam_io_util.h"
  16. #include "cam_cdm_soc.h"
  17. #define CAM_CDM_OFFSET_FROM_REG(x, y) ((x)->offsets[y].offset)
  18. #define CAM_CDM_ATTR_FROM_REG(x, y) ((x)->offsets[y].attribute)
  19. bool cam_cdm_read_hw_reg(struct cam_hw_info *cdm_hw,
  20. uint32_t reg, uint32_t *value)
  21. {
  22. void __iomem *reg_addr;
  23. void __iomem *base =
  24. cdm_hw->soc_info.reg_map[CAM_HW_CDM_BASE_INDEX].mem_base;
  25. resource_size_t mem_len =
  26. cdm_hw->soc_info.reg_map[CAM_HW_CDM_BASE_INDEX].size;
  27. CAM_DBG(CAM_CDM, "E: b=%pK blen=%d off=%x", (void __iomem *)base,
  28. (int)mem_len, reg);
  29. reg_addr = (base + reg);
  30. if (reg_addr > (base + mem_len)) {
  31. CAM_ERR_RATE_LIMIT(CAM_CDM,
  32. "Invalid mapped region %d", reg);
  33. goto permission_error;
  34. }
  35. *value = cam_io_r_mb(reg_addr);
  36. CAM_DBG(CAM_CDM, "X b=%pK off=%x val=%x",
  37. (void __iomem *)base, reg,
  38. *value);
  39. return false;
  40. permission_error:
  41. *value = 0;
  42. return true;
  43. }
  44. bool cam_cdm_write_hw_reg(struct cam_hw_info *cdm_hw,
  45. uint32_t reg, uint32_t value)
  46. {
  47. void __iomem *reg_addr;
  48. void __iomem *base =
  49. cdm_hw->soc_info.reg_map[CAM_HW_CDM_BASE_INDEX].mem_base;
  50. resource_size_t mem_len =
  51. cdm_hw->soc_info.reg_map[CAM_HW_CDM_BASE_INDEX].size;
  52. CAM_DBG(CAM_CDM, "E: b=%pK off=%x val=%x", (void __iomem *)base,
  53. reg, value);
  54. reg_addr = (base + reg);
  55. if (reg_addr > (base + mem_len)) {
  56. CAM_ERR_RATE_LIMIT(CAM_CDM,
  57. "Accessing invalid region:%d\n",
  58. reg);
  59. goto permission_error;
  60. }
  61. cam_io_w_mb(value, reg_addr);
  62. return false;
  63. permission_error:
  64. return true;
  65. }
  66. int cam_cdm_soc_load_dt_private(struct platform_device *pdev,
  67. struct cam_cdm_private_dt_data *cdm_pvt_data)
  68. {
  69. int i, rc = -EINVAL, num_fifo_entries = 0, num_clients = 0;
  70. num_clients = of_property_count_strings(
  71. pdev->dev.of_node, "cdm-client-names");
  72. if ((num_clients <= 0) ||
  73. (num_clients > CAM_PER_CDM_MAX_REGISTERED_CLIENTS)) {
  74. CAM_ERR(CAM_CDM, "Invalid count of client names count=%d",
  75. num_clients);
  76. rc = -EINVAL;
  77. goto end;
  78. }
  79. cdm_pvt_data->dt_num_supported_clients = (uint32_t)num_clients;
  80. CAM_DBG(CAM_CDM, "Num supported cdm_client = %u",
  81. cdm_pvt_data->dt_num_supported_clients);
  82. cdm_pvt_data->dt_cdm_shared = true;
  83. for (i = 0; i < cdm_pvt_data->dt_num_supported_clients; i++) {
  84. rc = of_property_read_string_index(pdev->dev.of_node,
  85. "cdm-client-names", i,
  86. &(cdm_pvt_data->dt_cdm_client_name[i]));
  87. CAM_DBG(CAM_CDM, "cdm-client-names[%d] = %s", i,
  88. cdm_pvt_data->dt_cdm_client_name[i]);
  89. if (rc < 0) {
  90. CAM_ERR(CAM_CDM,
  91. "Reading cdm-client-names failed for client: %d",
  92. i);
  93. goto end;
  94. }
  95. }
  96. cdm_pvt_data->is_single_ctx_cdm =
  97. of_property_read_bool(pdev->dev.of_node,
  98. "single-context-cdm");
  99. rc = of_property_read_u8(pdev->dev.of_node, "cdm-priority-group",
  100. &cdm_pvt_data->priority_group);
  101. if (rc < 0) {
  102. cdm_pvt_data->priority_group = 0;
  103. rc = 0;
  104. }
  105. cdm_pvt_data->config_fifo = of_property_read_bool(pdev->dev.of_node,
  106. "config-fifo");
  107. if (cdm_pvt_data->config_fifo) {
  108. num_fifo_entries = of_property_count_u32_elems(
  109. pdev->dev.of_node,
  110. "fifo-depths");
  111. if (num_fifo_entries != CAM_CDM_NUM_BL_FIFO) {
  112. CAM_ERR(CAM_CDM,
  113. "Wrong number of configurable FIFOs %d",
  114. num_fifo_entries);
  115. rc = -EINVAL;
  116. goto end;
  117. }
  118. for (i = 0; i < num_fifo_entries; i++) {
  119. rc = of_property_read_u32_index(pdev->dev.of_node,
  120. "fifo-depths", i, &cdm_pvt_data->fifo_depth[i]);
  121. if (rc < 0) {
  122. CAM_ERR(CAM_CDM,
  123. "Unable to read fifo-depth rc %d",
  124. rc);
  125. goto end;
  126. }
  127. CAM_DBG(CAM_CDM, "FIFO%d depth is %d",
  128. i, cdm_pvt_data->fifo_depth[i]);
  129. }
  130. } else {
  131. for (i = 0; i < CAM_CDM_BL_FIFO_MAX; i++) {
  132. cdm_pvt_data->fifo_depth[i] =
  133. CAM_CDM_BL_FIFO_LENGTH_MAX_DEFAULT;
  134. CAM_DBG(CAM_CDM, "FIFO%d depth is %d",
  135. i, cdm_pvt_data->fifo_depth[i]);
  136. }
  137. }
  138. end:
  139. return rc;
  140. }
  141. int cam_hw_cdm_soc_get_dt_properties(struct cam_hw_info *cdm_hw,
  142. const struct of_device_id *table)
  143. {
  144. int rc;
  145. struct cam_hw_soc_info *soc_ptr;
  146. const struct of_device_id *id;
  147. struct cam_cdm *cdm_core = NULL;
  148. if (!cdm_hw || (cdm_hw->soc_info.soc_private)
  149. || !(cdm_hw->soc_info.pdev))
  150. return -EINVAL;
  151. cdm_core = cdm_hw->core_info;
  152. soc_ptr = &cdm_hw->soc_info;
  153. rc = cam_soc_util_get_dt_properties(soc_ptr);
  154. if (rc != 0) {
  155. CAM_ERR(CAM_CDM, "Failed to retrieve the CDM dt properties");
  156. goto end;
  157. }
  158. soc_ptr->soc_private = kzalloc(
  159. sizeof(struct cam_cdm_private_dt_data),
  160. GFP_KERNEL);
  161. if (!soc_ptr->soc_private)
  162. return -ENOMEM;
  163. rc = cam_cdm_soc_load_dt_private(soc_ptr->pdev,
  164. soc_ptr->soc_private);
  165. if (rc != 0) {
  166. CAM_ERR(CAM_CDM, "Failed to load CDM dt private data");
  167. goto error;
  168. }
  169. id = of_match_node(table, soc_ptr->pdev->dev.of_node);
  170. if ((!id) || !(id->data)) {
  171. CAM_ERR(CAM_CDM, "Failed to retrieve the CDM id table");
  172. goto error;
  173. }
  174. cdm_core->offsets =
  175. (struct cam_cdm_hw_reg_offset *)id->data;
  176. CAM_DBG(CAM_CDM, "name %s", cdm_core->name);
  177. snprintf(cdm_core->name, sizeof(cdm_core->name), "%s%d",
  178. id->compatible, soc_ptr->index);
  179. CAM_DBG(CAM_CDM, "name %s", cdm_core->name);
  180. goto end;
  181. error:
  182. rc = -EINVAL;
  183. kfree(soc_ptr->soc_private);
  184. soc_ptr->soc_private = NULL;
  185. end:
  186. return rc;
  187. }
  188. int cam_cdm_intf_mgr_soc_get_dt_properties(
  189. struct platform_device *pdev, struct cam_cdm_intf_mgr *mgr)
  190. {
  191. int rc;
  192. rc = of_property_read_u32(pdev->dev.of_node,
  193. "num-hw-cdm", &mgr->dt_supported_hw_cdm);
  194. CAM_DBG(CAM_CDM, "Number of HW cdm supported =%d",
  195. mgr->dt_supported_hw_cdm);
  196. return rc;
  197. }