blob: 68b50dad4bdb59c9dc9527d542668f5e87ef200e [file] [log] [blame]
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -07001/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070013#include <linux/io.h>
14#include <linux/delay.h>
15#include <linux/slab.h>
16#include <linux/random.h>
17#include <asm/errno.h>
18#include <linux/timer.h>
19#include <media/cam_icp.h>
Lakshmi Narayana Kalavala2743a0d2017-05-30 10:41:37 -070020#include <linux/iopoll.h>
Jigarkumar Zalaa32fc7b2017-08-22 16:25:34 -070021#include <soc/qcom/socinfo.h>
Lakshmi Narayana Kalavala2743a0d2017-05-30 10:41:37 -070022
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070023#include "cam_io_util.h"
24#include "hfi_reg.h"
25#include "hfi_sys_defs.h"
26#include "hfi_session_defs.h"
27#include "hfi_intf.h"
28#include "cam_icp_hw_mgr_intf.h"
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -070029#include "cam_debug_util.h"
Suresh Vankadaraaa6ff8f2017-10-26 22:51:27 +053030#include "cam_soc_util.h"
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070031
32#define HFI_VERSION_INFO_MAJOR_VAL 1
33#define HFI_VERSION_INFO_MINOR_VAL 1
34#define HFI_VERSION_INFO_STEP_VAL 0
35#define HFI_VERSION_INFO_STEP_VAL 0
36#define HFI_VERSION_INFO_MAJOR_BMSK 0xFF000000
37#define HFI_VERSION_INFO_MAJOR_SHFT 24
38#define HFI_VERSION_INFO_MINOR_BMSK 0xFFFF00
39#define HFI_VERSION_INFO_MINOR_SHFT 8
40#define HFI_VERSION_INFO_STEP_BMSK 0xFF
41#define HFI_VERSION_INFO_STEP_SHFT 0
42
Alok Pandey78093d32017-11-08 18:56:54 +053043#define HFI_MAX_POLL_TRY 5
44
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -070045static struct hfi_info *g_hfi;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070046unsigned int g_icp_mmu_hdl;
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -070047static DEFINE_MUTEX(hfi_cmd_q_mutex);
48static DEFINE_MUTEX(hfi_msg_q_mutex);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070049
50int hfi_write_cmd(void *cmd_ptr)
51{
52 uint32_t size_in_words, empty_space, new_write_idx, read_idx, temp;
53 uint32_t *write_q, *write_ptr;
54 struct hfi_qtbl *q_tbl;
55 struct hfi_q_hdr *q;
56 int rc = 0;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070057
58 if (!cmd_ptr) {
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -070059 CAM_ERR(CAM_HFI, "command is null");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070060 return -EINVAL;
61 }
62
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -070063 mutex_lock(&hfi_cmd_q_mutex);
64 if (!g_hfi) {
65 CAM_ERR(CAM_HFI, "HFI interface not setup");
66 rc = -ENODEV;
67 goto err;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070068 }
69
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -070070 if (g_hfi->hfi_state != HFI_READY ||
71 !g_hfi->cmd_q_state) {
72 CAM_ERR(CAM_HFI, "HFI state: %u, cmd q state: %u",
73 g_hfi->hfi_state, g_hfi->cmd_q_state);
74 rc = -ENODEV;
75 goto err;
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -070076 }
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070077
78 q_tbl = (struct hfi_qtbl *)g_hfi->map.qtbl.kva;
79 q = &q_tbl->q_hdr[Q_CMD];
80
81 write_q = (uint32_t *)g_hfi->map.cmd_q.kva;
82
83 size_in_words = (*(uint32_t *)cmd_ptr) >> BYTE_WORD_SHIFT;
84 if (!size_in_words) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -070085 CAM_DBG(CAM_HFI, "failed");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070086 rc = -EINVAL;
87 goto err;
88 }
89
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070090 read_idx = q->qhdr_read_idx;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070091 empty_space = (q->qhdr_write_idx >= read_idx) ?
92 (q->qhdr_q_size - (q->qhdr_write_idx - read_idx)) :
93 (read_idx - q->qhdr_write_idx);
94 if (empty_space <= size_in_words) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -070095 CAM_ERR(CAM_HFI, "failed");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070096 rc = -EIO;
97 goto err;
98 }
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -070099
100 new_write_idx = q->qhdr_write_idx + size_in_words;
101 write_ptr = (uint32_t *)(write_q + q->qhdr_write_idx);
102
103 if (new_write_idx < q->qhdr_q_size) {
104 memcpy(write_ptr, (uint8_t *)cmd_ptr,
105 size_in_words << BYTE_WORD_SHIFT);
106 } else {
107 new_write_idx -= q->qhdr_q_size;
108 temp = (size_in_words - new_write_idx) << BYTE_WORD_SHIFT;
109 memcpy(write_ptr, (uint8_t *)cmd_ptr, temp);
110 memcpy(write_q, (uint8_t *)cmd_ptr + temp,
111 new_write_idx << BYTE_WORD_SHIFT);
112 }
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700113
Suresh Vankadarae1ce24d2017-11-15 09:08:35 +0530114 /*
115 * To make sure command data in a command queue before
116 * updating write index
117 */
118 wmb();
119
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700120 q->qhdr_write_idx = new_write_idx;
Suresh Vankadarae1ce24d2017-11-15 09:08:35 +0530121
122 /*
123 * Before raising interrupt make sure command data is ready for
124 * firmware to process
125 */
126 wmb();
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700127 cam_io_w((uint32_t)INTR_ENABLE,
128 g_hfi->csr_base + HFI_REG_A5_CSR_HOST2ICPINT);
129err:
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700130 mutex_unlock(&hfi_cmd_q_mutex);
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700131 return rc;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700132}
133
Karthik Anantha Ramad347282017-11-01 13:09:17 -0700134int hfi_read_message(uint32_t *pmsg, uint8_t q_id,
135 uint32_t *words_read)
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700136{
137 struct hfi_qtbl *q_tbl_ptr;
138 struct hfi_q_hdr *q;
Lakshmi Narayana Kalavaladac0b6c2017-09-13 15:33:42 -0700139 uint32_t new_read_idx, size_in_words, word_diff, temp;
140 uint32_t *read_q, *read_ptr, *write_ptr;
Karthik Anantha Ramad347282017-11-01 13:09:17 -0700141 int rc = 0;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700142
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700143 if (!pmsg) {
144 CAM_ERR(CAM_HFI, "Invalid msg");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700145 return -EINVAL;
146 }
147
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700148 if (q_id > Q_DBG) {
149 CAM_ERR(CAM_HFI, "Inavlid q :%u", q_id);
150 return -EINVAL;
151 }
152
153 mutex_lock(&hfi_msg_q_mutex);
154 if (!g_hfi) {
155 CAM_ERR(CAM_HFI, "hfi not set up yet");
156 rc = -ENODEV;
157 goto err;
158 }
159
160 if ((g_hfi->hfi_state != HFI_READY) ||
161 !g_hfi->msg_q_state) {
162 CAM_ERR(CAM_HFI, "hfi state: %u, msg q state: %u",
163 g_hfi->hfi_state, g_hfi->msg_q_state);
164 rc = -ENODEV;
165 goto err;
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700166 }
167
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700168 q_tbl_ptr = (struct hfi_qtbl *)g_hfi->map.qtbl.kva;
169 q = &q_tbl_ptr->q_hdr[q_id];
170
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700171 if (q->qhdr_read_idx == q->qhdr_write_idx) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700172 CAM_DBG(CAM_HFI, "Q not ready, state:%u, r idx:%u, w idx:%u",
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700173 g_hfi->hfi_state, q->qhdr_read_idx, q->qhdr_write_idx);
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700174 rc = -EIO;
175 goto err;
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700176 }
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700177
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700178 if (q_id == Q_MSG)
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700179 read_q = (uint32_t *)g_hfi->map.msg_q.kva;
180 else
181 read_q = (uint32_t *)g_hfi->map.dbg_q.kva;
182
183 read_ptr = (uint32_t *)(read_q + q->qhdr_read_idx);
Lakshmi Narayana Kalavaladac0b6c2017-09-13 15:33:42 -0700184 write_ptr = (uint32_t *)(read_q + q->qhdr_write_idx);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700185
Lakshmi Narayana Kalavaladac0b6c2017-09-13 15:33:42 -0700186 if (write_ptr > read_ptr)
187 size_in_words = write_ptr - read_ptr;
188 else {
189 word_diff = read_ptr - write_ptr;
190 if (q_id == Q_MSG)
191 size_in_words = (ICP_MSG_Q_SIZE_IN_BYTES >>
192 BYTE_WORD_SHIFT) - word_diff;
193 else
194 size_in_words = (ICP_DBG_Q_SIZE_IN_BYTES >>
195 BYTE_WORD_SHIFT) - word_diff;
196 }
197
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700198 if ((size_in_words == 0) ||
Lakshmi Narayana Kalavaladac0b6c2017-09-13 15:33:42 -0700199 (size_in_words > ICP_HFI_MAX_PKT_SIZE_IN_WORDS)) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700200 CAM_ERR(CAM_HFI, "invalid HFI message packet size - 0x%08x",
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700201 size_in_words << BYTE_WORD_SHIFT);
202 q->qhdr_read_idx = q->qhdr_write_idx;
203 rc = -EIO;
204 goto err;
205 }
206
207 new_read_idx = q->qhdr_read_idx + size_in_words;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700208
209 if (new_read_idx < q->qhdr_q_size) {
210 memcpy(pmsg, read_ptr, size_in_words << BYTE_WORD_SHIFT);
211 } else {
212 new_read_idx -= q->qhdr_q_size;
213 temp = (size_in_words - new_read_idx) << BYTE_WORD_SHIFT;
214 memcpy(pmsg, read_ptr, temp);
215 memcpy((uint8_t *)pmsg + temp, read_q,
216 new_read_idx << BYTE_WORD_SHIFT);
217 }
218
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700219 q->qhdr_read_idx = new_read_idx;
Karthik Anantha Ramad347282017-11-01 13:09:17 -0700220 *words_read = size_in_words;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700221err:
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700222 mutex_unlock(&hfi_msg_q_mutex);
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700223 return rc;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700224}
225
Suresh Vankadaraaa6ff8f2017-10-26 22:51:27 +0530226int hfi_cmd_ubwc_config(uint32_t *ubwc_cfg)
227{
228 uint8_t *prop;
229 struct hfi_cmd_prop *dbg_prop;
230 uint32_t size = 0;
231
232 size = sizeof(struct hfi_cmd_prop) +
233 sizeof(struct hfi_cmd_ubwc_cfg);
234
235 prop = kzalloc(size, GFP_KERNEL);
236 if (!prop)
237 return -ENOMEM;
238
239 dbg_prop = (struct hfi_cmd_prop *)prop;
240 dbg_prop->size = size;
241 dbg_prop->pkt_type = HFI_CMD_SYS_SET_PROPERTY;
242 dbg_prop->num_prop = 1;
243 dbg_prop->prop_data[0] = HFI_PROP_SYS_UBWC_CFG;
244 dbg_prop->prop_data[1] = ubwc_cfg[0];
245 dbg_prop->prop_data[2] = ubwc_cfg[1];
246
247 hfi_write_cmd(prop);
248 kfree(prop);
249
250 return 0;
251}
252
Alok Pandey78093d32017-11-08 18:56:54 +0530253int hfi_enable_ipe_bps_pc(bool enable, uint32_t core_info)
Suresh Vankadara6657bc22017-07-31 10:33:04 +0530254{
255 uint8_t *prop;
256 struct hfi_cmd_prop *dbg_prop;
257 uint32_t size = 0;
258
259 size = sizeof(struct hfi_cmd_prop) +
260 sizeof(struct hfi_ipe_bps_pc);
261
262 prop = kzalloc(size, GFP_KERNEL);
263 if (!prop)
264 return -ENOMEM;
265
266 dbg_prop = (struct hfi_cmd_prop *)prop;
267 dbg_prop->size = size;
268 dbg_prop->pkt_type = HFI_CMD_SYS_SET_PROPERTY;
269 dbg_prop->num_prop = 1;
270 dbg_prop->prop_data[0] = HFI_PROP_SYS_IPEBPS_PC;
271 dbg_prop->prop_data[1] = enable;
Alok Pandey78093d32017-11-08 18:56:54 +0530272 dbg_prop->prop_data[2] = core_info;
Suresh Vankadara6657bc22017-07-31 10:33:04 +0530273
274 hfi_write_cmd(prop);
275 kfree(prop);
276
277 return 0;
278}
279
Lakshmi Narayana Kalavaladac0b6c2017-09-13 15:33:42 -0700280int hfi_set_debug_level(uint32_t lvl)
281{
282 uint8_t *prop;
283 struct hfi_cmd_prop *dbg_prop;
284 uint32_t size = 0, val;
285
286 val = HFI_DEBUG_MSG_LOW |
287 HFI_DEBUG_MSG_MEDIUM |
288 HFI_DEBUG_MSG_HIGH |
289 HFI_DEBUG_MSG_ERROR |
290 HFI_DEBUG_MSG_FATAL |
291 HFI_DEBUG_MSG_PERF |
292 HFI_DEBUG_CFG_WFI |
293 HFI_DEBUG_CFG_ARM9WD;
294
295 if (lvl > val)
296 return -EINVAL;
297
298 size = sizeof(struct hfi_cmd_prop) +
299 sizeof(struct hfi_debug);
300
301 prop = kzalloc(size, GFP_KERNEL);
302 if (!prop)
303 return -ENOMEM;
304
305 dbg_prop = (struct hfi_cmd_prop *)prop;
306 dbg_prop->size = size;
307 dbg_prop->pkt_type = HFI_CMD_SYS_SET_PROPERTY;
308 dbg_prop->num_prop = 1;
309 dbg_prop->prop_data[0] = HFI_PROP_SYS_DEBUG_CFG;
310 dbg_prop->prop_data[1] = lvl;
311 dbg_prop->prop_data[2] = HFI_DEBUG_MODE_QUEUE;
312
313 hfi_write_cmd(prop);
314 kfree(prop);
315
316 return 0;
317}
318
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700319void hfi_send_system_cmd(uint32_t type, uint64_t data, uint32_t size)
320{
321 switch (type) {
322 case HFI_CMD_SYS_INIT: {
323 struct hfi_cmd_sys_init init;
324
325 memset(&init, 0, sizeof(init));
326
327 init.size = sizeof(struct hfi_cmd_sys_init);
328 init.pkt_type = type;
329 hfi_write_cmd(&init);
330 }
331 break;
332 case HFI_CMD_SYS_PC_PREP: {
333 struct hfi_cmd_pc_prep prep;
334
335 prep.size = sizeof(struct hfi_cmd_pc_prep);
336 prep.pkt_type = type;
337 hfi_write_cmd(&prep);
338 }
339 break;
340 case HFI_CMD_SYS_SET_PROPERTY: {
341 struct hfi_cmd_prop prop;
342
343 if ((uint32_t)data == (uint32_t)HFI_PROP_SYS_DEBUG_CFG) {
344 prop.size = sizeof(struct hfi_cmd_prop);
345 prop.pkt_type = type;
346 prop.num_prop = 1;
347 prop.prop_data[0] = HFI_PROP_SYS_DEBUG_CFG;
348 hfi_write_cmd(&prop);
349 }
350 }
351 break;
352 case HFI_CMD_SYS_GET_PROPERTY:
353 break;
354 case HFI_CMD_SYS_PING: {
355 struct hfi_cmd_ping_pkt ping;
356
357 ping.size = sizeof(struct hfi_cmd_ping_pkt);
358 ping.pkt_type = type;
359 ping.user_data = (uint64_t)data;
360 hfi_write_cmd(&ping);
361 }
362 break;
363 case HFI_CMD_SYS_RESET: {
364 struct hfi_cmd_sys_reset_pkt reset;
365
366 reset.size = sizeof(struct hfi_cmd_sys_reset_pkt);
367 reset.pkt_type = type;
368 reset.user_data = (uint64_t)data;
369 hfi_write_cmd(&reset);
370 }
371 break;
372 case HFI_CMD_IPEBPS_CREATE_HANDLE: {
373 struct hfi_cmd_create_handle handle;
374
375 handle.size = sizeof(struct hfi_cmd_create_handle);
376 handle.pkt_type = type;
377 handle.handle_type = (uint32_t)data;
378 handle.user_data1 = 0;
379 hfi_write_cmd(&handle);
380 }
381 break;
382 case HFI_CMD_IPEBPS_ASYNC_COMMAND_INDIRECT:
383 break;
384 default:
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700385 CAM_ERR(CAM_HFI, "command not supported :%d", type);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700386 break;
387 }
388}
389
390
391int hfi_get_hw_caps(void *query_buf)
392{
393 int i = 0;
394 struct cam_icp_query_cap_cmd *query_cmd = NULL;
395
396 if (!query_buf) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700397 CAM_ERR(CAM_HFI, "query buf is NULL");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700398 return -EINVAL;
399 }
400
401 query_cmd = (struct cam_icp_query_cap_cmd *)query_buf;
402 query_cmd->fw_version.major = 0x12;
403 query_cmd->fw_version.minor = 0x12;
404 query_cmd->fw_version.revision = 0x12;
405
406 query_cmd->api_version.major = 0x13;
407 query_cmd->api_version.minor = 0x13;
408 query_cmd->api_version.revision = 0x13;
409
410 query_cmd->num_ipe = 2;
411 query_cmd->num_bps = 1;
412
413 for (i = 0; i < CAM_ICP_DEV_TYPE_MAX; i++) {
414 query_cmd->dev_ver[i].dev_type = i;
415 query_cmd->dev_ver[i].hw_ver.major = 0x34 + i;
416 query_cmd->dev_ver[i].hw_ver.minor = 0x34 + i;
417 query_cmd->dev_ver[i].hw_ver.incr = 0x34 + i;
418 }
419 return 0;
420}
421
Suresh Vankadarad8905f42017-06-04 13:33:49 +0530422void cam_hfi_disable_cpu(void __iomem *icp_base)
423{
424 uint32_t data;
425 uint32_t val;
Alok Pandey78093d32017-11-08 18:56:54 +0530426 uint32_t try = 0;
Suresh Vankadarad8905f42017-06-04 13:33:49 +0530427
428 data = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_STATUS);
Alok Pandey78093d32017-11-08 18:56:54 +0530429
430 while (try < HFI_MAX_POLL_TRY) {
431 data = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_STATUS);
432 CAM_DBG(CAM_HFI, "wfi status = %x\n", (int)data);
433
434 if (data & ICP_CSR_A5_STATUS_WFI)
435 break;
436
437 msleep(100);
438 try++;
Suresh Vankadarad8905f42017-06-04 13:33:49 +0530439 }
Alok Pandey78093d32017-11-08 18:56:54 +0530440
441 val = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_CONTROL);
442 val &= ~(ICP_FLAG_CSR_A5_EN | ICP_FLAG_CSR_WAKE_UP_EN);
443 cam_io_w(val, icp_base + HFI_REG_A5_CSR_A5_CONTROL);
444
445 val = cam_io_r(icp_base + HFI_REG_A5_CSR_NSEC_RESET);
446 cam_io_w(val, icp_base + HFI_REG_A5_CSR_NSEC_RESET);
Suresh Vankadarad8905f42017-06-04 13:33:49 +0530447}
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700448
449void cam_hfi_enable_cpu(void __iomem *icp_base)
450{
451 cam_io_w((uint32_t)ICP_FLAG_CSR_A5_EN,
452 icp_base + HFI_REG_A5_CSR_A5_CONTROL);
453 cam_io_w((uint32_t)0x10, icp_base + HFI_REG_A5_CSR_NSEC_RESET);
454}
455
Alok Pandey78093d32017-11-08 18:56:54 +0530456int cam_hfi_resume(struct hfi_mem_info *hfi_mem,
457 void __iomem *icp_base, bool debug)
458{
459 int rc = 0;
460 uint32_t data;
461 uint32_t fw_version, status = 0;
462
463 cam_hfi_enable_cpu(icp_base);
464 g_hfi->csr_base = icp_base;
465
466 rc = readw_poll_timeout((icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE),
467 status, status != ICP_INIT_RESP_SUCCESS, 15, 200);
468
469 if (rc) {
470 CAM_ERR(CAM_HFI, "timed out , status = %u", status);
471 return -EINVAL;
472 }
473
474 fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION);
475 CAM_DBG(CAM_HFI, "fw version : [%x]", fw_version);
476
477 cam_io_w((uint32_t)INTR_ENABLE, icp_base + HFI_REG_A5_CSR_A2HOSTINTEN);
478
479 if (debug) {
480 cam_io_w_mb(
481 (uint32_t)(ICP_FLAG_CSR_A5_EN | ICP_FLAG_CSR_WAKE_UP_EN |
482 ICP_CSR_EDBGRQ | ICP_CSR_DBGSWENABLE),
483 icp_base + HFI_REG_A5_CSR_A5_CONTROL);
484 msleep(100);
485 cam_io_w_mb((uint32_t)(ICP_FLAG_CSR_A5_EN |
486 ICP_FLAG_CSR_WAKE_UP_EN | ICP_CSR_EN_CLKGATE_WFI),
487 icp_base + HFI_REG_A5_CSR_A5_CONTROL);
488 } else {
489 cam_io_w_mb((uint32_t)ICP_FLAG_CSR_A5_EN |
490 ICP_FLAG_CSR_WAKE_UP_EN | ICP_CSR_EN_CLKGATE_WFI,
491 icp_base + HFI_REG_A5_CSR_A5_CONTROL);
492 }
493
494 data = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_STATUS);
495 CAM_DBG(CAM_HFI, "wfi status = %x", (int)data);
496
497 cam_io_w((uint32_t)hfi_mem->qtbl.iova, icp_base + HFI_REG_QTBL_PTR);
498 cam_io_w((uint32_t)hfi_mem->shmem.iova,
499 icp_base + HFI_REG_SHARED_MEM_PTR);
500 cam_io_w((uint32_t)hfi_mem->shmem.len,
501 icp_base + HFI_REG_SHARED_MEM_SIZE);
502 cam_io_w((uint32_t)hfi_mem->sec_heap.iova,
503 icp_base + HFI_REG_UNCACHED_HEAP_PTR);
504 cam_io_w((uint32_t)hfi_mem->sec_heap.len,
505 icp_base + HFI_REG_UNCACHED_HEAP_SIZE);
506
507 cam_io_w((uint32_t)INTR_ENABLE, icp_base + HFI_REG_A5_CSR_A2HOSTINTEN);
508 return rc;
509}
510
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700511int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem,
512 void __iomem *icp_base, bool debug)
513{
514 int rc = 0;
515 struct hfi_qtbl *qtbl;
516 struct hfi_qtbl_hdr *qtbl_hdr;
517 struct hfi_q_hdr *cmd_q_hdr, *msg_q_hdr, *dbg_q_hdr;
Jigarkumar Zalaa32fc7b2017-08-22 16:25:34 -0700518 uint32_t hw_version, soc_version, fw_version, status = 0;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700519
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700520 mutex_lock(&hfi_cmd_q_mutex);
521 mutex_lock(&hfi_msg_q_mutex);
522
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700523 if (!g_hfi) {
524 g_hfi = kzalloc(sizeof(struct hfi_info), GFP_KERNEL);
525 if (!g_hfi) {
526 rc = -ENOMEM;
527 goto alloc_fail;
528 }
529 }
530
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700531 if (g_hfi->hfi_state != HFI_DEINIT) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700532 CAM_ERR(CAM_HFI, "hfi_init: invalid state");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700533 return -EINVAL;
534 }
535
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700536 memcpy(&g_hfi->map, hfi_mem, sizeof(g_hfi->map));
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700537 g_hfi->hfi_state = HFI_DEINIT;
Jigarkumar Zalaa32fc7b2017-08-22 16:25:34 -0700538 soc_version = socinfo_get_version();
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700539 if (debug) {
540 cam_io_w_mb(
541 (uint32_t)(ICP_FLAG_CSR_A5_EN | ICP_FLAG_CSR_WAKE_UP_EN |
542 ICP_CSR_EDBGRQ | ICP_CSR_DBGSWENABLE),
543 icp_base + HFI_REG_A5_CSR_A5_CONTROL);
544 msleep(100);
545 cam_io_w_mb((uint32_t)(ICP_FLAG_CSR_A5_EN |
546 ICP_FLAG_CSR_WAKE_UP_EN | ICP_CSR_EN_CLKGATE_WFI),
547 icp_base + HFI_REG_A5_CSR_A5_CONTROL);
548 } else {
Karthik Anantha Ram1a72c862017-10-06 14:02:53 -0700549 /* Due to hardware bug in V1 ICP clock gating has to be
550 * disabled, this is supposed to be fixed in V-2. But enabling
551 * the clock gating is causing the firmware hang, hence
552 * disabling the clock gating on both V1 and V2 until the
553 * hardware team root causes this
554 */
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700555 cam_io_w((uint32_t)ICP_FLAG_CSR_A5_EN |
Jigarkumar Zalaa32fc7b2017-08-22 16:25:34 -0700556 ICP_FLAG_CSR_WAKE_UP_EN |
Karthik Anantha Ram1a72c862017-10-06 14:02:53 -0700557 ICP_CSR_EN_CLKGATE_WFI,
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700558 icp_base + HFI_REG_A5_CSR_A5_CONTROL);
559 }
560
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700561 qtbl = (struct hfi_qtbl *)hfi_mem->qtbl.kva;
562 qtbl_hdr = &qtbl->q_tbl_hdr;
563 qtbl_hdr->qtbl_version = 0xFFFFFFFF;
564 qtbl_hdr->qtbl_size = sizeof(struct hfi_qtbl);
565 qtbl_hdr->qtbl_qhdr0_offset = sizeof(struct hfi_qtbl_hdr);
566 qtbl_hdr->qtbl_qhdr_size = sizeof(struct hfi_q_hdr);
567 qtbl_hdr->qtbl_num_q = ICP_HFI_NUMBER_OF_QS;
568 qtbl_hdr->qtbl_num_active_q = ICP_HFI_NUMBER_OF_QS;
569
570 /* setup host-to-firmware command queue */
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700571 cmd_q_hdr = &qtbl->q_hdr[Q_CMD];
572 cmd_q_hdr->qhdr_status = QHDR_ACTIVE;
573 cmd_q_hdr->qhdr_start_addr = hfi_mem->cmd_q.iova;
574 cmd_q_hdr->qhdr_q_size = ICP_CMD_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT;
575 cmd_q_hdr->qhdr_pkt_size = ICP_HFI_VAR_SIZE_PKT;
576 cmd_q_hdr->qhdr_pkt_drop_cnt = RESET;
577 cmd_q_hdr->qhdr_read_idx = RESET;
578 cmd_q_hdr->qhdr_write_idx = RESET;
579
580 /* setup firmware-to-Host message queue */
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700581 msg_q_hdr = &qtbl->q_hdr[Q_MSG];
582 msg_q_hdr->qhdr_status = QHDR_ACTIVE;
583 msg_q_hdr->qhdr_start_addr = hfi_mem->msg_q.iova;
584 msg_q_hdr->qhdr_q_size = ICP_MSG_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT;
585 msg_q_hdr->qhdr_pkt_size = ICP_HFI_VAR_SIZE_PKT;
586 msg_q_hdr->qhdr_pkt_drop_cnt = RESET;
587 msg_q_hdr->qhdr_read_idx = RESET;
588 msg_q_hdr->qhdr_write_idx = RESET;
589
590 /* setup firmware-to-Host message queue */
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700591 dbg_q_hdr = &qtbl->q_hdr[Q_DBG];
592 dbg_q_hdr->qhdr_status = QHDR_ACTIVE;
593 dbg_q_hdr->qhdr_start_addr = hfi_mem->dbg_q.iova;
594 dbg_q_hdr->qhdr_q_size = ICP_DBG_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT;
595 dbg_q_hdr->qhdr_pkt_size = ICP_HFI_VAR_SIZE_PKT;
596 dbg_q_hdr->qhdr_pkt_drop_cnt = RESET;
597 dbg_q_hdr->qhdr_read_idx = RESET;
598 dbg_q_hdr->qhdr_write_idx = RESET;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700599
600 switch (event_driven_mode) {
601 case INTR_MODE:
602 cmd_q_hdr->qhdr_type = Q_CMD;
603 cmd_q_hdr->qhdr_rx_wm = SET;
604 cmd_q_hdr->qhdr_tx_wm = SET;
605 cmd_q_hdr->qhdr_rx_req = SET;
606 cmd_q_hdr->qhdr_tx_req = RESET;
607 cmd_q_hdr->qhdr_rx_irq_status = RESET;
608 cmd_q_hdr->qhdr_tx_irq_status = RESET;
609
610 msg_q_hdr->qhdr_type = Q_MSG;
611 msg_q_hdr->qhdr_rx_wm = SET;
612 msg_q_hdr->qhdr_tx_wm = SET;
613 msg_q_hdr->qhdr_rx_req = SET;
614 msg_q_hdr->qhdr_tx_req = RESET;
615 msg_q_hdr->qhdr_rx_irq_status = RESET;
616 msg_q_hdr->qhdr_tx_irq_status = RESET;
617
618 dbg_q_hdr->qhdr_type = Q_DBG;
619 dbg_q_hdr->qhdr_rx_wm = SET;
Lakshmi Narayana Kalavaladac0b6c2017-09-13 15:33:42 -0700620 dbg_q_hdr->qhdr_tx_wm = SET_WM;
621 dbg_q_hdr->qhdr_rx_req = RESET;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700622 dbg_q_hdr->qhdr_tx_req = RESET;
623 dbg_q_hdr->qhdr_rx_irq_status = RESET;
624 dbg_q_hdr->qhdr_tx_irq_status = RESET;
625
626 break;
627
628 case POLL_MODE:
629 cmd_q_hdr->qhdr_type = Q_CMD | TX_EVENT_POLL_MODE_2 |
630 RX_EVENT_POLL_MODE_2;
631 msg_q_hdr->qhdr_type = Q_MSG | TX_EVENT_POLL_MODE_2 |
632 RX_EVENT_POLL_MODE_2;
633 dbg_q_hdr->qhdr_type = Q_DBG | TX_EVENT_POLL_MODE_2 |
634 RX_EVENT_POLL_MODE_2;
635 break;
636
637 case WM_MODE:
638 cmd_q_hdr->qhdr_type = Q_CMD | TX_EVENT_DRIVEN_MODE_2 |
639 RX_EVENT_DRIVEN_MODE_2;
640 cmd_q_hdr->qhdr_rx_wm = SET;
641 cmd_q_hdr->qhdr_tx_wm = SET;
642 cmd_q_hdr->qhdr_rx_req = RESET;
643 cmd_q_hdr->qhdr_tx_req = SET;
644 cmd_q_hdr->qhdr_rx_irq_status = RESET;
645 cmd_q_hdr->qhdr_tx_irq_status = RESET;
646
647 msg_q_hdr->qhdr_type = Q_MSG | TX_EVENT_DRIVEN_MODE_2 |
648 RX_EVENT_DRIVEN_MODE_2;
649 msg_q_hdr->qhdr_rx_wm = SET;
650 msg_q_hdr->qhdr_tx_wm = SET;
651 msg_q_hdr->qhdr_rx_req = SET;
652 msg_q_hdr->qhdr_tx_req = RESET;
653 msg_q_hdr->qhdr_rx_irq_status = RESET;
654 msg_q_hdr->qhdr_tx_irq_status = RESET;
655
656 dbg_q_hdr->qhdr_type = Q_DBG | TX_EVENT_DRIVEN_MODE_2 |
657 RX_EVENT_DRIVEN_MODE_2;
658 dbg_q_hdr->qhdr_rx_wm = SET;
Lakshmi Narayana Kalavaladac0b6c2017-09-13 15:33:42 -0700659 dbg_q_hdr->qhdr_tx_wm = SET_WM;
660 dbg_q_hdr->qhdr_rx_req = RESET;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700661 dbg_q_hdr->qhdr_tx_req = RESET;
662 dbg_q_hdr->qhdr_rx_irq_status = RESET;
663 dbg_q_hdr->qhdr_tx_irq_status = RESET;
664 break;
665
666 default:
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700667 CAM_ERR(CAM_HFI, "Invalid event driven mode :%u",
668 event_driven_mode);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700669 break;
670 }
671
672 cam_io_w((uint32_t)hfi_mem->qtbl.iova, icp_base + HFI_REG_QTBL_PTR);
Lakshmi Narayana Kalavala2743a0d2017-05-30 10:41:37 -0700673 cam_io_w((uint32_t)hfi_mem->shmem.iova,
674 icp_base + HFI_REG_SHARED_MEM_PTR);
675 cam_io_w((uint32_t)hfi_mem->shmem.len,
676 icp_base + HFI_REG_SHARED_MEM_SIZE);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700677 cam_io_w((uint32_t)hfi_mem->sec_heap.iova,
678 icp_base + HFI_REG_UNCACHED_HEAP_PTR);
679 cam_io_w((uint32_t)hfi_mem->sec_heap.len,
680 icp_base + HFI_REG_UNCACHED_HEAP_SIZE);
681 cam_io_w((uint32_t)ICP_INIT_REQUEST_SET,
682 icp_base + HFI_REG_HOST_ICP_INIT_REQUEST);
683
684 hw_version = cam_io_r(icp_base + HFI_REG_A5_HW_VERSION);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700685
Lakshmi Narayana Kalavala2743a0d2017-05-30 10:41:37 -0700686 rc = readw_poll_timeout((icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE),
687 status, status != ICP_INIT_RESP_SUCCESS, 15, 200);
688 if (rc) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700689 CAM_ERR(CAM_HFI, "timed out , status = %u", status);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700690 goto regions_fail;
691 }
692
693 fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION);
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700694 CAM_DBG(CAM_HFI, "hw version : : [%x], fw version : [%x]",
695 hw_version, fw_version);
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700696
697 g_hfi->csr_base = icp_base;
698 g_hfi->hfi_state = HFI_READY;
699 g_hfi->cmd_q_state = true;
700 g_hfi->msg_q_state = true;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700701 cam_io_w((uint32_t)INTR_ENABLE, icp_base + HFI_REG_A5_CSR_A2HOSTINTEN);
702
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700703 mutex_unlock(&hfi_cmd_q_mutex);
704 mutex_unlock(&hfi_msg_q_mutex);
705
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700706 return rc;
707regions_fail:
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700708 kfree(g_hfi);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700709alloc_fail:
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700710 mutex_unlock(&hfi_cmd_q_mutex);
711 mutex_unlock(&hfi_msg_q_mutex);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700712 return rc;
713}
714
715
716void cam_hfi_deinit(void)
717{
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700718 mutex_lock(&hfi_cmd_q_mutex);
719 mutex_lock(&hfi_msg_q_mutex);
720
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700721 if (!g_hfi) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700722 CAM_ERR(CAM_HFI, "hfi path not established yet");
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700723 goto err;
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700724 }
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700725
726 g_hfi->cmd_q_state = false;
727 g_hfi->msg_q_state = false;
728
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700729 cam_io_w((uint32_t)INTR_DISABLE,
730 g_hfi->csr_base + HFI_REG_A5_CSR_A2HOSTINTEN);
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700731 kzfree(g_hfi);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700732 g_hfi = NULL;
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700733
734err:
735 mutex_unlock(&hfi_cmd_q_mutex);
736 mutex_unlock(&hfi_msg_q_mutex);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700737}