hfi.c 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  4. * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
  5. */
  6. #include <linux/io.h>
  7. #include <linux/delay.h>
  8. #include <linux/slab.h>
  9. #include <linux/random.h>
  10. #include <asm/errno.h>
  11. #include <linux/timer.h>
  12. #include <media/cam_icp.h>
  13. #include <linux/iopoll.h>
  14. #include "cam_presil_hw_access.h"
  15. #include "cam_io_util.h"
  16. #include "hfi_reg.h"
  17. #include "hfi_sys_defs.h"
  18. #include "hfi_session_defs.h"
  19. #include "hfi_intf.h"
  20. #include "cam_icp_hw_mgr_intf.h"
  21. #include "cam_debug_util.h"
  22. #include "cam_compat.h"
  23. #include "cam_soc_util.h"
  24. #define HFI_VERSION_INFO_MAJOR_VAL 1
  25. #define HFI_VERSION_INFO_MINOR_VAL 1
  26. #define HFI_VERSION_INFO_STEP_VAL 0
  27. #define HFI_VERSION_INFO_STEP_VAL 0
  28. #define HFI_VERSION_INFO_MAJOR_BMSK 0xFF000000
  29. #define HFI_VERSION_INFO_MAJOR_SHFT 24
  30. #define HFI_VERSION_INFO_MINOR_BMSK 0xFFFF00
  31. #define HFI_VERSION_INFO_MINOR_SHFT 8
  32. #define HFI_VERSION_INFO_STEP_BMSK 0xFF
  33. #define HFI_VERSION_INFO_STEP_SHFT 0
  34. /* TO DO Lower timeout value */
  35. #define HFI_POLL_DELAY_US 10
  36. #define HFI_POLL_TIMEOUT_US 1500000
  37. static struct hfi_info *g_hfi;
  38. unsigned int g_icp_mmu_hdl;
  39. static DEFINE_MUTEX(hfi_cmd_q_mutex);
  40. static DEFINE_MUTEX(hfi_msg_q_mutex);
  41. static int cam_hfi_presil_setup(struct hfi_mem_info *hfi_mem);
  42. static int cam_hfi_presil_set_init_request(void);
  43. #ifndef CONFIG_CAM_PRESIL
  44. static void hfi_irq_raise(struct hfi_info *hfi)
  45. {
  46. if (hfi->ops.irq_raise)
  47. hfi->ops.irq_raise(hfi->priv);
  48. }
  49. #endif
  50. static void hfi_irq_enable(struct hfi_info *hfi)
  51. {
  52. if (hfi->ops.irq_enable)
  53. hfi->ops.irq_enable(hfi->priv);
  54. }
  55. static void __iomem *hfi_iface_addr(struct hfi_info *hfi)
  56. {
  57. void __iomem *ret = NULL;
  58. if (hfi->ops.iface_addr)
  59. ret = hfi->ops.iface_addr(hfi->priv);
  60. return IS_ERR_OR_NULL(ret) ? NULL : ret;
  61. }
  62. static void hfi_queue_dump(uint32_t *dwords, int count)
  63. {
  64. int i;
  65. int rows;
  66. int remaining;
  67. rows = count / 4;
  68. remaining = count % 4;
  69. for (i = 0; i < rows; i++, dwords += 4)
  70. CAM_DBG(CAM_HFI,
  71. "word[%04d]: 0x%08x 0x%08x 0x%08x 0x%08x",
  72. i * 4, dwords[0], dwords[1], dwords[2], dwords[3]);
  73. if (remaining == 1)
  74. CAM_DBG(CAM_HFI, "word[%04d]: 0x%08x", rows * 4, dwords[0]);
  75. else if (remaining == 2)
  76. CAM_DBG(CAM_HFI, "word[%04d]: 0x%08x 0x%08x",
  77. rows * 4, dwords[0], dwords[1]);
  78. else if (remaining == 3)
  79. CAM_DBG(CAM_HFI, "word[%04d]: 0x%08x 0x%08x 0x%08x",
  80. rows * 4, dwords[0], dwords[1], dwords[2]);
  81. }
  82. void cam_hfi_mini_dump(struct hfi_mini_dump_info *dst)
  83. {
  84. struct hfi_mem_info *hfi_mem = &g_hfi->map;
  85. struct hfi_qtbl *qtbl;
  86. struct hfi_q_hdr *q_hdr;
  87. uint32_t *dwords;
  88. int num_dwords;
  89. if (!hfi_mem) {
  90. CAM_ERR(CAM_HFI, "hfi mem info NULL... unable to dump queues");
  91. return;
  92. }
  93. qtbl = (struct hfi_qtbl *)hfi_mem->qtbl.kva;
  94. q_hdr = &qtbl->q_hdr[Q_CMD];
  95. dwords = (uint32_t *)hfi_mem->cmd_q.kva;
  96. num_dwords = ICP_CMD_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT;
  97. memcpy(dst->cmd_q, dwords, ICP_CMD_Q_SIZE_IN_BYTES);
  98. q_hdr = &qtbl->q_hdr[Q_MSG];
  99. dwords = (uint32_t *)hfi_mem->msg_q.kva;
  100. memcpy(dst->msg_q, dwords, ICP_CMD_Q_SIZE_IN_BYTES);
  101. dst->msg_q_state = g_hfi->msg_q_state;
  102. dst->cmd_q_state = g_hfi->cmd_q_state;
  103. }
  104. void cam_hfi_queue_dump(bool dump_queue_data)
  105. {
  106. struct hfi_mem_info *hfi_mem = &g_hfi->map;
  107. struct hfi_qtbl *qtbl;
  108. struct hfi_q_hdr *q_hdr;
  109. uint32_t *dwords;
  110. int num_dwords;
  111. if (!hfi_mem) {
  112. CAM_ERR(CAM_HFI, "hfi mem info NULL... unable to dump queues");
  113. return;
  114. }
  115. qtbl = (struct hfi_qtbl *)hfi_mem->qtbl.kva;
  116. CAM_INFO(CAM_HFI,
  117. "qtbl header: version=0x%08x tbl_size=%u numq=%u qhdr_size=%u",
  118. qtbl->q_tbl_hdr.qtbl_version,
  119. qtbl->q_tbl_hdr.qtbl_size,
  120. qtbl->q_tbl_hdr.qtbl_num_q,
  121. qtbl->q_tbl_hdr.qtbl_qhdr_size);
  122. q_hdr = &qtbl->q_hdr[Q_CMD];
  123. CAM_INFO(CAM_HFI,
  124. "cmd_q: addr=0x%08x size=%u read_idx=%u write_idx=%u",
  125. hfi_mem->cmd_q.iova,
  126. q_hdr->qhdr_q_size,
  127. q_hdr->qhdr_read_idx,
  128. q_hdr->qhdr_write_idx);
  129. dwords = (uint32_t *)hfi_mem->cmd_q.kva;
  130. num_dwords = ICP_CMD_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT;
  131. if (dump_queue_data)
  132. hfi_queue_dump(dwords, num_dwords);
  133. q_hdr = &qtbl->q_hdr[Q_MSG];
  134. CAM_INFO(CAM_HFI,
  135. "msg_q: addr=0x%08x size=%u read_idx=%u write_idx=%u",
  136. hfi_mem->msg_q.iova,
  137. q_hdr->qhdr_q_size,
  138. q_hdr->qhdr_read_idx,
  139. q_hdr->qhdr_write_idx);
  140. dwords = (uint32_t *)hfi_mem->msg_q.kva;
  141. num_dwords = ICP_MSG_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT;
  142. if (dump_queue_data)
  143. hfi_queue_dump(dwords, num_dwords);
  144. }
  145. #ifndef CONFIG_CAM_PRESIL
  146. int hfi_write_cmd(void *cmd_ptr)
  147. {
  148. uint32_t size_in_words, empty_space, new_write_idx, read_idx, temp;
  149. uint32_t *write_q, *write_ptr;
  150. struct hfi_qtbl *q_tbl;
  151. struct hfi_q_hdr *q;
  152. int rc = 0;
  153. if (!cmd_ptr) {
  154. CAM_ERR(CAM_HFI, "command is null");
  155. return -EINVAL;
  156. }
  157. mutex_lock(&hfi_cmd_q_mutex);
  158. if (!g_hfi) {
  159. CAM_ERR(CAM_HFI, "HFI interface not setup");
  160. rc = -ENODEV;
  161. goto err;
  162. }
  163. if (g_hfi->hfi_state != HFI_READY ||
  164. !g_hfi->cmd_q_state) {
  165. CAM_ERR(CAM_HFI, "HFI state: %u, cmd q state: %u",
  166. g_hfi->hfi_state, g_hfi->cmd_q_state);
  167. rc = -ENODEV;
  168. goto err;
  169. }
  170. q_tbl = (struct hfi_qtbl *)g_hfi->map.qtbl.kva;
  171. q = &q_tbl->q_hdr[Q_CMD];
  172. write_q = (uint32_t *)g_hfi->map.cmd_q.kva;
  173. size_in_words = (*(uint32_t *)cmd_ptr) >> BYTE_WORD_SHIFT;
  174. if (!size_in_words) {
  175. CAM_DBG(CAM_HFI, "failed");
  176. rc = -EINVAL;
  177. goto err;
  178. }
  179. read_idx = q->qhdr_read_idx;
  180. empty_space = (q->qhdr_write_idx >= read_idx) ?
  181. (q->qhdr_q_size - (q->qhdr_write_idx - read_idx)) :
  182. (read_idx - q->qhdr_write_idx);
  183. if (empty_space <= size_in_words) {
  184. CAM_ERR(CAM_HFI, "failed: empty space %u, size_in_words %u",
  185. empty_space, size_in_words);
  186. rc = -EIO;
  187. goto err;
  188. }
  189. new_write_idx = q->qhdr_write_idx + size_in_words;
  190. write_ptr = (uint32_t *)(write_q + q->qhdr_write_idx);
  191. if (new_write_idx < q->qhdr_q_size) {
  192. memcpy(write_ptr, (uint8_t *)cmd_ptr,
  193. size_in_words << BYTE_WORD_SHIFT);
  194. } else {
  195. new_write_idx -= q->qhdr_q_size;
  196. temp = (size_in_words - new_write_idx) << BYTE_WORD_SHIFT;
  197. memcpy(write_ptr, (uint8_t *)cmd_ptr, temp);
  198. memcpy(write_q, (uint8_t *)cmd_ptr + temp,
  199. new_write_idx << BYTE_WORD_SHIFT);
  200. }
  201. /*
  202. * To make sure command data in a command queue before
  203. * updating write index
  204. */
  205. wmb();
  206. q->qhdr_write_idx = new_write_idx;
  207. /*
  208. * Before raising interrupt make sure command data is ready for
  209. * firmware to process
  210. */
  211. wmb();
  212. hfi_irq_raise(g_hfi);
  213. /* Ensure HOST2ICP trigger is received by FW */
  214. wmb();
  215. err:
  216. mutex_unlock(&hfi_cmd_q_mutex);
  217. return rc;
  218. }
  219. int hfi_read_message(uint32_t *pmsg, uint8_t q_id,
  220. uint32_t *words_read)
  221. {
  222. struct hfi_qtbl *q_tbl_ptr;
  223. struct hfi_q_hdr *q;
  224. uint32_t new_read_idx, size_in_words, word_diff, temp;
  225. uint32_t *read_q, *read_ptr, *write_ptr;
  226. uint32_t size_upper_bound = 0;
  227. int rc = 0;
  228. if (!pmsg) {
  229. CAM_ERR(CAM_HFI, "Invalid msg");
  230. return -EINVAL;
  231. }
  232. if (!((q_id == Q_MSG) || (q_id == Q_DBG))) {
  233. CAM_ERR(CAM_HFI, "Invalid q :%u", q_id);
  234. return -EINVAL;
  235. }
  236. mutex_lock(&hfi_msg_q_mutex);
  237. if (!g_hfi) {
  238. CAM_ERR(CAM_HFI, "hfi not set up yet");
  239. rc = -ENODEV;
  240. goto err;
  241. }
  242. if ((g_hfi->hfi_state != HFI_READY) ||
  243. !g_hfi->msg_q_state) {
  244. CAM_ERR(CAM_HFI, "hfi state: %u, msg q state: %u",
  245. g_hfi->hfi_state, g_hfi->msg_q_state);
  246. rc = -ENODEV;
  247. goto err;
  248. }
  249. q_tbl_ptr = (struct hfi_qtbl *)g_hfi->map.qtbl.kva;
  250. q = &q_tbl_ptr->q_hdr[q_id];
  251. if (q->qhdr_read_idx == q->qhdr_write_idx) {
  252. CAM_DBG(CAM_HFI, "Q not ready, state:%u, r idx:%u, w idx:%u",
  253. g_hfi->hfi_state, q->qhdr_read_idx, q->qhdr_write_idx);
  254. rc = -EIO;
  255. goto err;
  256. }
  257. size_upper_bound = q->qhdr_q_size;
  258. if (q_id == Q_MSG)
  259. read_q = (uint32_t *)g_hfi->map.msg_q.kva;
  260. else
  261. read_q = (uint32_t *)g_hfi->map.dbg_q.kva;
  262. read_ptr = (uint32_t *)(read_q + q->qhdr_read_idx);
  263. write_ptr = (uint32_t *)(read_q + q->qhdr_write_idx);
  264. if (write_ptr > read_ptr)
  265. size_in_words = write_ptr - read_ptr;
  266. else {
  267. word_diff = read_ptr - write_ptr;
  268. size_in_words = q->qhdr_q_size - word_diff;
  269. }
  270. if ((size_in_words == 0) ||
  271. (size_in_words > size_upper_bound)) {
  272. CAM_ERR(CAM_HFI, "invalid HFI message packet size - 0x%08x",
  273. size_in_words << BYTE_WORD_SHIFT);
  274. q->qhdr_read_idx = q->qhdr_write_idx;
  275. rc = -EIO;
  276. goto err;
  277. }
  278. new_read_idx = q->qhdr_read_idx + size_in_words;
  279. if (new_read_idx < q->qhdr_q_size) {
  280. memcpy(pmsg, read_ptr, size_in_words << BYTE_WORD_SHIFT);
  281. } else {
  282. new_read_idx -= q->qhdr_q_size;
  283. temp = (size_in_words - new_read_idx) << BYTE_WORD_SHIFT;
  284. memcpy(pmsg, read_ptr, temp);
  285. memcpy((uint8_t *)pmsg + temp, read_q,
  286. new_read_idx << BYTE_WORD_SHIFT);
  287. }
  288. q->qhdr_read_idx = new_read_idx;
  289. *words_read = size_in_words;
  290. /* Memory Barrier to make sure message
  291. * queue parameters are updated after read
  292. */
  293. wmb();
  294. err:
  295. mutex_unlock(&hfi_msg_q_mutex);
  296. return rc;
  297. }
  298. #endif /* #ifndef CONFIG_CAM_PRESIL */
  299. int hfi_cmd_ubwc_config(uint32_t *ubwc_cfg)
  300. {
  301. uint8_t *prop;
  302. struct hfi_cmd_prop *dbg_prop;
  303. uint32_t size = 0;
  304. size = sizeof(struct hfi_cmd_prop) +
  305. sizeof(struct hfi_cmd_ubwc_cfg);
  306. CAM_DBG(CAM_HFI,
  307. "size of ubwc %u, ubwc_cfg [rd-0x%x,wr-0x%x]",
  308. size, ubwc_cfg[0], ubwc_cfg[1]);
  309. prop = kzalloc(size, GFP_KERNEL);
  310. if (!prop)
  311. return -ENOMEM;
  312. dbg_prop = (struct hfi_cmd_prop *)prop;
  313. dbg_prop->size = size;
  314. dbg_prop->pkt_type = HFI_CMD_SYS_SET_PROPERTY;
  315. dbg_prop->num_prop = 1;
  316. dbg_prop->prop_data[0] = HFI_PROP_SYS_UBWC_CFG;
  317. dbg_prop->prop_data[1] = ubwc_cfg[0];
  318. dbg_prop->prop_data[2] = ubwc_cfg[1];
  319. hfi_write_cmd(prop);
  320. kfree(prop);
  321. return 0;
  322. }
  323. int hfi_cmd_ubwc_config_ext(uint32_t *ubwc_ipe_cfg,
  324. uint32_t *ubwc_bps_cfg)
  325. {
  326. uint8_t *prop;
  327. struct hfi_cmd_prop *dbg_prop;
  328. uint32_t size = 0;
  329. size = sizeof(struct hfi_cmd_prop) +
  330. sizeof(struct hfi_cmd_ubwc_cfg_ext);
  331. CAM_DBG(CAM_HFI,
  332. "size of ubwc %u, ubwc_ipe_cfg[rd-0x%x,wr-0x%x] ubwc_bps_cfg[rd-0x%x,wr-0x%x]",
  333. size, ubwc_ipe_cfg[0], ubwc_ipe_cfg[1],
  334. ubwc_bps_cfg[0], ubwc_bps_cfg[1]);
  335. prop = kzalloc(size, GFP_KERNEL);
  336. if (!prop)
  337. return -ENOMEM;
  338. dbg_prop = (struct hfi_cmd_prop *)prop;
  339. dbg_prop->size = size;
  340. dbg_prop->pkt_type = HFI_CMD_SYS_SET_PROPERTY;
  341. dbg_prop->num_prop = 1;
  342. dbg_prop->prop_data[0] = HFI_PROPERTY_SYS_UBWC_CONFIG_EX;
  343. dbg_prop->prop_data[1] = ubwc_bps_cfg[0];
  344. dbg_prop->prop_data[2] = ubwc_bps_cfg[1];
  345. dbg_prop->prop_data[3] = ubwc_ipe_cfg[0];
  346. dbg_prop->prop_data[4] = ubwc_ipe_cfg[1];
  347. hfi_write_cmd(prop);
  348. kfree(prop);
  349. return 0;
  350. }
  351. int hfi_enable_dev_pc(bool enable, uint32_t core_info)
  352. {
  353. uint8_t *prop;
  354. struct hfi_cmd_prop *dbg_prop;
  355. uint32_t size = 0;
  356. size = sizeof(struct hfi_cmd_prop) +
  357. sizeof(struct hfi_dev_pc);
  358. prop = kzalloc(size, GFP_KERNEL);
  359. if (!prop)
  360. return -ENOMEM;
  361. dbg_prop = (struct hfi_cmd_prop *)prop;
  362. dbg_prop->size = size;
  363. dbg_prop->pkt_type = HFI_CMD_SYS_SET_PROPERTY;
  364. dbg_prop->num_prop = 1;
  365. dbg_prop->prop_data[0] = HFI_PROP_SYS_IPEBPS_PC;
  366. dbg_prop->prop_data[1] = enable;
  367. dbg_prop->prop_data[2] = core_info;
  368. hfi_write_cmd(prop);
  369. kfree(prop);
  370. return 0;
  371. }
  372. int hfi_set_debug_level(u64 icp_dbg_type, uint32_t lvl)
  373. {
  374. uint8_t *prop;
  375. struct hfi_cmd_prop *dbg_prop;
  376. uint32_t size = 0, val;
  377. val = HFI_DEBUG_MSG_LOW |
  378. HFI_DEBUG_MSG_MEDIUM |
  379. HFI_DEBUG_MSG_HIGH |
  380. HFI_DEBUG_MSG_ERROR |
  381. HFI_DEBUG_MSG_FATAL |
  382. HFI_DEBUG_MSG_PERF |
  383. HFI_DEBUG_CFG_WFI |
  384. HFI_DEBUG_CFG_ARM9WD;
  385. if (lvl > val)
  386. return -EINVAL;
  387. if (g_hfi)
  388. g_hfi->dbg_lvl = lvl;
  389. size = sizeof(struct hfi_cmd_prop) +
  390. sizeof(struct hfi_debug);
  391. prop = kzalloc(size, GFP_KERNEL);
  392. if (!prop)
  393. return -ENOMEM;
  394. dbg_prop = (struct hfi_cmd_prop *)prop;
  395. dbg_prop->size = size;
  396. dbg_prop->pkt_type = HFI_CMD_SYS_SET_PROPERTY;
  397. dbg_prop->num_prop = 1;
  398. dbg_prop->prop_data[0] = HFI_PROP_SYS_DEBUG_CFG;
  399. dbg_prop->prop_data[1] = lvl;
  400. dbg_prop->prop_data[2] = icp_dbg_type;
  401. hfi_write_cmd(prop);
  402. kfree(prop);
  403. return 0;
  404. }
  405. int hfi_set_fw_dump_levels(uint32_t hang_dump_lvl,
  406. uint32_t ram_dump_lvl)
  407. {
  408. uint8_t *prop = NULL;
  409. struct hfi_cmd_prop *fw_dump_level_switch_prop = NULL;
  410. uint32_t size = 0;
  411. CAM_DBG(CAM_HFI, "fw dump ENTER");
  412. size = sizeof(struct hfi_cmd_prop) + sizeof(uint32_t);
  413. prop = kzalloc(size, GFP_KERNEL);
  414. if (!prop)
  415. return -ENOMEM;
  416. fw_dump_level_switch_prop = (struct hfi_cmd_prop *)prop;
  417. fw_dump_level_switch_prop->size = size;
  418. fw_dump_level_switch_prop->pkt_type = HFI_CMD_SYS_SET_PROPERTY;
  419. fw_dump_level_switch_prop->num_prop = 1;
  420. fw_dump_level_switch_prop->prop_data[0] = HFI_PROP_SYS_FW_DUMP_CFG;
  421. fw_dump_level_switch_prop->prop_data[1] = hang_dump_lvl;
  422. /* Write hang dump level */
  423. hfi_write_cmd(prop);
  424. /* Update and write ramdump level */
  425. fw_dump_level_switch_prop->prop_data[0] = HFI_PROPERTY_SYS_RAMDUMP_MODE;
  426. fw_dump_level_switch_prop->prop_data[1] = ram_dump_lvl;
  427. hfi_write_cmd(prop);
  428. CAM_DBG(CAM_HFI,
  429. "prop->size = %d prop->pkt_type = %d prop->num_prop = %d hang_dump_lvl = %u ram_dump_lvl = %u",
  430. fw_dump_level_switch_prop->size,
  431. fw_dump_level_switch_prop->pkt_type,
  432. fw_dump_level_switch_prop->num_prop,
  433. hang_dump_lvl, ram_dump_lvl);
  434. kfree(prop);
  435. return 0;
  436. }
  437. int hfi_send_freq_info(int32_t freq)
  438. {
  439. uint8_t *prop = NULL;
  440. struct hfi_cmd_prop *dbg_prop = NULL;
  441. uint32_t size = 0;
  442. if (!g_hfi) {
  443. CAM_ERR(CAM_HFI, "HFI interface not setup");
  444. return -ENODEV;
  445. }
  446. if (!(g_hfi->dbg_lvl & HFI_DEBUG_MSG_PERF))
  447. return -EINVAL;
  448. size = sizeof(struct hfi_cmd_prop) + sizeof(freq);
  449. prop = kzalloc(size, GFP_KERNEL);
  450. if (!prop)
  451. return -ENOMEM;
  452. dbg_prop = (struct hfi_cmd_prop *)prop;
  453. dbg_prop->size = size;
  454. dbg_prop->pkt_type = HFI_CMD_SYS_SET_PROPERTY;
  455. dbg_prop->num_prop = 1;
  456. dbg_prop->prop_data[0] = HFI_PROPERTY_SYS_ICP_HW_FREQUENCY;
  457. dbg_prop->prop_data[1] = freq;
  458. CAM_DBG(CAM_HFI, "prop->size = %d\n"
  459. "prop->pkt_type = %d\n"
  460. "prop->num_prop = %d\n"
  461. "prop->prop_data[0] = %d\n"
  462. "prop->prop_data[1] = %d\n"
  463. "dbg_lvl = 0x%x\n",
  464. dbg_prop->size,
  465. dbg_prop->pkt_type,
  466. dbg_prop->num_prop,
  467. dbg_prop->prop_data[0],
  468. dbg_prop->prop_data[1],
  469. g_hfi->dbg_lvl);
  470. hfi_write_cmd(prop);
  471. kfree(prop);
  472. return 0;
  473. }
  474. void hfi_send_system_cmd(uint32_t type, uint64_t data, uint32_t size)
  475. {
  476. switch (type) {
  477. case HFI_CMD_SYS_INIT: {
  478. struct hfi_cmd_sys_init init;
  479. init.size = sizeof(struct hfi_cmd_sys_init);
  480. init.pkt_type = type;
  481. hfi_write_cmd(&init);
  482. }
  483. break;
  484. case HFI_CMD_SYS_PC_PREP: {
  485. struct hfi_cmd_pc_prep prep;
  486. prep.size = sizeof(struct hfi_cmd_pc_prep);
  487. prep.pkt_type = type;
  488. hfi_write_cmd(&prep);
  489. }
  490. break;
  491. case HFI_CMD_SYS_SET_PROPERTY: {
  492. struct hfi_cmd_prop prop;
  493. if ((uint32_t)data == (uint32_t)HFI_PROP_SYS_DEBUG_CFG) {
  494. prop.size = sizeof(struct hfi_cmd_prop);
  495. prop.pkt_type = type;
  496. prop.num_prop = 1;
  497. prop.prop_data[0] = HFI_PROP_SYS_DEBUG_CFG;
  498. hfi_write_cmd(&prop);
  499. }
  500. }
  501. break;
  502. case HFI_CMD_SYS_GET_PROPERTY:
  503. break;
  504. case HFI_CMD_SYS_PING: {
  505. struct hfi_cmd_ping_pkt ping;
  506. ping.size = sizeof(struct hfi_cmd_ping_pkt);
  507. ping.pkt_type = type;
  508. ping.user_data = (uint64_t)data;
  509. hfi_write_cmd(&ping);
  510. }
  511. break;
  512. case HFI_CMD_SYS_RESET: {
  513. struct hfi_cmd_sys_reset_pkt reset;
  514. reset.size = sizeof(struct hfi_cmd_sys_reset_pkt);
  515. reset.pkt_type = type;
  516. reset.user_data = (uint64_t)data;
  517. hfi_write_cmd(&reset);
  518. }
  519. break;
  520. case HFI_CMD_IPEBPS_CREATE_HANDLE: {
  521. struct hfi_cmd_create_handle handle;
  522. handle.size = sizeof(struct hfi_cmd_create_handle);
  523. handle.pkt_type = type;
  524. handle.handle_type = (uint32_t)data;
  525. handle.user_data1 = 0;
  526. hfi_write_cmd(&handle);
  527. }
  528. break;
  529. case HFI_CMD_IPEBPS_ASYNC_COMMAND_INDIRECT:
  530. break;
  531. default:
  532. CAM_ERR(CAM_HFI, "command not supported :%d", type);
  533. break;
  534. }
  535. }
  536. int hfi_get_hw_caps(void *query_buf)
  537. {
  538. int i = 0;
  539. struct cam_icp_query_cap_cmd *query_cmd = NULL;
  540. if (!query_buf) {
  541. CAM_ERR(CAM_HFI, "query buf is NULL");
  542. return -EINVAL;
  543. }
  544. query_cmd = (struct cam_icp_query_cap_cmd *)query_buf;
  545. query_cmd->fw_version.major = 0x12;
  546. query_cmd->fw_version.minor = 0x12;
  547. query_cmd->fw_version.revision = 0x12;
  548. query_cmd->api_version.major = 0x13;
  549. query_cmd->api_version.minor = 0x13;
  550. query_cmd->api_version.revision = 0x13;
  551. query_cmd->num_ipe = 2;
  552. query_cmd->num_bps = 1;
  553. for (i = 0; i < CAM_ICP_DEV_TYPE_MAX; i++) {
  554. query_cmd->dev_ver[i].dev_type = i;
  555. query_cmd->dev_ver[i].hw_ver.major = 0x34 + i;
  556. query_cmd->dev_ver[i].hw_ver.minor = 0x34 + i;
  557. query_cmd->dev_ver[i].hw_ver.incr = 0x34 + i;
  558. }
  559. return 0;
  560. }
  561. int cam_hfi_resume(struct hfi_mem_info *hfi_mem)
  562. {
  563. int rc = 0;
  564. uint32_t fw_version, status = 0;
  565. void __iomem *icp_base = hfi_iface_addr(g_hfi);
  566. if (!icp_base) {
  567. CAM_ERR(CAM_HFI, "invalid HFI interface address");
  568. return -EINVAL;
  569. }
  570. if (cam_common_read_poll_timeout(icp_base +
  571. HFI_REG_ICP_HOST_INIT_RESPONSE,
  572. HFI_POLL_DELAY_US, HFI_POLL_TIMEOUT_US,
  573. (uint32_t)UINT_MAX, ICP_INIT_RESP_SUCCESS, &status)) {
  574. CAM_ERR(CAM_HFI, "response poll timed out: status=0x%08x",
  575. status);
  576. return -ETIMEDOUT;
  577. }
  578. hfi_irq_enable(g_hfi);
  579. fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION);
  580. CAM_DBG(CAM_HFI, "fw version : [%x]", fw_version);
  581. cam_io_w_mb((uint32_t)hfi_mem->qtbl.iova, icp_base + HFI_REG_QTBL_PTR);
  582. cam_io_w_mb((uint32_t)hfi_mem->sfr_buf.iova,
  583. icp_base + HFI_REG_SFR_PTR);
  584. cam_io_w_mb((uint32_t)hfi_mem->shmem.iova,
  585. icp_base + HFI_REG_SHARED_MEM_PTR);
  586. cam_io_w_mb((uint32_t)hfi_mem->shmem.len,
  587. icp_base + HFI_REG_SHARED_MEM_SIZE);
  588. cam_io_w_mb((uint32_t)hfi_mem->sec_heap.iova,
  589. icp_base + HFI_REG_SECONDARY_HEAP_PTR);
  590. cam_io_w_mb((uint32_t)hfi_mem->sec_heap.len,
  591. icp_base + HFI_REG_SECONDARY_HEAP_SIZE);
  592. cam_io_w_mb((uint32_t)hfi_mem->qdss.iova,
  593. icp_base + HFI_REG_QDSS_IOVA);
  594. cam_io_w_mb((uint32_t)hfi_mem->qdss.len,
  595. icp_base + HFI_REG_QDSS_IOVA_SIZE);
  596. cam_io_w_mb((uint32_t)hfi_mem->io_mem.iova,
  597. icp_base + HFI_REG_IO_REGION_IOVA);
  598. cam_io_w_mb((uint32_t)hfi_mem->io_mem.len,
  599. icp_base + HFI_REG_IO_REGION_SIZE);
  600. cam_io_w_mb((uint32_t)hfi_mem->io_mem2.iova,
  601. icp_base + HFI_REG_IO2_REGION_IOVA);
  602. cam_io_w_mb((uint32_t)hfi_mem->io_mem2.len,
  603. icp_base + HFI_REG_IO2_REGION_SIZE);
  604. cam_io_w_mb((uint32_t)hfi_mem->fw_uncached.iova,
  605. icp_base + HFI_REG_FWUNCACHED_REGION_IOVA);
  606. cam_io_w_mb((uint32_t)hfi_mem->fw_uncached.len,
  607. icp_base + HFI_REG_FWUNCACHED_REGION_SIZE);
  608. CAM_DBG(CAM_HFI, "IO1 : [0x%x 0x%x] IO2 [0x%x 0x%x]",
  609. hfi_mem->io_mem.iova, hfi_mem->io_mem.len,
  610. hfi_mem->io_mem2.iova, hfi_mem->io_mem2.len);
  611. CAM_DBG(CAM_HFI, "FwUncached : [0x%x 0x%x] Shared [0x%x 0x%x]",
  612. hfi_mem->fw_uncached.iova, hfi_mem->fw_uncached.len,
  613. hfi_mem->shmem.iova, hfi_mem->shmem.len);
  614. CAM_DBG(CAM_HFI, "SecHeap : [0x%x 0x%x] QDSS [0x%x 0x%x]",
  615. hfi_mem->sec_heap.iova, hfi_mem->sec_heap.len,
  616. hfi_mem->qdss.iova, hfi_mem->qdss.len);
  617. CAM_DBG(CAM_HFI, "QTbl : [0x%x 0x%x] Sfr [0x%x 0x%x]",
  618. hfi_mem->qtbl.iova, hfi_mem->qtbl.len,
  619. hfi_mem->sfr_buf.iova, hfi_mem->sfr_buf.len);
  620. return rc;
  621. }
  622. int cam_hfi_init(struct hfi_mem_info *hfi_mem, const struct hfi_ops *hfi_ops,
  623. void *priv, uint8_t event_driven_mode)
  624. {
  625. int rc = 0;
  626. uint32_t status = 0;
  627. struct hfi_qtbl *qtbl;
  628. struct hfi_qtbl_hdr *qtbl_hdr;
  629. struct hfi_q_hdr *cmd_q_hdr, *msg_q_hdr, *dbg_q_hdr;
  630. struct sfr_buf *sfr_buffer;
  631. void __iomem *icp_base;
  632. if (!hfi_mem || !hfi_ops || !priv) {
  633. CAM_ERR(CAM_HFI,
  634. "invalid arg: hfi_mem=%pK hfi_ops=%pK priv=%pK",
  635. hfi_mem, hfi_ops, priv);
  636. return -EINVAL;
  637. }
  638. mutex_lock(&hfi_cmd_q_mutex);
  639. mutex_lock(&hfi_msg_q_mutex);
  640. if (!g_hfi) {
  641. g_hfi = kzalloc(sizeof(struct hfi_info), GFP_KERNEL);
  642. if (!g_hfi) {
  643. rc = -ENOMEM;
  644. goto alloc_fail;
  645. }
  646. }
  647. if (g_hfi->hfi_state != HFI_DEINIT) {
  648. CAM_ERR(CAM_HFI, "hfi_init: invalid state");
  649. rc = -EINVAL;
  650. goto regions_fail;
  651. }
  652. memcpy(&g_hfi->map, hfi_mem, sizeof(g_hfi->map));
  653. g_hfi->hfi_state = HFI_DEINIT;
  654. qtbl = (struct hfi_qtbl *)hfi_mem->qtbl.kva;
  655. qtbl_hdr = &qtbl->q_tbl_hdr;
  656. qtbl_hdr->qtbl_version = 0xFFFFFFFF;
  657. qtbl_hdr->qtbl_size = sizeof(struct hfi_qtbl);
  658. qtbl_hdr->qtbl_qhdr0_offset = sizeof(struct hfi_qtbl_hdr);
  659. qtbl_hdr->qtbl_qhdr_size = sizeof(struct hfi_q_hdr);
  660. qtbl_hdr->qtbl_num_q = ICP_HFI_NUMBER_OF_QS;
  661. qtbl_hdr->qtbl_num_active_q = ICP_HFI_NUMBER_OF_QS;
  662. /* setup host-to-firmware command queue */
  663. cmd_q_hdr = &qtbl->q_hdr[Q_CMD];
  664. cmd_q_hdr->qhdr_status = QHDR_ACTIVE;
  665. cmd_q_hdr->qhdr_start_addr = hfi_mem->cmd_q.iova;
  666. cmd_q_hdr->qhdr_q_size = ICP_CMD_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT;
  667. cmd_q_hdr->qhdr_pkt_size = ICP_HFI_VAR_SIZE_PKT;
  668. cmd_q_hdr->qhdr_pkt_drop_cnt = RESET;
  669. cmd_q_hdr->qhdr_read_idx = RESET;
  670. cmd_q_hdr->qhdr_write_idx = RESET;
  671. /* setup firmware-to-Host message queue */
  672. msg_q_hdr = &qtbl->q_hdr[Q_MSG];
  673. msg_q_hdr->qhdr_status = QHDR_ACTIVE;
  674. msg_q_hdr->qhdr_start_addr = hfi_mem->msg_q.iova;
  675. msg_q_hdr->qhdr_q_size = ICP_MSG_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT;
  676. msg_q_hdr->qhdr_pkt_size = ICP_HFI_VAR_SIZE_PKT;
  677. msg_q_hdr->qhdr_pkt_drop_cnt = RESET;
  678. msg_q_hdr->qhdr_read_idx = RESET;
  679. msg_q_hdr->qhdr_write_idx = RESET;
  680. /* setup firmware-to-Host message queue */
  681. dbg_q_hdr = &qtbl->q_hdr[Q_DBG];
  682. dbg_q_hdr->qhdr_status = QHDR_ACTIVE;
  683. dbg_q_hdr->qhdr_start_addr = hfi_mem->dbg_q.iova;
  684. dbg_q_hdr->qhdr_q_size = ICP_DBG_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT;
  685. dbg_q_hdr->qhdr_pkt_size = ICP_HFI_VAR_SIZE_PKT;
  686. dbg_q_hdr->qhdr_pkt_drop_cnt = RESET;
  687. dbg_q_hdr->qhdr_read_idx = RESET;
  688. dbg_q_hdr->qhdr_write_idx = RESET;
  689. sfr_buffer = (struct sfr_buf *)hfi_mem->sfr_buf.kva;
  690. sfr_buffer->size = ICP_MSG_SFR_SIZE_IN_BYTES;
  691. switch (event_driven_mode) {
  692. case INTR_MODE:
  693. cmd_q_hdr->qhdr_type = Q_CMD;
  694. cmd_q_hdr->qhdr_rx_wm = SET;
  695. cmd_q_hdr->qhdr_tx_wm = SET;
  696. cmd_q_hdr->qhdr_rx_req = SET;
  697. cmd_q_hdr->qhdr_tx_req = RESET;
  698. cmd_q_hdr->qhdr_rx_irq_status = RESET;
  699. cmd_q_hdr->qhdr_tx_irq_status = RESET;
  700. msg_q_hdr->qhdr_type = Q_MSG;
  701. msg_q_hdr->qhdr_rx_wm = SET;
  702. msg_q_hdr->qhdr_tx_wm = SET;
  703. msg_q_hdr->qhdr_rx_req = SET;
  704. msg_q_hdr->qhdr_tx_req = RESET;
  705. msg_q_hdr->qhdr_rx_irq_status = RESET;
  706. msg_q_hdr->qhdr_tx_irq_status = RESET;
  707. dbg_q_hdr->qhdr_type = Q_DBG;
  708. dbg_q_hdr->qhdr_rx_wm = SET;
  709. dbg_q_hdr->qhdr_tx_wm = SET_WM;
  710. dbg_q_hdr->qhdr_rx_req = RESET;
  711. dbg_q_hdr->qhdr_tx_req = RESET;
  712. dbg_q_hdr->qhdr_rx_irq_status = RESET;
  713. dbg_q_hdr->qhdr_tx_irq_status = RESET;
  714. break;
  715. case POLL_MODE:
  716. cmd_q_hdr->qhdr_type = Q_CMD | TX_EVENT_POLL_MODE_2 |
  717. RX_EVENT_POLL_MODE_2;
  718. msg_q_hdr->qhdr_type = Q_MSG | TX_EVENT_POLL_MODE_2 |
  719. RX_EVENT_POLL_MODE_2;
  720. dbg_q_hdr->qhdr_type = Q_DBG | TX_EVENT_POLL_MODE_2 |
  721. RX_EVENT_POLL_MODE_2;
  722. break;
  723. case WM_MODE:
  724. cmd_q_hdr->qhdr_type = Q_CMD | TX_EVENT_DRIVEN_MODE_2 |
  725. RX_EVENT_DRIVEN_MODE_2;
  726. cmd_q_hdr->qhdr_rx_wm = SET;
  727. cmd_q_hdr->qhdr_tx_wm = SET;
  728. cmd_q_hdr->qhdr_rx_req = RESET;
  729. cmd_q_hdr->qhdr_tx_req = SET;
  730. cmd_q_hdr->qhdr_rx_irq_status = RESET;
  731. cmd_q_hdr->qhdr_tx_irq_status = RESET;
  732. msg_q_hdr->qhdr_type = Q_MSG | TX_EVENT_DRIVEN_MODE_2 |
  733. RX_EVENT_DRIVEN_MODE_2;
  734. msg_q_hdr->qhdr_rx_wm = SET;
  735. msg_q_hdr->qhdr_tx_wm = SET;
  736. msg_q_hdr->qhdr_rx_req = SET;
  737. msg_q_hdr->qhdr_tx_req = RESET;
  738. msg_q_hdr->qhdr_rx_irq_status = RESET;
  739. msg_q_hdr->qhdr_tx_irq_status = RESET;
  740. dbg_q_hdr->qhdr_type = Q_DBG | TX_EVENT_DRIVEN_MODE_2 |
  741. RX_EVENT_DRIVEN_MODE_2;
  742. dbg_q_hdr->qhdr_rx_wm = SET;
  743. dbg_q_hdr->qhdr_tx_wm = SET_WM;
  744. dbg_q_hdr->qhdr_rx_req = RESET;
  745. dbg_q_hdr->qhdr_tx_req = RESET;
  746. dbg_q_hdr->qhdr_rx_irq_status = RESET;
  747. dbg_q_hdr->qhdr_tx_irq_status = RESET;
  748. break;
  749. default:
  750. CAM_ERR(CAM_HFI, "Invalid event driven mode :%u",
  751. event_driven_mode);
  752. break;
  753. }
  754. g_hfi->ops = *hfi_ops;
  755. g_hfi->priv = priv;
  756. icp_base = hfi_iface_addr(g_hfi);
  757. if (!icp_base) {
  758. CAM_ERR(CAM_HFI, "invalid HFI interface address");
  759. rc = -EINVAL;
  760. goto regions_fail;
  761. }
  762. cam_io_w_mb((uint32_t)hfi_mem->qtbl.iova,
  763. icp_base + HFI_REG_QTBL_PTR);
  764. cam_io_w_mb((uint32_t)hfi_mem->sfr_buf.iova,
  765. icp_base + HFI_REG_SFR_PTR);
  766. cam_io_w_mb((uint32_t)hfi_mem->shmem.iova,
  767. icp_base + HFI_REG_SHARED_MEM_PTR);
  768. cam_io_w_mb((uint32_t)hfi_mem->shmem.len,
  769. icp_base + HFI_REG_SHARED_MEM_SIZE);
  770. cam_io_w_mb((uint32_t)hfi_mem->sec_heap.iova,
  771. icp_base + HFI_REG_SECONDARY_HEAP_PTR);
  772. cam_io_w_mb((uint32_t)hfi_mem->sec_heap.len,
  773. icp_base + HFI_REG_SECONDARY_HEAP_SIZE);
  774. cam_io_w_mb((uint32_t)hfi_mem->qdss.iova,
  775. icp_base + HFI_REG_QDSS_IOVA);
  776. cam_io_w_mb((uint32_t)hfi_mem->qdss.len,
  777. icp_base + HFI_REG_QDSS_IOVA_SIZE);
  778. cam_io_w_mb((uint32_t)hfi_mem->io_mem.iova,
  779. icp_base + HFI_REG_IO_REGION_IOVA);
  780. cam_io_w_mb((uint32_t)hfi_mem->io_mem.len,
  781. icp_base + HFI_REG_IO_REGION_SIZE);
  782. cam_io_w_mb((uint32_t)hfi_mem->io_mem2.iova,
  783. icp_base + HFI_REG_IO2_REGION_IOVA);
  784. cam_io_w_mb((uint32_t)hfi_mem->io_mem2.len,
  785. icp_base + HFI_REG_IO2_REGION_SIZE);
  786. cam_io_w_mb((uint32_t)hfi_mem->fw_uncached.iova,
  787. icp_base + HFI_REG_FWUNCACHED_REGION_IOVA);
  788. cam_io_w_mb((uint32_t)hfi_mem->fw_uncached.len,
  789. icp_base + HFI_REG_FWUNCACHED_REGION_SIZE);
  790. CAM_DBG(CAM_HFI, "IO1 : [0x%x 0x%x] IO2 [0x%x 0x%x]",
  791. hfi_mem->io_mem.iova, hfi_mem->io_mem.len,
  792. hfi_mem->io_mem2.iova, hfi_mem->io_mem2.len);
  793. CAM_DBG(CAM_HFI, "FwUncached : [0x%x 0x%x] Shared [0x%x 0x%x]",
  794. hfi_mem->fw_uncached.iova, hfi_mem->fw_uncached.len,
  795. hfi_mem->shmem.iova, hfi_mem->shmem.len);
  796. CAM_DBG(CAM_HFI, "SecHeap : [0x%x 0x%x] QDSS [0x%x 0x%x]",
  797. hfi_mem->sec_heap.iova, hfi_mem->sec_heap.len,
  798. hfi_mem->qdss.iova, hfi_mem->qdss.len);
  799. CAM_DBG(CAM_HFI, "QTbl : [0x%x 0x%x] Sfr [0x%x 0x%x]",
  800. hfi_mem->qtbl.iova, hfi_mem->qtbl.len,
  801. hfi_mem->sfr_buf.iova, hfi_mem->sfr_buf.len);
  802. if (cam_presil_mode_enabled())
  803. cam_hfi_presil_setup(hfi_mem);
  804. cam_io_w_mb((uint32_t)ICP_INIT_REQUEST_SET,
  805. icp_base + HFI_REG_HOST_ICP_INIT_REQUEST);
  806. if (cam_presil_mode_enabled())
  807. cam_hfi_presil_set_init_request();
  808. if (cam_common_read_poll_timeout(icp_base +
  809. HFI_REG_ICP_HOST_INIT_RESPONSE,
  810. HFI_POLL_DELAY_US, HFI_POLL_TIMEOUT_US,
  811. (uint32_t)UINT_MAX, ICP_INIT_RESP_SUCCESS, &status)) {
  812. CAM_ERR(CAM_HFI, "response poll timed out: status=0x%08x",
  813. status);
  814. rc = -ETIMEDOUT;
  815. goto regions_fail;
  816. }
  817. CAM_DBG(CAM_HFI, "ICP fw version: 0x%x",
  818. cam_io_r(icp_base + HFI_REG_FW_VERSION));
  819. g_hfi->hfi_state = HFI_READY;
  820. g_hfi->cmd_q_state = true;
  821. g_hfi->msg_q_state = true;
  822. hfi_irq_enable(g_hfi);
  823. mutex_unlock(&hfi_cmd_q_mutex);
  824. mutex_unlock(&hfi_msg_q_mutex);
  825. return rc;
  826. regions_fail:
  827. kfree(g_hfi);
  828. g_hfi = NULL;
  829. alloc_fail:
  830. mutex_unlock(&hfi_cmd_q_mutex);
  831. mutex_unlock(&hfi_msg_q_mutex);
  832. return rc;
  833. }
  834. void cam_hfi_deinit(void)
  835. {
  836. if (cam_presil_mode_enabled()) {
  837. CAM_DBG(CAM_HFI, "SYS_RESET Needed in presil for back to back hfi_init success");
  838. hfi_send_system_cmd(HFI_CMD_SYS_RESET, 0, 0);
  839. }
  840. mutex_lock(&hfi_cmd_q_mutex);
  841. mutex_lock(&hfi_msg_q_mutex);
  842. if (!g_hfi) {
  843. CAM_ERR(CAM_HFI, "hfi path not established yet");
  844. goto err;
  845. }
  846. g_hfi->cmd_q_state = false;
  847. g_hfi->msg_q_state = false;
  848. cam_free_clear((void *)g_hfi);
  849. g_hfi = NULL;
  850. err:
  851. mutex_unlock(&hfi_cmd_q_mutex);
  852. mutex_unlock(&hfi_msg_q_mutex);
  853. }
  854. #ifdef CONFIG_CAM_PRESIL
  855. static int cam_hfi_presil_setup(struct hfi_mem_info *hfi_mem)
  856. {
  857. /**
  858. * The pchost maintains its own set of queue structures and
  859. * needs additional info to accomplish this. Use the set of
  860. * dummy registers to pass along this info.
  861. */
  862. /**
  863. * IOVA region length for each queue is currently hardcoded in
  864. * pchost (except for SFR). No need to send for now.
  865. */
  866. cam_presil_send_event(CAM_PRESIL_EVENT_HFI_REG_CMD_Q_IOVA, hfi_mem->cmd_q.iova);
  867. cam_presil_send_event(CAM_PRESIL_EVENT_HFI_REG_MSG_Q_IOVA, hfi_mem->msg_q.iova);
  868. cam_presil_send_event(CAM_PRESIL_EVENT_HFI_REG_DBG_Q_IOVA, hfi_mem->dbg_q.iova);
  869. cam_presil_send_event(CAM_PRESIL_EVENT_HFI_REG_SFR_LEN, hfi_mem->sfr_buf.len);
  870. return 0;
  871. }
  872. static int cam_hfi_presil_set_init_request(void)
  873. {
  874. CAM_DBG(CAM_PRESIL, "notifying pchost to start HFI init...");
  875. cam_presil_send_event(CAM_PRESIL_EVENT_HFI_REG_ICP_V1_HW_VERSION_TO_START_HFI_INIT, 0xFF);
  876. CAM_DBG(CAM_PRESIL, "got done with PCHOST HFI init...");
  877. return 0;
  878. }
  879. int hfi_write_cmd(void *cmd_ptr)
  880. {
  881. int presil_rc = CAM_PRESIL_BLOCKED;
  882. int rc = 0;
  883. if (!cmd_ptr) {
  884. CAM_ERR(CAM_HFI, "command is null");
  885. return -EINVAL;
  886. }
  887. mutex_lock(&hfi_cmd_q_mutex);
  888. presil_rc = cam_presil_hfi_write_cmd(cmd_ptr, (*(uint32_t *)cmd_ptr),
  889. CAM_PRESIL_CLIENT_ID_CAMERA);
  890. if ((presil_rc != CAM_PRESIL_SUCCESS) && (presil_rc != CAM_PRESIL_BLOCKED)) {
  891. CAM_ERR(CAM_HFI, "failed presil rc %d", presil_rc);
  892. rc = -EINVAL;
  893. } else {
  894. CAM_DBG(CAM_HFI, "presil rc %d", presil_rc);
  895. }
  896. mutex_unlock(&hfi_cmd_q_mutex);
  897. return rc;
  898. }
  899. int hfi_read_message(uint32_t *pmsg, uint8_t q_id,
  900. uint32_t *words_read)
  901. {
  902. int presil_rc = CAM_PRESIL_BLOCKED;
  903. int rc = 0;
  904. if (!pmsg) {
  905. CAM_ERR(CAM_HFI, "Invalid msg");
  906. return -EINVAL;
  907. }
  908. if (q_id > Q_DBG) {
  909. CAM_ERR(CAM_HFI, "Invalid q :%u", q_id);
  910. return -EINVAL;
  911. }
  912. mutex_lock(&hfi_msg_q_mutex);
  913. memset(pmsg, 0x0, sizeof(uint32_t) * 256 /* ICP_MSG_BUF_SIZE */);
  914. *words_read = 0;
  915. presil_rc = cam_presil_hfi_read_message(pmsg, q_id, words_read,
  916. CAM_PRESIL_CLIENT_ID_CAMERA);
  917. if ((presil_rc != CAM_PRESIL_SUCCESS) && (presil_rc != CAM_PRESIL_BLOCKED)) {
  918. CAM_ERR(CAM_HFI, "failed presil rc %d", presil_rc);
  919. rc = -EINVAL;
  920. } else {
  921. CAM_DBG(CAM_HFI, "presil rc %d", presil_rc);
  922. }
  923. mutex_unlock(&hfi_msg_q_mutex);
  924. return rc;
  925. }
  926. #else
  927. /* when presil mode not enabled */
  928. static int cam_hfi_presil_setup(struct hfi_mem_info *hfi_mem)
  929. {
  930. return 0;
  931. }
  932. static int cam_hfi_presil_set_init_request(void)
  933. {
  934. return 0;
  935. }
  936. #endif /* #ifdef CONFIG_CAM_PRESIL */