blob: 77f33d0a262a003290ecf5560861cd99d66e8d66 [file] [log] [blame]
Vivek Veenamd37bd7b2018-01-18 01:18:30 +05301/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -07002 *
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
Suresh Vankadara466bed22017-11-30 06:30:20 +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;
Venkat Chinta2396a462018-01-02 15:46:01 -0800141 uint32_t size_upper_bound = 0;
Karthik Anantha Ramad347282017-11-01 13:09:17 -0700142 int rc = 0;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700143
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700144 if (!pmsg) {
145 CAM_ERR(CAM_HFI, "Invalid msg");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700146 return -EINVAL;
147 }
148
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700149 if (q_id > Q_DBG) {
150 CAM_ERR(CAM_HFI, "Inavlid q :%u", q_id);
151 return -EINVAL;
152 }
153
154 mutex_lock(&hfi_msg_q_mutex);
155 if (!g_hfi) {
156 CAM_ERR(CAM_HFI, "hfi not set up yet");
157 rc = -ENODEV;
158 goto err;
159 }
160
161 if ((g_hfi->hfi_state != HFI_READY) ||
162 !g_hfi->msg_q_state) {
163 CAM_ERR(CAM_HFI, "hfi state: %u, msg q state: %u",
164 g_hfi->hfi_state, g_hfi->msg_q_state);
165 rc = -ENODEV;
166 goto err;
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700167 }
168
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700169 q_tbl_ptr = (struct hfi_qtbl *)g_hfi->map.qtbl.kva;
170 q = &q_tbl_ptr->q_hdr[q_id];
171
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700172 if (q->qhdr_read_idx == q->qhdr_write_idx) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700173 CAM_DBG(CAM_HFI, "Q not ready, state:%u, r idx:%u, w idx:%u",
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700174 g_hfi->hfi_state, q->qhdr_read_idx, q->qhdr_write_idx);
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700175 rc = -EIO;
176 goto err;
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700177 }
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700178
Venkat Chinta2396a462018-01-02 15:46:01 -0800179 if (q_id == Q_MSG) {
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700180 read_q = (uint32_t *)g_hfi->map.msg_q.kva;
Venkat Chinta2396a462018-01-02 15:46:01 -0800181 size_upper_bound = ICP_HFI_MAX_PKT_SIZE_MSGQ_IN_WORDS;
182 } else {
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700183 read_q = (uint32_t *)g_hfi->map.dbg_q.kva;
Venkat Chinta2396a462018-01-02 15:46:01 -0800184 size_upper_bound = ICP_HFI_MAX_PKT_SIZE_IN_WORDS;
185 }
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700186
187 read_ptr = (uint32_t *)(read_q + q->qhdr_read_idx);
Lakshmi Narayana Kalavaladac0b6c2017-09-13 15:33:42 -0700188 write_ptr = (uint32_t *)(read_q + q->qhdr_write_idx);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700189
Lakshmi Narayana Kalavaladac0b6c2017-09-13 15:33:42 -0700190 if (write_ptr > read_ptr)
191 size_in_words = write_ptr - read_ptr;
192 else {
193 word_diff = read_ptr - write_ptr;
194 if (q_id == Q_MSG)
195 size_in_words = (ICP_MSG_Q_SIZE_IN_BYTES >>
196 BYTE_WORD_SHIFT) - word_diff;
197 else
198 size_in_words = (ICP_DBG_Q_SIZE_IN_BYTES >>
199 BYTE_WORD_SHIFT) - word_diff;
200 }
201
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700202 if ((size_in_words == 0) ||
Venkat Chinta2396a462018-01-02 15:46:01 -0800203 (size_in_words > size_upper_bound)) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700204 CAM_ERR(CAM_HFI, "invalid HFI message packet size - 0x%08x",
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700205 size_in_words << BYTE_WORD_SHIFT);
206 q->qhdr_read_idx = q->qhdr_write_idx;
207 rc = -EIO;
208 goto err;
209 }
210
211 new_read_idx = q->qhdr_read_idx + size_in_words;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700212
213 if (new_read_idx < q->qhdr_q_size) {
214 memcpy(pmsg, read_ptr, size_in_words << BYTE_WORD_SHIFT);
215 } else {
216 new_read_idx -= q->qhdr_q_size;
217 temp = (size_in_words - new_read_idx) << BYTE_WORD_SHIFT;
218 memcpy(pmsg, read_ptr, temp);
219 memcpy((uint8_t *)pmsg + temp, read_q,
220 new_read_idx << BYTE_WORD_SHIFT);
221 }
222
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700223 q->qhdr_read_idx = new_read_idx;
Karthik Anantha Ramad347282017-11-01 13:09:17 -0700224 *words_read = size_in_words;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700225err:
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700226 mutex_unlock(&hfi_msg_q_mutex);
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700227 return rc;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700228}
229
Suresh Vankadaraaa6ff8f2017-10-26 22:51:27 +0530230int hfi_cmd_ubwc_config(uint32_t *ubwc_cfg)
231{
232 uint8_t *prop;
233 struct hfi_cmd_prop *dbg_prop;
234 uint32_t size = 0;
235
236 size = sizeof(struct hfi_cmd_prop) +
237 sizeof(struct hfi_cmd_ubwc_cfg);
238
239 prop = kzalloc(size, GFP_KERNEL);
240 if (!prop)
241 return -ENOMEM;
242
243 dbg_prop = (struct hfi_cmd_prop *)prop;
244 dbg_prop->size = size;
245 dbg_prop->pkt_type = HFI_CMD_SYS_SET_PROPERTY;
246 dbg_prop->num_prop = 1;
247 dbg_prop->prop_data[0] = HFI_PROP_SYS_UBWC_CFG;
248 dbg_prop->prop_data[1] = ubwc_cfg[0];
249 dbg_prop->prop_data[2] = ubwc_cfg[1];
250
251 hfi_write_cmd(prop);
252 kfree(prop);
253
254 return 0;
255}
256
Suresh Vankadara466bed22017-11-30 06:30:20 +0530257int hfi_enable_ipe_bps_pc(bool enable, uint32_t core_info)
Suresh Vankadara6657bc22017-07-31 10:33:04 +0530258{
259 uint8_t *prop;
260 struct hfi_cmd_prop *dbg_prop;
261 uint32_t size = 0;
262
263 size = sizeof(struct hfi_cmd_prop) +
264 sizeof(struct hfi_ipe_bps_pc);
265
266 prop = kzalloc(size, GFP_KERNEL);
267 if (!prop)
268 return -ENOMEM;
269
270 dbg_prop = (struct hfi_cmd_prop *)prop;
271 dbg_prop->size = size;
272 dbg_prop->pkt_type = HFI_CMD_SYS_SET_PROPERTY;
273 dbg_prop->num_prop = 1;
274 dbg_prop->prop_data[0] = HFI_PROP_SYS_IPEBPS_PC;
275 dbg_prop->prop_data[1] = enable;
Suresh Vankadara466bed22017-11-30 06:30:20 +0530276 dbg_prop->prop_data[2] = core_info;
Suresh Vankadara6657bc22017-07-31 10:33:04 +0530277
278 hfi_write_cmd(prop);
279 kfree(prop);
280
281 return 0;
282}
283
Lakshmi Narayana Kalavaladac0b6c2017-09-13 15:33:42 -0700284int hfi_set_debug_level(uint32_t lvl)
285{
286 uint8_t *prop;
287 struct hfi_cmd_prop *dbg_prop;
288 uint32_t size = 0, val;
289
290 val = HFI_DEBUG_MSG_LOW |
291 HFI_DEBUG_MSG_MEDIUM |
292 HFI_DEBUG_MSG_HIGH |
293 HFI_DEBUG_MSG_ERROR |
294 HFI_DEBUG_MSG_FATAL |
295 HFI_DEBUG_MSG_PERF |
296 HFI_DEBUG_CFG_WFI |
297 HFI_DEBUG_CFG_ARM9WD;
298
299 if (lvl > val)
300 return -EINVAL;
301
302 size = sizeof(struct hfi_cmd_prop) +
303 sizeof(struct hfi_debug);
304
305 prop = kzalloc(size, GFP_KERNEL);
306 if (!prop)
307 return -ENOMEM;
308
309 dbg_prop = (struct hfi_cmd_prop *)prop;
310 dbg_prop->size = size;
311 dbg_prop->pkt_type = HFI_CMD_SYS_SET_PROPERTY;
312 dbg_prop->num_prop = 1;
313 dbg_prop->prop_data[0] = HFI_PROP_SYS_DEBUG_CFG;
314 dbg_prop->prop_data[1] = lvl;
315 dbg_prop->prop_data[2] = HFI_DEBUG_MODE_QUEUE;
316
317 hfi_write_cmd(prop);
318 kfree(prop);
319
320 return 0;
321}
322
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700323void hfi_send_system_cmd(uint32_t type, uint64_t data, uint32_t size)
324{
325 switch (type) {
326 case HFI_CMD_SYS_INIT: {
327 struct hfi_cmd_sys_init init;
328
329 memset(&init, 0, sizeof(init));
330
331 init.size = sizeof(struct hfi_cmd_sys_init);
332 init.pkt_type = type;
333 hfi_write_cmd(&init);
334 }
335 break;
336 case HFI_CMD_SYS_PC_PREP: {
337 struct hfi_cmd_pc_prep prep;
338
339 prep.size = sizeof(struct hfi_cmd_pc_prep);
340 prep.pkt_type = type;
341 hfi_write_cmd(&prep);
342 }
343 break;
344 case HFI_CMD_SYS_SET_PROPERTY: {
345 struct hfi_cmd_prop prop;
346
347 if ((uint32_t)data == (uint32_t)HFI_PROP_SYS_DEBUG_CFG) {
348 prop.size = sizeof(struct hfi_cmd_prop);
349 prop.pkt_type = type;
350 prop.num_prop = 1;
351 prop.prop_data[0] = HFI_PROP_SYS_DEBUG_CFG;
352 hfi_write_cmd(&prop);
353 }
354 }
355 break;
356 case HFI_CMD_SYS_GET_PROPERTY:
357 break;
358 case HFI_CMD_SYS_PING: {
359 struct hfi_cmd_ping_pkt ping;
360
361 ping.size = sizeof(struct hfi_cmd_ping_pkt);
362 ping.pkt_type = type;
363 ping.user_data = (uint64_t)data;
364 hfi_write_cmd(&ping);
365 }
366 break;
367 case HFI_CMD_SYS_RESET: {
368 struct hfi_cmd_sys_reset_pkt reset;
369
370 reset.size = sizeof(struct hfi_cmd_sys_reset_pkt);
371 reset.pkt_type = type;
372 reset.user_data = (uint64_t)data;
373 hfi_write_cmd(&reset);
374 }
375 break;
376 case HFI_CMD_IPEBPS_CREATE_HANDLE: {
377 struct hfi_cmd_create_handle handle;
378
379 handle.size = sizeof(struct hfi_cmd_create_handle);
380 handle.pkt_type = type;
381 handle.handle_type = (uint32_t)data;
382 handle.user_data1 = 0;
383 hfi_write_cmd(&handle);
384 }
385 break;
386 case HFI_CMD_IPEBPS_ASYNC_COMMAND_INDIRECT:
387 break;
388 default:
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700389 CAM_ERR(CAM_HFI, "command not supported :%d", type);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700390 break;
391 }
392}
393
394
395int hfi_get_hw_caps(void *query_buf)
396{
397 int i = 0;
398 struct cam_icp_query_cap_cmd *query_cmd = NULL;
399
400 if (!query_buf) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700401 CAM_ERR(CAM_HFI, "query buf is NULL");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700402 return -EINVAL;
403 }
404
405 query_cmd = (struct cam_icp_query_cap_cmd *)query_buf;
406 query_cmd->fw_version.major = 0x12;
407 query_cmd->fw_version.minor = 0x12;
408 query_cmd->fw_version.revision = 0x12;
409
410 query_cmd->api_version.major = 0x13;
411 query_cmd->api_version.minor = 0x13;
412 query_cmd->api_version.revision = 0x13;
413
414 query_cmd->num_ipe = 2;
415 query_cmd->num_bps = 1;
416
417 for (i = 0; i < CAM_ICP_DEV_TYPE_MAX; i++) {
418 query_cmd->dev_ver[i].dev_type = i;
419 query_cmd->dev_ver[i].hw_ver.major = 0x34 + i;
420 query_cmd->dev_ver[i].hw_ver.minor = 0x34 + i;
421 query_cmd->dev_ver[i].hw_ver.incr = 0x34 + i;
422 }
423 return 0;
424}
425
Suresh Vankadarad8905f42017-06-04 13:33:49 +0530426void cam_hfi_disable_cpu(void __iomem *icp_base)
427{
428 uint32_t data;
429 uint32_t val;
Suresh Vankadara466bed22017-11-30 06:30:20 +0530430 uint32_t try = 0;
Suresh Vankadarad8905f42017-06-04 13:33:49 +0530431
Suresh Vankadara466bed22017-11-30 06:30:20 +0530432 while (try < HFI_MAX_POLL_TRY) {
433 data = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_STATUS);
434 CAM_DBG(CAM_HFI, "wfi status = %x\n", (int)data);
435
436 if (data & ICP_CSR_A5_STATUS_WFI)
437 break;
438 /* Need to poll here to confirm that FW is going trigger wfi
439 * and Host can the proceed. No interrupt is expected from FW
440 * at this time.
441 */
442 msleep(100);
443 try++;
Suresh Vankadarad8905f42017-06-04 13:33:49 +0530444 }
Suresh Vankadara466bed22017-11-30 06:30:20 +0530445
446 val = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_CONTROL);
447 val &= ~(ICP_FLAG_CSR_A5_EN | ICP_FLAG_CSR_WAKE_UP_EN);
448 cam_io_w(val, icp_base + HFI_REG_A5_CSR_A5_CONTROL);
449
450 val = cam_io_r(icp_base + HFI_REG_A5_CSR_NSEC_RESET);
451 cam_io_w(val, icp_base + HFI_REG_A5_CSR_NSEC_RESET);
Suresh Vankadarad8905f42017-06-04 13:33:49 +0530452}
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700453
454void cam_hfi_enable_cpu(void __iomem *icp_base)
455{
456 cam_io_w((uint32_t)ICP_FLAG_CSR_A5_EN,
457 icp_base + HFI_REG_A5_CSR_A5_CONTROL);
458 cam_io_w((uint32_t)0x10, icp_base + HFI_REG_A5_CSR_NSEC_RESET);
459}
460
Suresh Vankadara466bed22017-11-30 06:30:20 +0530461int cam_hfi_resume(struct hfi_mem_info *hfi_mem,
462 void __iomem *icp_base, bool debug)
463{
464 int rc = 0;
465 uint32_t data;
466 uint32_t fw_version, status = 0;
467
468 cam_hfi_enable_cpu(icp_base);
469 g_hfi->csr_base = icp_base;
470
471 rc = readw_poll_timeout((icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE),
472 status, status != ICP_INIT_RESP_SUCCESS, 15, 200);
473
474 if (rc) {
475 CAM_ERR(CAM_HFI, "timed out , status = %u", status);
476 return -EINVAL;
477 }
478
479 fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION);
480 CAM_DBG(CAM_HFI, "fw version : [%x]", fw_version);
481
482 cam_io_w((uint32_t)INTR_ENABLE, icp_base + HFI_REG_A5_CSR_A2HOSTINTEN);
483
484 if (debug) {
485 cam_io_w_mb(ICP_FLAG_A5_CTRL_DBG_EN,
486 (icp_base + HFI_REG_A5_CSR_A5_CONTROL));
487
488 /* Barrier needed as next write should be done after
489 * sucessful previous write. Next write enable clock
490 * gating
491 */
492 wmb();
493
494 cam_io_w_mb((uint32_t)ICP_FLAG_A5_CTRL_EN,
495 icp_base + HFI_REG_A5_CSR_A5_CONTROL);
496
497 } else {
498 cam_io_w_mb((uint32_t)ICP_FLAG_A5_CTRL_EN,
499 icp_base + HFI_REG_A5_CSR_A5_CONTROL);
500 }
501
502 data = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_STATUS);
503 CAM_DBG(CAM_HFI, "wfi status = %x", (int)data);
504
505 cam_io_w((uint32_t)hfi_mem->qtbl.iova, icp_base + HFI_REG_QTBL_PTR);
506 cam_io_w((uint32_t)hfi_mem->shmem.iova,
507 icp_base + HFI_REG_SHARED_MEM_PTR);
508 cam_io_w((uint32_t)hfi_mem->shmem.len,
509 icp_base + HFI_REG_SHARED_MEM_SIZE);
510 cam_io_w((uint32_t)hfi_mem->sec_heap.iova,
511 icp_base + HFI_REG_UNCACHED_HEAP_PTR);
512 cam_io_w((uint32_t)hfi_mem->sec_heap.len,
513 icp_base + HFI_REG_UNCACHED_HEAP_SIZE);
514
515 cam_io_w((uint32_t)INTR_ENABLE, icp_base + HFI_REG_A5_CSR_A2HOSTINTEN);
516 return rc;
517}
518
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700519int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem,
520 void __iomem *icp_base, bool debug)
521{
522 int rc = 0;
523 struct hfi_qtbl *qtbl;
524 struct hfi_qtbl_hdr *qtbl_hdr;
525 struct hfi_q_hdr *cmd_q_hdr, *msg_q_hdr, *dbg_q_hdr;
Jigarkumar Zalaa32fc7b2017-08-22 16:25:34 -0700526 uint32_t hw_version, soc_version, fw_version, status = 0;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700527
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700528 mutex_lock(&hfi_cmd_q_mutex);
529 mutex_lock(&hfi_msg_q_mutex);
530
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700531 if (!g_hfi) {
532 g_hfi = kzalloc(sizeof(struct hfi_info), GFP_KERNEL);
533 if (!g_hfi) {
534 rc = -ENOMEM;
535 goto alloc_fail;
536 }
537 }
538
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700539 if (g_hfi->hfi_state != HFI_DEINIT) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700540 CAM_ERR(CAM_HFI, "hfi_init: invalid state");
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700541 return -EINVAL;
542 }
543
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700544 memcpy(&g_hfi->map, hfi_mem, sizeof(g_hfi->map));
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700545 g_hfi->hfi_state = HFI_DEINIT;
Jigarkumar Zalaa32fc7b2017-08-22 16:25:34 -0700546 soc_version = socinfo_get_version();
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700547 if (debug) {
548 cam_io_w_mb(
549 (uint32_t)(ICP_FLAG_CSR_A5_EN | ICP_FLAG_CSR_WAKE_UP_EN |
550 ICP_CSR_EDBGRQ | ICP_CSR_DBGSWENABLE),
551 icp_base + HFI_REG_A5_CSR_A5_CONTROL);
552 msleep(100);
553 cam_io_w_mb((uint32_t)(ICP_FLAG_CSR_A5_EN |
554 ICP_FLAG_CSR_WAKE_UP_EN | ICP_CSR_EN_CLKGATE_WFI),
555 icp_base + HFI_REG_A5_CSR_A5_CONTROL);
556 } else {
Karthik Anantha Ram1a72c862017-10-06 14:02:53 -0700557 /* Due to hardware bug in V1 ICP clock gating has to be
558 * disabled, this is supposed to be fixed in V-2. But enabling
559 * the clock gating is causing the firmware hang, hence
560 * disabling the clock gating on both V1 and V2 until the
561 * hardware team root causes this
562 */
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700563 cam_io_w((uint32_t)ICP_FLAG_CSR_A5_EN |
Jigarkumar Zalaa32fc7b2017-08-22 16:25:34 -0700564 ICP_FLAG_CSR_WAKE_UP_EN |
Karthik Anantha Ram1a72c862017-10-06 14:02:53 -0700565 ICP_CSR_EN_CLKGATE_WFI,
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700566 icp_base + HFI_REG_A5_CSR_A5_CONTROL);
567 }
568
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700569 qtbl = (struct hfi_qtbl *)hfi_mem->qtbl.kva;
570 qtbl_hdr = &qtbl->q_tbl_hdr;
571 qtbl_hdr->qtbl_version = 0xFFFFFFFF;
572 qtbl_hdr->qtbl_size = sizeof(struct hfi_qtbl);
573 qtbl_hdr->qtbl_qhdr0_offset = sizeof(struct hfi_qtbl_hdr);
574 qtbl_hdr->qtbl_qhdr_size = sizeof(struct hfi_q_hdr);
575 qtbl_hdr->qtbl_num_q = ICP_HFI_NUMBER_OF_QS;
576 qtbl_hdr->qtbl_num_active_q = ICP_HFI_NUMBER_OF_QS;
577
578 /* setup host-to-firmware command queue */
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700579 cmd_q_hdr = &qtbl->q_hdr[Q_CMD];
580 cmd_q_hdr->qhdr_status = QHDR_ACTIVE;
581 cmd_q_hdr->qhdr_start_addr = hfi_mem->cmd_q.iova;
582 cmd_q_hdr->qhdr_q_size = ICP_CMD_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT;
583 cmd_q_hdr->qhdr_pkt_size = ICP_HFI_VAR_SIZE_PKT;
584 cmd_q_hdr->qhdr_pkt_drop_cnt = RESET;
585 cmd_q_hdr->qhdr_read_idx = RESET;
586 cmd_q_hdr->qhdr_write_idx = RESET;
587
588 /* setup firmware-to-Host message queue */
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700589 msg_q_hdr = &qtbl->q_hdr[Q_MSG];
590 msg_q_hdr->qhdr_status = QHDR_ACTIVE;
591 msg_q_hdr->qhdr_start_addr = hfi_mem->msg_q.iova;
592 msg_q_hdr->qhdr_q_size = ICP_MSG_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT;
593 msg_q_hdr->qhdr_pkt_size = ICP_HFI_VAR_SIZE_PKT;
594 msg_q_hdr->qhdr_pkt_drop_cnt = RESET;
595 msg_q_hdr->qhdr_read_idx = RESET;
596 msg_q_hdr->qhdr_write_idx = RESET;
597
598 /* setup firmware-to-Host message queue */
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700599 dbg_q_hdr = &qtbl->q_hdr[Q_DBG];
600 dbg_q_hdr->qhdr_status = QHDR_ACTIVE;
601 dbg_q_hdr->qhdr_start_addr = hfi_mem->dbg_q.iova;
602 dbg_q_hdr->qhdr_q_size = ICP_DBG_Q_SIZE_IN_BYTES >> BYTE_WORD_SHIFT;
603 dbg_q_hdr->qhdr_pkt_size = ICP_HFI_VAR_SIZE_PKT;
604 dbg_q_hdr->qhdr_pkt_drop_cnt = RESET;
605 dbg_q_hdr->qhdr_read_idx = RESET;
606 dbg_q_hdr->qhdr_write_idx = RESET;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700607
608 switch (event_driven_mode) {
609 case INTR_MODE:
610 cmd_q_hdr->qhdr_type = Q_CMD;
611 cmd_q_hdr->qhdr_rx_wm = SET;
612 cmd_q_hdr->qhdr_tx_wm = SET;
613 cmd_q_hdr->qhdr_rx_req = SET;
614 cmd_q_hdr->qhdr_tx_req = RESET;
615 cmd_q_hdr->qhdr_rx_irq_status = RESET;
616 cmd_q_hdr->qhdr_tx_irq_status = RESET;
617
618 msg_q_hdr->qhdr_type = Q_MSG;
619 msg_q_hdr->qhdr_rx_wm = SET;
620 msg_q_hdr->qhdr_tx_wm = SET;
621 msg_q_hdr->qhdr_rx_req = SET;
622 msg_q_hdr->qhdr_tx_req = RESET;
623 msg_q_hdr->qhdr_rx_irq_status = RESET;
624 msg_q_hdr->qhdr_tx_irq_status = RESET;
625
626 dbg_q_hdr->qhdr_type = Q_DBG;
627 dbg_q_hdr->qhdr_rx_wm = SET;
Lakshmi Narayana Kalavaladac0b6c2017-09-13 15:33:42 -0700628 dbg_q_hdr->qhdr_tx_wm = SET_WM;
629 dbg_q_hdr->qhdr_rx_req = RESET;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700630 dbg_q_hdr->qhdr_tx_req = RESET;
631 dbg_q_hdr->qhdr_rx_irq_status = RESET;
632 dbg_q_hdr->qhdr_tx_irq_status = RESET;
633
634 break;
635
636 case POLL_MODE:
637 cmd_q_hdr->qhdr_type = Q_CMD | TX_EVENT_POLL_MODE_2 |
638 RX_EVENT_POLL_MODE_2;
639 msg_q_hdr->qhdr_type = Q_MSG | TX_EVENT_POLL_MODE_2 |
640 RX_EVENT_POLL_MODE_2;
641 dbg_q_hdr->qhdr_type = Q_DBG | TX_EVENT_POLL_MODE_2 |
642 RX_EVENT_POLL_MODE_2;
643 break;
644
645 case WM_MODE:
646 cmd_q_hdr->qhdr_type = Q_CMD | TX_EVENT_DRIVEN_MODE_2 |
647 RX_EVENT_DRIVEN_MODE_2;
648 cmd_q_hdr->qhdr_rx_wm = SET;
649 cmd_q_hdr->qhdr_tx_wm = SET;
650 cmd_q_hdr->qhdr_rx_req = RESET;
651 cmd_q_hdr->qhdr_tx_req = SET;
652 cmd_q_hdr->qhdr_rx_irq_status = RESET;
653 cmd_q_hdr->qhdr_tx_irq_status = RESET;
654
655 msg_q_hdr->qhdr_type = Q_MSG | TX_EVENT_DRIVEN_MODE_2 |
656 RX_EVENT_DRIVEN_MODE_2;
657 msg_q_hdr->qhdr_rx_wm = SET;
658 msg_q_hdr->qhdr_tx_wm = SET;
659 msg_q_hdr->qhdr_rx_req = SET;
660 msg_q_hdr->qhdr_tx_req = RESET;
661 msg_q_hdr->qhdr_rx_irq_status = RESET;
662 msg_q_hdr->qhdr_tx_irq_status = RESET;
663
664 dbg_q_hdr->qhdr_type = Q_DBG | TX_EVENT_DRIVEN_MODE_2 |
665 RX_EVENT_DRIVEN_MODE_2;
666 dbg_q_hdr->qhdr_rx_wm = SET;
Lakshmi Narayana Kalavaladac0b6c2017-09-13 15:33:42 -0700667 dbg_q_hdr->qhdr_tx_wm = SET_WM;
668 dbg_q_hdr->qhdr_rx_req = RESET;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700669 dbg_q_hdr->qhdr_tx_req = RESET;
670 dbg_q_hdr->qhdr_rx_irq_status = RESET;
671 dbg_q_hdr->qhdr_tx_irq_status = RESET;
672 break;
673
674 default:
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700675 CAM_ERR(CAM_HFI, "Invalid event driven mode :%u",
676 event_driven_mode);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700677 break;
678 }
679
680 cam_io_w((uint32_t)hfi_mem->qtbl.iova, icp_base + HFI_REG_QTBL_PTR);
Lakshmi Narayana Kalavala2743a0d2017-05-30 10:41:37 -0700681 cam_io_w((uint32_t)hfi_mem->shmem.iova,
682 icp_base + HFI_REG_SHARED_MEM_PTR);
683 cam_io_w((uint32_t)hfi_mem->shmem.len,
684 icp_base + HFI_REG_SHARED_MEM_SIZE);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700685 cam_io_w((uint32_t)hfi_mem->sec_heap.iova,
686 icp_base + HFI_REG_UNCACHED_HEAP_PTR);
687 cam_io_w((uint32_t)hfi_mem->sec_heap.len,
688 icp_base + HFI_REG_UNCACHED_HEAP_SIZE);
689 cam_io_w((uint32_t)ICP_INIT_REQUEST_SET,
690 icp_base + HFI_REG_HOST_ICP_INIT_REQUEST);
691
692 hw_version = cam_io_r(icp_base + HFI_REG_A5_HW_VERSION);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700693
Lakshmi Narayana Kalavala2743a0d2017-05-30 10:41:37 -0700694 rc = readw_poll_timeout((icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE),
695 status, status != ICP_INIT_RESP_SUCCESS, 15, 200);
696 if (rc) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700697 CAM_ERR(CAM_HFI, "timed out , status = %u", status);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700698 goto regions_fail;
699 }
700
701 fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION);
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700702 CAM_DBG(CAM_HFI, "hw version : : [%x], fw version : [%x]",
703 hw_version, fw_version);
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700704
705 g_hfi->csr_base = icp_base;
706 g_hfi->hfi_state = HFI_READY;
707 g_hfi->cmd_q_state = true;
708 g_hfi->msg_q_state = true;
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700709 cam_io_w((uint32_t)INTR_ENABLE, icp_base + HFI_REG_A5_CSR_A2HOSTINTEN);
710
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700711 mutex_unlock(&hfi_cmd_q_mutex);
712 mutex_unlock(&hfi_msg_q_mutex);
713
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700714 return rc;
715regions_fail:
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700716 kfree(g_hfi);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700717alloc_fail:
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700718 mutex_unlock(&hfi_cmd_q_mutex);
719 mutex_unlock(&hfi_msg_q_mutex);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700720 return rc;
721}
722
723
Vivek Veenamd37bd7b2018-01-18 01:18:30 +0530724void cam_hfi_deinit(void)
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700725{
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700726 mutex_lock(&hfi_cmd_q_mutex);
727 mutex_lock(&hfi_msg_q_mutex);
728
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700729 if (!g_hfi) {
Lakshmi Narayana Kalavalaadc6ce32017-07-17 17:19:11 -0700730 CAM_ERR(CAM_HFI, "hfi path not established yet");
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700731 goto err;
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700732 }
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700733
734 g_hfi->cmd_q_state = false;
735 g_hfi->msg_q_state = false;
736
Lakshmi Narayana Kalavalac2fac452017-06-12 12:38:07 -0700737 cam_io_w((uint32_t)INTR_DISABLE,
738 g_hfi->csr_base + HFI_REG_A5_CSR_A2HOSTINTEN);
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700739 kzfree(g_hfi);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700740 g_hfi = NULL;
Lakshmi Narayana Kalavalafb421372017-07-20 14:37:48 -0700741
742err:
743 mutex_unlock(&hfi_cmd_q_mutex);
744 mutex_unlock(&hfi_msg_q_mutex);
Lakshmi Narayana Kalavala85c40352017-05-15 16:19:13 -0700745}