hw_fence_drv_ipc.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  4. */
  5. #include <linux/of_platform.h>
  6. #include "hw_fence_drv_priv.h"
  7. #include "hw_fence_drv_utils.h"
  8. #include "hw_fence_drv_ipc.h"
  9. #include "hw_fence_drv_debug.h"
  10. /*
  11. * Max size of base table with ipc mappings, with one mapping per client type with configurable
  12. * number of subclients
  13. */
  14. #define HW_FENCE_IPC_MAP_MAX (HW_FENCE_MAX_STATIC_CLIENTS_INDEX + \
  15. HW_FENCE_MAX_CLIENT_TYPE_CONFIGURABLE)
  16. /**
  17. * struct hw_fence_client_ipc_map - map client id with ipc signal for trigger.
  18. * @ipc_client_id_virt: virtual ipc client id for the hw-fence client.
  19. * @ipc_client_id_phys: physical ipc client id for the hw-fence client.
  20. * @ipc_signal_id: ipc signal id for the hw-fence client.
  21. * @update_rxq: bool to indicate if clinet uses rx-queue.
  22. * @send_ipc: bool to indicate if client requires ipc interrupt for signaled fences
  23. */
  24. struct hw_fence_client_ipc_map {
  25. int ipc_client_id_virt;
  26. int ipc_client_id_phys;
  27. int ipc_signal_id;
  28. bool update_rxq;
  29. bool send_ipc;
  30. };
  31. /**
  32. * struct hw_fence_clients_ipc_map_no_dpu - Table makes the 'client to signal' mapping, which
  33. * is used by the hw fence driver to trigger ipc signal when the hw fence is already
  34. * signaled.
  35. * This no_dpu version is for targets that do not support dpu client id
  36. *
  37. * Notes:
  38. * The index of this struct must match the enum hw_fence_client_id.
  39. * To change to a loopback signal instead of GMU, change ctx0 row to use:
  40. * {HW_FENCE_IPC_CLIENT_ID_APPS, 20}.
  41. */
  42. struct hw_fence_client_ipc_map hw_fence_clients_ipc_map_no_dpu[HW_FENCE_IPC_MAP_MAX] = {
  43. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 1, true, true},/* ctrlq*/
  44. {HW_FENCE_IPC_CLIENT_ID_GPU_VID, HW_FENCE_IPC_CLIENT_ID_GPU_VID, 0, false, false},/* ctx0 */
  45. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 14, false, true},/*ctl0*/
  46. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 15, false, true},/*ctl1*/
  47. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 16, false, true},/*ctl2*/
  48. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 17, false, true},/*ctl3*/
  49. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 18, false, true},/*ctl4*/
  50. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 19, false, true},/*ctl5*/
  51. #if IS_ENABLED(CONFIG_DEBUG_FS)
  52. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 21, true, false},/*val0*/
  53. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 22, true, false},/*val1*/
  54. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 23, true, false},/*val2*/
  55. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 24, true, false},/*val3*/
  56. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 25, true, false},/*val4*/
  57. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 26, true, false},/*val5*/
  58. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 27, true, false},/*val6*/
  59. #endif /* CONFIG_DEBUG_FS */
  60. };
  61. /**
  62. * struct hw_fence_clients_ipc_map - Table makes the 'client to signal' mapping, which is
  63. * used by the hw fence driver to trigger ipc signal when hw fence is already
  64. * signaled.
  65. * This version is for targets that support dpu client id.
  66. *
  67. * Note that the index of this struct must match the enum hw_fence_client_id
  68. */
  69. struct hw_fence_client_ipc_map hw_fence_clients_ipc_map[HW_FENCE_IPC_MAP_MAX] = {
  70. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 1, true, true},/*ctrl q*/
  71. {HW_FENCE_IPC_CLIENT_ID_GPU_VID, HW_FENCE_IPC_CLIENT_ID_GPU_VID, 0, false, false},/*ctx0 */
  72. {HW_FENCE_IPC_CLIENT_ID_DPU_VID, HW_FENCE_IPC_CLIENT_ID_DPU_VID, 0, false, true},/* ctl0 */
  73. {HW_FENCE_IPC_CLIENT_ID_DPU_VID, HW_FENCE_IPC_CLIENT_ID_DPU_VID, 1, false, true},/* ctl1 */
  74. {HW_FENCE_IPC_CLIENT_ID_DPU_VID, HW_FENCE_IPC_CLIENT_ID_DPU_VID, 2, false, true},/* ctl2 */
  75. {HW_FENCE_IPC_CLIENT_ID_DPU_VID, HW_FENCE_IPC_CLIENT_ID_DPU_VID, 3, false, true},/* ctl3 */
  76. {HW_FENCE_IPC_CLIENT_ID_DPU_VID, HW_FENCE_IPC_CLIENT_ID_DPU_VID, 4, false, true},/* ctl4 */
  77. {HW_FENCE_IPC_CLIENT_ID_DPU_VID, HW_FENCE_IPC_CLIENT_ID_DPU_VID, 5, false, true},/* ctl5 */
  78. #if IS_ENABLED(CONFIG_DEBUG_FS)
  79. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 21, true, false},/*val0*/
  80. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 22, true, false},/*val1*/
  81. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 23, true, false},/*val2*/
  82. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 24, true, false},/*val3*/
  83. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 25, true, false},/*val4*/
  84. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 26, true, false},/*val5*/
  85. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_VID, 27, true, false},/*val6*/
  86. #else
  87. {0, 0, 0, false, false}, /* val0 */
  88. {0, 0, 0, false, false}, /* val1 */
  89. {0, 0, 0, false, false}, /* val2 */
  90. {0, 0, 0, false, false}, /* val3 */
  91. {0, 0, 0, false, false}, /* val4 */
  92. {0, 0, 0, false, false}, /* val5 */
  93. {0, 0, 0, false, false}, /* val6 */
  94. #endif /* CONFIG_DEBUG_FS */
  95. {HW_FENCE_IPC_CLIENT_ID_IPE_VID, HW_FENCE_IPC_CLIENT_ID_IPE_VID, 0, true, true}, /* ipe */
  96. {HW_FENCE_IPC_CLIENT_ID_VPU_VID, HW_FENCE_IPC_CLIENT_ID_VPU_VID, 0, true, true}, /* vpu */
  97. };
  98. /**
  99. * struct hw_fence_clients_ipc_map_v2 - Table makes the 'client to signal' mapping, which is
  100. * used by the hw fence driver to trigger ipc signal when hw fence is already
  101. * signaled.
  102. * This version is for targets that support dpu client id and IPC v2.
  103. *
  104. * Note that the index of this struct must match the enum hw_fence_client_id for clients ids less
  105. * than HW_FENCE_MAX_STATIC_CLIENTS_INDEX.
  106. * For clients with configurable sub-clients, the index of this struct matches
  107. * HW_FENCE_MAX_STATIC_CLIENTS_INDEX + (client type index - HW_FENCE_MAX_CLIENT_TYPE_STATIC).
  108. */
  109. struct hw_fence_client_ipc_map hw_fence_clients_ipc_map_v2[HW_FENCE_IPC_MAP_MAX] = {
  110. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_PID, 1, true, true},/*ctrlq */
  111. {HW_FENCE_IPC_CLIENT_ID_GPU_VID, HW_FENCE_IPC_CLIENT_ID_GPU_PID, 0, false, false},/* ctx0*/
  112. {HW_FENCE_IPC_CLIENT_ID_DPU_VID, HW_FENCE_IPC_CLIENT_ID_DPU_PID, 0, false, true},/* ctl0 */
  113. {HW_FENCE_IPC_CLIENT_ID_DPU_VID, HW_FENCE_IPC_CLIENT_ID_DPU_PID, 1, false, true},/* ctl1 */
  114. {HW_FENCE_IPC_CLIENT_ID_DPU_VID, HW_FENCE_IPC_CLIENT_ID_DPU_PID, 2, false, true},/* ctl2 */
  115. {HW_FENCE_IPC_CLIENT_ID_DPU_VID, HW_FENCE_IPC_CLIENT_ID_DPU_PID, 3, false, true},/* ctl3 */
  116. {HW_FENCE_IPC_CLIENT_ID_DPU_VID, HW_FENCE_IPC_CLIENT_ID_DPU_PID, 4, false, true},/* ctl4 */
  117. {HW_FENCE_IPC_CLIENT_ID_DPU_VID, HW_FENCE_IPC_CLIENT_ID_DPU_PID, 5, false, true},/* ctl5 */
  118. #if IS_ENABLED(CONFIG_DEBUG_FS)
  119. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_PID, 21, true, false},/*val0*/
  120. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_PID, 22, true, false},/*val1*/
  121. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_PID, 23, true, false},/*val2*/
  122. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_PID, 24, true, false},/*val3*/
  123. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_PID, 25, true, false},/*val4*/
  124. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_PID, 26, true, false},/*val5*/
  125. {HW_FENCE_IPC_CLIENT_ID_APPS_VID, HW_FENCE_IPC_CLIENT_ID_APPS_PID, 27, true, false},/*val6*/
  126. #else
  127. {0, 0, 0, false, false}, /* val0 */
  128. {0, 0, 0, false, false}, /* val1 */
  129. {0, 0, 0, false, false}, /* val2 */
  130. {0, 0, 0, false, false}, /* val3 */
  131. {0, 0, 0, false, false}, /* val4 */
  132. {0, 0, 0, false, false}, /* val5 */
  133. {0, 0, 0, false, false}, /* val6 */
  134. #endif /* CONFIG_DEBUG_FS */
  135. {HW_FENCE_IPC_CLIENT_ID_IPE_VID, HW_FENCE_IPC_CLIENT_ID_IPE_PID, 0, true, true}, /* ipe */
  136. {HW_FENCE_IPC_CLIENT_ID_VPU_VID, HW_FENCE_IPC_CLIENT_ID_VPU_PID, 0, true, true}, /* vpu */
  137. {HW_FENCE_IPC_CLIENT_ID_IFE0_VID, HW_FENCE_IPC_CLIENT_ID_IFE0_PID, 0, false, true},/* ife0*/
  138. {HW_FENCE_IPC_CLIENT_ID_IFE1_VID, HW_FENCE_IPC_CLIENT_ID_IFE1_PID, 0, false, true},/* ife1*/
  139. {HW_FENCE_IPC_CLIENT_ID_IFE2_VID, HW_FENCE_IPC_CLIENT_ID_IFE2_PID, 0, false, true},/* ife2*/
  140. {HW_FENCE_IPC_CLIENT_ID_IFE3_VID, HW_FENCE_IPC_CLIENT_ID_IFE3_PID, 0, false, true},/* ife3*/
  141. {HW_FENCE_IPC_CLIENT_ID_IFE4_VID, HW_FENCE_IPC_CLIENT_ID_IFE4_PID, 0, false, true},/* ife4*/
  142. {HW_FENCE_IPC_CLIENT_ID_IFE5_VID, HW_FENCE_IPC_CLIENT_ID_IFE5_PID, 0, false, true},/* ife5*/
  143. {HW_FENCE_IPC_CLIENT_ID_IFE6_VID, HW_FENCE_IPC_CLIENT_ID_IFE6_PID, 0, false, true},/* ife6*/
  144. {HW_FENCE_IPC_CLIENT_ID_IFE7_VID, HW_FENCE_IPC_CLIENT_ID_IFE7_PID, 0, false, true},/* ife7*/
  145. };
  146. int hw_fence_ipcc_get_client_virt_id(struct hw_fence_driver_data *drv_data, u32 client_id)
  147. {
  148. if (!drv_data || client_id >= drv_data->clients_num)
  149. return -EINVAL;
  150. return drv_data->ipc_clients_table[client_id].ipc_client_id_virt;
  151. }
  152. int hw_fence_ipcc_get_client_phys_id(struct hw_fence_driver_data *drv_data, u32 client_id)
  153. {
  154. if (!drv_data || client_id >= drv_data->clients_num)
  155. return -EINVAL;
  156. return drv_data->ipc_clients_table[client_id].ipc_client_id_phys;
  157. }
  158. int hw_fence_ipcc_get_signal_id(struct hw_fence_driver_data *drv_data, u32 client_id)
  159. {
  160. if (!drv_data || client_id >= drv_data->clients_num)
  161. return -EINVAL;
  162. return drv_data->ipc_clients_table[client_id].ipc_signal_id;
  163. }
  164. bool hw_fence_ipcc_needs_rxq_update(struct hw_fence_driver_data *drv_data, int client_id)
  165. {
  166. if (!drv_data || client_id >= drv_data->clients_num)
  167. return false;
  168. return drv_data->ipc_clients_table[client_id].update_rxq;
  169. }
  170. bool hw_fence_ipcc_needs_ipc_irq(struct hw_fence_driver_data *drv_data, int client_id)
  171. {
  172. if (!drv_data || client_id >= HW_FENCE_CLIENT_MAX)
  173. return false;
  174. return drv_data->ipc_clients_table[client_id].send_ipc;
  175. }
  176. /**
  177. * _get_ipc_phys_client_name() - Returns ipc client name from its physical id, used for debugging.
  178. */
  179. static inline char *_get_ipc_phys_client_name(u32 client_id)
  180. {
  181. switch (client_id) {
  182. case HW_FENCE_IPC_CLIENT_ID_APPS_PID:
  183. return "APPS_PID";
  184. case HW_FENCE_IPC_CLIENT_ID_GPU_PID:
  185. return "GPU_PID";
  186. case HW_FENCE_IPC_CLIENT_ID_DPU_PID:
  187. return "DPU_PID";
  188. case HW_FENCE_IPC_CLIENT_ID_IPE_PID:
  189. return "IPE_PID";
  190. case HW_FENCE_IPC_CLIENT_ID_VPU_PID:
  191. return "VPU_PID";
  192. case HW_FENCE_IPC_CLIENT_ID_IFE0_PID:
  193. return "IFE0_PID";
  194. case HW_FENCE_IPC_CLIENT_ID_IFE1_PID:
  195. return "IFE1_PID";
  196. case HW_FENCE_IPC_CLIENT_ID_IFE2_PID:
  197. return "IFE2_PID";
  198. case HW_FENCE_IPC_CLIENT_ID_IFE3_PID:
  199. return "IFE3_PID";
  200. case HW_FENCE_IPC_CLIENT_ID_IFE4_PID:
  201. return "IFE4_PID";
  202. case HW_FENCE_IPC_CLIENT_ID_IFE5_PID:
  203. return "IFE5_PID";
  204. case HW_FENCE_IPC_CLIENT_ID_IFE6_PID:
  205. return "IFE6_PID";
  206. case HW_FENCE_IPC_CLIENT_ID_IFE7_PID:
  207. return "IFE7_PID";
  208. }
  209. return "UNKNOWN_PID";
  210. }
  211. /**
  212. * _get_ipc_virt_client_name() - Returns ipc client name from its virtual id, used for debugging.
  213. */
  214. static inline char *_get_ipc_virt_client_name(u32 client_id)
  215. {
  216. switch (client_id) {
  217. case HW_FENCE_IPC_CLIENT_ID_APPS_VID:
  218. return "APPS_VID";
  219. case HW_FENCE_IPC_CLIENT_ID_GPU_VID:
  220. return "GPU_VID";
  221. case HW_FENCE_IPC_CLIENT_ID_DPU_VID:
  222. return "DPU_VID";
  223. case HW_FENCE_IPC_CLIENT_ID_IPE_VID:
  224. return "IPE_VID";
  225. case HW_FENCE_IPC_CLIENT_ID_VPU_VID:
  226. return "VPU_VID";
  227. case HW_FENCE_IPC_CLIENT_ID_IFE0_VID:
  228. return "IFE0_VID";
  229. case HW_FENCE_IPC_CLIENT_ID_IFE1_VID:
  230. return "IFE1_VID";
  231. case HW_FENCE_IPC_CLIENT_ID_IFE2_VID:
  232. return "IFE2_VID";
  233. case HW_FENCE_IPC_CLIENT_ID_IFE3_VID:
  234. return "IFE3_VID";
  235. case HW_FENCE_IPC_CLIENT_ID_IFE4_VID:
  236. return "IFE4_VID";
  237. case HW_FENCE_IPC_CLIENT_ID_IFE5_VID:
  238. return "IFE5_VID";
  239. case HW_FENCE_IPC_CLIENT_ID_IFE6_VID:
  240. return "IFE6_VID";
  241. case HW_FENCE_IPC_CLIENT_ID_IFE7_VID:
  242. return "IFE7_VID";
  243. }
  244. return "UNKNOWN_VID";
  245. }
  246. void hw_fence_ipcc_trigger_signal(struct hw_fence_driver_data *drv_data,
  247. u32 tx_client_pid, u32 rx_client_vid, u32 signal_id)
  248. {
  249. void __iomem *ptr;
  250. u32 val;
  251. /* Send signal */
  252. ptr = IPC_PROTOCOLp_CLIENTc_SEND(drv_data->ipcc_io_mem, drv_data->protocol_id,
  253. tx_client_pid);
  254. val = (rx_client_vid << 16) | signal_id;
  255. HWFNC_DBG_IRQ("Sending ipcc from %s (%d) to %s (%d) signal_id:%d [wr:0x%x to off:0x%pK]\n",
  256. _get_ipc_phys_client_name(tx_client_pid), tx_client_pid,
  257. _get_ipc_virt_client_name(rx_client_vid), rx_client_vid,
  258. signal_id, val, ptr);
  259. HWFNC_DBG_H("Write:0x%x to RegOffset:0x%pK\n", val, ptr);
  260. writel_relaxed(val, ptr);
  261. /* Make sure value is written */
  262. wmb();
  263. }
  264. static int _hw_fence_ipcc_init_map_with_configurable_clients(struct hw_fence_driver_data *drv_data,
  265. struct hw_fence_client_ipc_map *base_table)
  266. {
  267. int i, j, map_idx;
  268. size_t size;
  269. size = drv_data->clients_num * sizeof(struct hw_fence_client_ipc_map);
  270. drv_data->ipc_clients_table = kzalloc(size, GFP_KERNEL);
  271. if (!drv_data->ipc_clients_table)
  272. return -ENOMEM;
  273. /* copy mappings for static hw fence clients */
  274. size = HW_FENCE_MAX_STATIC_CLIENTS_INDEX * sizeof(struct hw_fence_client_ipc_map);
  275. memcpy(drv_data->ipc_clients_table, base_table, size);
  276. /* initialize mappings for ipc clients with configurable number of hw fence clients */
  277. map_idx = HW_FENCE_MAX_STATIC_CLIENTS_INDEX;
  278. for (i = 0; i < HW_FENCE_MAX_CLIENT_TYPE_CONFIGURABLE; i++) {
  279. int client_type = HW_FENCE_MAX_CLIENT_TYPE_STATIC + i;
  280. int clients_num = drv_data->hw_fence_client_types[client_type].clients_num;
  281. for (j = 0; j < clients_num; j++) {
  282. /* this should never happen if drv_data->clients_num is correct */
  283. if (map_idx >= drv_data->clients_num) {
  284. HWFNC_ERR("%s clients_num:%lu exceeds drv_data->clients_num:%lu\n",
  285. drv_data->hw_fence_client_types[client_type].name,
  286. clients_num, drv_data->clients_num);
  287. return -EINVAL;
  288. }
  289. drv_data->ipc_clients_table[map_idx] =
  290. base_table[HW_FENCE_MAX_STATIC_CLIENTS_INDEX + i];
  291. drv_data->ipc_clients_table[map_idx].ipc_signal_id = j;
  292. map_idx++;
  293. }
  294. }
  295. return 0;
  296. }
  297. /**
  298. * _hw_fence_ipcc_hwrev_init() - Initializes internal driver struct with corresponding ipcc data,
  299. * according to the ipcc hw revision.
  300. * @drv_data: driver data.
  301. * @hwrev: ipcc hw revision.
  302. */
  303. static int _hw_fence_ipcc_hwrev_init(struct hw_fence_driver_data *drv_data, u32 hwrev)
  304. {
  305. int ret = 0;
  306. switch (hwrev) {
  307. case HW_FENCE_IPCC_HW_REV_100:
  308. drv_data->ipcc_client_vid = HW_FENCE_IPC_CLIENT_ID_APPS_VID;
  309. drv_data->ipcc_client_pid = HW_FENCE_IPC_CLIENT_ID_APPS_VID;
  310. drv_data->protocol_id = HW_FENCE_IPC_COMPUTE_L1_PROTOCOL_ID_LAHAINA;
  311. drv_data->ipc_clients_table = hw_fence_clients_ipc_map_no_dpu;
  312. HWFNC_DBG_INIT("ipcc protocol_id: Lahaina\n");
  313. break;
  314. case HW_FENCE_IPCC_HW_REV_110:
  315. drv_data->ipcc_client_vid = HW_FENCE_IPC_CLIENT_ID_APPS_VID;
  316. drv_data->ipcc_client_pid = HW_FENCE_IPC_CLIENT_ID_APPS_VID;
  317. drv_data->protocol_id = HW_FENCE_IPC_COMPUTE_L1_PROTOCOL_ID_WAIPIO;
  318. drv_data->ipc_clients_table = hw_fence_clients_ipc_map_no_dpu;
  319. HWFNC_DBG_INIT("ipcc protocol_id: Waipio\n");
  320. break;
  321. case HW_FENCE_IPCC_HW_REV_170:
  322. drv_data->ipcc_client_vid = HW_FENCE_IPC_CLIENT_ID_APPS_VID;
  323. drv_data->ipcc_client_pid = HW_FENCE_IPC_CLIENT_ID_APPS_VID;
  324. drv_data->protocol_id = HW_FENCE_IPC_COMPUTE_L1_PROTOCOL_ID_KALAMA;
  325. drv_data->ipc_clients_table = hw_fence_clients_ipc_map;
  326. HWFNC_DBG_INIT("ipcc protocol_id: Kalama\n");
  327. break;
  328. case HW_FENCE_IPCC_HW_REV_203:
  329. drv_data->ipcc_client_vid = HW_FENCE_IPC_CLIENT_ID_APPS_VID;
  330. drv_data->ipcc_client_pid = HW_FENCE_IPC_CLIENT_ID_APPS_PID;
  331. drv_data->protocol_id = HW_FENCE_IPC_FENCE_PROTOCOL_ID_PINEAPPLE; /* Fence */
  332. ret = _hw_fence_ipcc_init_map_with_configurable_clients(drv_data,
  333. hw_fence_clients_ipc_map_v2);
  334. HWFNC_DBG_INIT("ipcc protocol_id: Pineapple\n");
  335. break;
  336. default:
  337. return -1;
  338. }
  339. return ret;
  340. }
  341. int hw_fence_ipcc_enable_signaling(struct hw_fence_driver_data *drv_data)
  342. {
  343. void __iomem *ptr;
  344. u32 val;
  345. int ret;
  346. HWFNC_DBG_H("enable ipc +\n");
  347. /**
  348. * Attempt to read the ipc version from dt, if not available, then attempt
  349. * to read from the registers.
  350. */
  351. ret = of_property_read_u32(drv_data->dev->of_node, "qcom,hw-fence-ipc-ver", &val);
  352. if (ret || !val) {
  353. /* if no device tree prop, attempt to get the version from the registers*/
  354. HWFNC_DBG_H("missing hw fences ipc-ver entry or invalid ret:%d val:%d\n", ret, val);
  355. /* Read IPC Version from Client=0x8 (apps) for protocol=2 (compute_l1) */
  356. val = readl_relaxed(IPC_PROTOCOLp_CLIENTc_VERSION(drv_data->ipcc_io_mem,
  357. HW_FENCE_IPC_COMPUTE_L1_PROTOCOL_ID_LAHAINA,
  358. HW_FENCE_IPC_CLIENT_ID_APPS_VID));
  359. HWFNC_DBG_INIT("ipcc version:0x%x\n", val);
  360. }
  361. if (_hw_fence_ipcc_hwrev_init(drv_data, val)) {
  362. HWFNC_ERR("ipcc protocol id not supported\n");
  363. return -EINVAL;
  364. }
  365. /* Enable compute l1 (protocol_id = 2) */
  366. val = 0x00000000;
  367. ptr = IPC_PROTOCOLp_CLIENTc_CONFIG(drv_data->ipcc_io_mem, drv_data->protocol_id,
  368. drv_data->ipcc_client_pid);
  369. HWFNC_DBG_H("Write:0x%x to RegOffset:0x%pK\n", val, ptr);
  370. writel_relaxed(val, ptr);
  371. /* Enable Client-Signal pairs from APPS(NS) (0x8) to APPS(NS) (0x8) */
  372. val = 0x000080000;
  373. ptr = IPC_PROTOCOLp_CLIENTc_RECV_SIGNAL_ENABLE(drv_data->ipcc_io_mem, drv_data->protocol_id,
  374. drv_data->ipcc_client_pid);
  375. HWFNC_DBG_H("Write:0x%x to RegOffset:0x%pK\n", val, ptr);
  376. writel_relaxed(val, ptr);
  377. HWFNC_DBG_H("enable ipc -\n");
  378. return 0;
  379. }
  380. #ifdef HW_DPU_IPCC
  381. int hw_fence_ipcc_enable_dpu_signaling(struct hw_fence_driver_data *drv_data)
  382. {
  383. struct hw_fence_client_ipc_map *hw_fence_client;
  384. bool protocol_enabled = false;
  385. void __iomem *ptr;
  386. u32 val;
  387. int i;
  388. HWFNC_DBG_H("enable dpu ipc +\n");
  389. if (!drv_data || !drv_data->protocol_id || !drv_data->ipc_clients_table) {
  390. HWFNC_ERR("invalid drv data\n");
  391. return -1;
  392. }
  393. HWFNC_DBG_H("ipcc_io_mem:0x%lx\n", (u64)drv_data->ipcc_io_mem);
  394. HWFNC_DBG_H("Initialize dpu signals\n");
  395. /* Enable Client-Signal pairs from DPU (25) to APPS(NS) (8) */
  396. for (i = 0; i < drv_data->clients_num; i++) {
  397. hw_fence_client = &drv_data->ipc_clients_table[i];
  398. /* skip any client that is not a dpu client */
  399. if (hw_fence_client->ipc_client_id_virt != HW_FENCE_IPC_CLIENT_ID_DPU_VID)
  400. continue;
  401. if (!protocol_enabled) {
  402. /*
  403. * First DPU client will enable the protocol for dpu, e.g. compute l1
  404. * (protocol_id = 2) or fencing protocol, depending on the target, for the
  405. * dpu client (vid = 25, pid = 9).
  406. * Sets bit(1) to clear when RECV_ID is read
  407. */
  408. val = 0x00000001;
  409. ptr = IPC_PROTOCOLp_CLIENTc_CONFIG(drv_data->ipcc_io_mem,
  410. drv_data->protocol_id, hw_fence_client->ipc_client_id_phys);
  411. HWFNC_DBG_H("Write:0x%x to RegOffset:0x%lx\n", val, (u64)ptr);
  412. writel_relaxed(val, ptr);
  413. protocol_enabled = true;
  414. }
  415. /* Enable signals for dpu client */
  416. HWFNC_DBG_H("dpu client:%d vid:%d pid:%d signal:%d\n", i,
  417. hw_fence_client->ipc_client_id_virt, hw_fence_client->ipc_client_id_phys,
  418. hw_fence_client->ipc_signal_id);
  419. /* Enable input apps-signal for dpu */
  420. val = (HW_FENCE_IPC_CLIENT_ID_APPS_VID << 16) |
  421. (hw_fence_client->ipc_signal_id & 0xFFFF);
  422. ptr = IPC_PROTOCOLp_CLIENTc_RECV_SIGNAL_ENABLE(drv_data->ipcc_io_mem,
  423. drv_data->protocol_id, hw_fence_client->ipc_client_id_phys);
  424. HWFNC_DBG_H("Write:0x%x to RegOffset:0x%lx\n", val, (u64)ptr);
  425. writel_relaxed(val, ptr);
  426. }
  427. HWFNC_DBG_H("enable dpu ipc -\n");
  428. return 0;
  429. }
  430. #endif /* HW_DPU_IPCC */