blob: d7a650421fd1e41cbc59ad7957a4b6ecb666ba78 [file] [log] [blame]
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001/* 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
13#include <linux/module.h>
14#include "cam_cci_core.h"
15#include "cam_cci_dev.h"
16
17static int32_t cam_cci_convert_type_to_num_bytes(
18 enum camera_sensor_i2c_type type)
19{
20 int32_t num_bytes;
21
22 switch (type) {
23 case CAMERA_SENSOR_I2C_TYPE_BYTE:
24 num_bytes = 1;
25 break;
26 case CAMERA_SENSOR_I2C_TYPE_WORD:
27 num_bytes = 2;
28 break;
29 case CAMERA_SENSOR_I2C_TYPE_3B:
30 num_bytes = 3;
31 break;
32 case CAMERA_SENSOR_I2C_TYPE_DWORD:
33 num_bytes = 4;
34 break;
35 default:
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -070036 CAM_ERR(CAM_CCI, "failed: %d", type);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -080037 num_bytes = 0;
38 break;
39 }
40 return num_bytes;
41}
42
43static void cam_cci_flush_queue(struct cci_device *cci_dev,
44 enum cci_i2c_master_t master)
45{
46 int32_t rc = 0;
Alok Pandey01b1b352017-06-25 20:38:54 +053047 struct cam_hw_soc_info *soc_info =
48 &cci_dev->soc_info;
49 void __iomem *base = soc_info->reg_map[0].mem_base;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -080050
Alok Pandey01b1b352017-06-25 20:38:54 +053051 cam_io_w_mb(1 << master, base + CCI_HALT_REQ_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -080052 rc = wait_for_completion_timeout(
53 &cci_dev->cci_master_info[master].reset_complete, CCI_TIMEOUT);
54 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -070055 CAM_ERR(CAM_CCI, "wait failed");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -080056 } else if (rc == 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -070057 CAM_ERR(CAM_CCI, "wait timeout");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -080058
59 /* Set reset pending flag to TRUE */
60 cci_dev->cci_master_info[master].reset_pending = TRUE;
61
62 /* Set proper mask to RESET CMD address based on MASTER */
63 if (master == MASTER_0)
64 cam_io_w_mb(CCI_M0_RESET_RMSK,
Alok Pandey01b1b352017-06-25 20:38:54 +053065 base + CCI_RESET_CMD_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -080066 else
67 cam_io_w_mb(CCI_M1_RESET_RMSK,
Alok Pandey01b1b352017-06-25 20:38:54 +053068 base + CCI_RESET_CMD_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -080069
70 /* wait for reset done irq */
71 rc = wait_for_completion_timeout(
72 &cci_dev->cci_master_info[master].reset_complete,
73 CCI_TIMEOUT);
74 if (rc <= 0)
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -070075 CAM_ERR(CAM_CCI, "wait failed %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -080076 }
77}
78
79static int32_t cam_cci_validate_queue(struct cci_device *cci_dev,
80 uint32_t len,
81 enum cci_i2c_master_t master,
82 enum cci_i2c_queue_t queue)
83{
84 int32_t rc = 0;
85 uint32_t read_val = 0;
86 uint32_t reg_offset = master * 0x200 + queue * 0x100;
Alok Pandey01b1b352017-06-25 20:38:54 +053087 struct cam_hw_soc_info *soc_info =
88 &cci_dev->soc_info;
89 void __iomem *base = soc_info->reg_map[0].mem_base;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -080090
Alok Pandey01b1b352017-06-25 20:38:54 +053091 read_val = cam_io_r_mb(base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -080092 CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + reg_offset);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -070093 CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR %d len %d max %d",
94 read_val, len,
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -080095 cci_dev->cci_i2c_queue_info[master][queue].max_queue_size);
96 if ((read_val + len + 1) > cci_dev->
97 cci_i2c_queue_info[master][queue].max_queue_size) {
98 uint32_t reg_val = 0;
99 uint32_t report_val = CCI_I2C_REPORT_CMD | (1 << 8);
100
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700101 CAM_DBG(CAM_CCI, "CCI_I2C_REPORT_CMD");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800102 cam_io_w_mb(report_val,
Alok Pandey01b1b352017-06-25 20:38:54 +0530103 base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800104 reg_offset);
105 read_val++;
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700106 CAM_DBG(CAM_CCI,
107 "CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR %d, queue: %d",
108 read_val, queue);
Alok Pandey01b1b352017-06-25 20:38:54 +0530109 cam_io_w_mb(read_val, base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800110 CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + reg_offset);
111 reg_val = 1 << ((master * 2) + queue);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700112 CAM_DBG(CAM_CCI, "CCI_QUEUE_START_ADDR");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800113 atomic_set(&cci_dev->cci_master_info[master].
114 done_pending[queue], 1);
Alok Pandey01b1b352017-06-25 20:38:54 +0530115 cam_io_w_mb(reg_val, base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800116 CCI_QUEUE_START_ADDR);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700117 CAM_DBG(CAM_CCI, "wait_for_completion_timeout");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800118 atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 1);
119 rc = wait_for_completion_timeout(&cci_dev->
120 cci_master_info[master].report_q[queue], CCI_TIMEOUT);
121 if (rc <= 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700122 CAM_ERR(CAM_CCI, "Wait_for_completion_timeout %d");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800123 if (rc == 0)
124 rc = -ETIMEDOUT;
125 cam_cci_flush_queue(cci_dev, master);
126 return rc;
127 }
128 rc = cci_dev->cci_master_info[master].status;
129 if (rc < 0)
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700130 CAM_ERR(CAM_CCI, "Failed rc %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800131 }
132
133 return rc;
134}
135
136static int32_t cam_cci_write_i2c_queue(struct cci_device *cci_dev,
137 uint32_t val,
138 enum cci_i2c_master_t master,
139 enum cci_i2c_queue_t queue)
140{
141 int32_t rc = 0;
142 uint32_t reg_offset = master * 0x200 + queue * 0x100;
Alok Pandey01b1b352017-06-25 20:38:54 +0530143 struct cam_hw_soc_info *soc_info =
144 &cci_dev->soc_info;
145 void __iomem *base = soc_info->reg_map[0].mem_base;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800146
147 if (!cci_dev) {
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700148 CAM_ERR(CAM_CCI, "Failed");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800149 return -EINVAL;
150 }
151
152 rc = cam_cci_validate_queue(cci_dev, 1, master, queue);
153 if (rc < 0) {
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700154 CAM_ERR(CAM_CCI, "Failed %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800155 return rc;
156 }
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700157 CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_LOAD_DATA_ADDR:val 0x%x:0x%x",
158 CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800159 reg_offset, val);
Alok Pandey01b1b352017-06-25 20:38:54 +0530160 cam_io_w_mb(val, base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800161 reg_offset);
162 return rc;
163}
164
165static int32_t cam_cci_lock_queue(struct cci_device *cci_dev,
166 enum cci_i2c_master_t master,
167 enum cci_i2c_queue_t queue, uint32_t en)
168{
169 uint32_t val;
170
171 if (queue != PRIORITY_QUEUE)
172 return 0;
173
174 val = en ? CCI_I2C_LOCK_CMD : CCI_I2C_UNLOCK_CMD;
175 return cam_cci_write_i2c_queue(cci_dev, val, master, queue);
176}
177
178#ifdef DUMP_CCI_REGISTERS
179static void cam_cci_dump_registers(struct cci_device *cci_dev,
180 enum cci_i2c_master_t master, enum cci_i2c_queue_t queue)
181{
182 uint32_t read_val = 0;
183 uint32_t i = 0;
184 uint32_t reg_offset = 0;
185
186 /* CCI Top Registers */
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700187 CAM_DBG(CAM_CCI, "****CCI TOP Registers ****");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800188 for (i = 0; i < DEBUG_TOP_REG_COUNT; i++) {
189 reg_offset = DEBUG_TOP_REG_START + i * 4;
190 read_val = cam_io_r_mb(cci_dev->base + reg_offset);
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700191 CAM_DBG(CAM_CCI, "offset = 0x%X value = 0x%X",
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700192 reg_offset, read_val);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800193 }
194
195 /* CCI Master registers */
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700196 CAM_DBG(CAM_CCI, "****CCI MASTER %d Registers ****",
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700197 master);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800198 for (i = 0; i < DEBUG_MASTER_REG_COUNT; i++) {
199 if (i == 6)
200 continue;
201 reg_offset = DEBUG_MASTER_REG_START + master*0x100 + i * 4;
202 read_val = cam_io_r_mb(cci_dev->base + reg_offset);
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700203 CAM_DBG(CAM_CCI, "offset = 0x%X value = 0x%X",
204 reg_offset, read_val);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800205 }
206
207 /* CCI Master Queue registers */
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700208 CAM_DBG(CAM_CCI, " **** CCI MASTER%d QUEUE%d Registers ****",
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700209 master, queue);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800210 for (i = 0; i < DEBUG_MASTER_QUEUE_REG_COUNT; i++) {
211 reg_offset = DEBUG_MASTER_QUEUE_REG_START + master*0x200 +
212 queue*0x100 + i * 4;
213 read_val = cam_io_r_mb(cci_dev->base + reg_offset);
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700214 CAM_DBG(CAM_CCI, "offset = 0x%X value = 0x%X",
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700215 reg_offset, read_val);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800216 }
217
218 /* CCI Interrupt registers */
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700219 CAM_DBG(CAM_CCI, " ****CCI Interrupt Registers ****");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800220 for (i = 0; i < DEBUG_INTR_REG_COUNT; i++) {
221 reg_offset = DEBUG_INTR_REG_START + i * 4;
222 read_val = cam_io_r_mb(cci_dev->base + reg_offset);
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700223 CAM_DBG(CAM_CCI, "offset = 0x%X value = 0x%X",
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700224 reg_offset, read_val);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800225 }
226}
227#endif
228
229static uint32_t cam_cci_wait(struct cci_device *cci_dev,
230 enum cci_i2c_master_t master,
231 enum cci_i2c_queue_t queue)
232{
233 int32_t rc = 0;
234
235 if (!cci_dev) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700236 CAM_ERR(CAM_CCI, "failed");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800237 return -EINVAL;
238 }
239
240 rc = wait_for_completion_timeout(&cci_dev->
241 cci_master_info[master].report_q[queue], CCI_TIMEOUT);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700242 CAM_DBG(CAM_CCI, "wait DONE_for_completion_timeout");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800243
244 if (rc <= 0) {
245#ifdef DUMP_CCI_REGISTERS
246 cam_cci_dump_registers(cci_dev, master, queue);
247#endif
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700248 CAM_ERR(CAM_CCI, "wait for queue: %d", queue);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800249 if (rc == 0)
250 rc = -ETIMEDOUT;
251 cam_cci_flush_queue(cci_dev, master);
252 return rc;
253 }
254 rc = cci_dev->cci_master_info[master].status;
255 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700256 CAM_ERR(CAM_CCI, "failed rc %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800257 return rc;
258 }
259
260 return 0;
261}
262
263static void cam_cci_load_report_cmd(struct cci_device *cci_dev,
264 enum cci_i2c_master_t master,
265 enum cci_i2c_queue_t queue)
266{
Alok Pandey01b1b352017-06-25 20:38:54 +0530267 struct cam_hw_soc_info *soc_info =
268 &cci_dev->soc_info;
269 void __iomem *base = soc_info->reg_map[0].mem_base;
270
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800271 uint32_t reg_offset = master * 0x200 + queue * 0x100;
Alok Pandey01b1b352017-06-25 20:38:54 +0530272 uint32_t read_val = cam_io_r_mb(base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800273 CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + reg_offset);
274 uint32_t report_val = CCI_I2C_REPORT_CMD | (1 << 8);
275
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700276 CAM_DBG(CAM_CCI, "CCI_I2C_REPORT_CMD curr_w_cnt: %d", read_val);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800277 cam_io_w_mb(report_val,
Alok Pandey01b1b352017-06-25 20:38:54 +0530278 base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800279 reg_offset);
280 read_val++;
281
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700282 CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR %d", read_val);
Alok Pandey01b1b352017-06-25 20:38:54 +0530283 cam_io_w_mb(read_val, base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800284 CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + reg_offset);
285}
286
287static int32_t cam_cci_wait_report_cmd(struct cci_device *cci_dev,
288 enum cci_i2c_master_t master,
289 enum cci_i2c_queue_t queue)
290{
Alok Pandey01b1b352017-06-25 20:38:54 +0530291 struct cam_hw_soc_info *soc_info =
292 &cci_dev->soc_info;
293 void __iomem *base = soc_info->reg_map[0].mem_base;
294
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800295 uint32_t reg_val = 1 << ((master * 2) + queue);
296
297 cam_cci_load_report_cmd(cci_dev, master, queue);
298 atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 1);
299 atomic_set(&cci_dev->cci_master_info[master].done_pending[queue], 1);
Alok Pandey01b1b352017-06-25 20:38:54 +0530300 cam_io_w_mb(reg_val, base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800301 CCI_QUEUE_START_ADDR);
302
303 return cam_cci_wait(cci_dev, master, queue);
304}
305
306static int32_t cam_cci_transfer_end(struct cci_device *cci_dev,
307 enum cci_i2c_master_t master,
308 enum cci_i2c_queue_t queue)
309{
310 int32_t rc = 0;
311
312 if (atomic_read(&cci_dev->cci_master_info[master].q_free[queue]) == 0) {
313 rc = cam_cci_lock_queue(cci_dev, master, queue, 0);
314 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700315 CAM_ERR(CAM_CCI, "failed line %d");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800316 return rc;
317 }
318 rc = cam_cci_wait_report_cmd(cci_dev, master, queue);
319 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700320 CAM_ERR(CAM_CCI, "failed rc %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800321 return rc;
322 }
323 } else {
324 atomic_set(&cci_dev->cci_master_info[master].
325 done_pending[queue], 1);
326 rc = cam_cci_wait(cci_dev, master, queue);
327 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700328 CAM_ERR(CAM_CCI, "failed rc %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800329 return rc;
330 }
331 rc = cam_cci_lock_queue(cci_dev, master, queue, 0);
332 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700333 CAM_ERR(CAM_CCI, "failed rc %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800334 return rc;
335 }
336 rc = cam_cci_wait_report_cmd(cci_dev, master, queue);
337 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700338 CAM_ERR(CAM_CCI, "Failed rc %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800339 return rc;
340 }
341 }
342
343 return rc;
344}
345
346static int32_t cam_cci_get_queue_free_size(struct cci_device *cci_dev,
347 enum cci_i2c_master_t master,
348 enum cci_i2c_queue_t queue)
349{
350 uint32_t read_val = 0;
351 uint32_t reg_offset = master * 0x200 + queue * 0x100;
Alok Pandey01b1b352017-06-25 20:38:54 +0530352 struct cam_hw_soc_info *soc_info =
353 &cci_dev->soc_info;
354 void __iomem *base = soc_info->reg_map[0].mem_base;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800355
Alok Pandey01b1b352017-06-25 20:38:54 +0530356 read_val = cam_io_r_mb(base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800357 CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + reg_offset);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700358 CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR %d max %d", read_val,
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800359 cci_dev->cci_i2c_queue_info[master][queue].max_queue_size);
360 return (cci_dev->
361 cci_i2c_queue_info[master][queue].max_queue_size) -
362 read_val;
363}
364
365static void cam_cci_process_half_q(struct cci_device *cci_dev,
366 enum cci_i2c_master_t master,
367 enum cci_i2c_queue_t queue)
368{
Alok Pandey01b1b352017-06-25 20:38:54 +0530369 struct cam_hw_soc_info *soc_info =
370 &cci_dev->soc_info;
371 void __iomem *base = soc_info->reg_map[0].mem_base;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800372 uint32_t reg_val = 1 << ((master * 2) + queue);
373
374 if (atomic_read(&cci_dev->cci_master_info[master].q_free[queue]) == 0) {
375 cam_cci_load_report_cmd(cci_dev, master, queue);
376 atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 1);
Alok Pandey01b1b352017-06-25 20:38:54 +0530377 cam_io_w_mb(reg_val, base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800378 CCI_QUEUE_START_ADDR);
379 }
380}
381
382static int32_t cam_cci_process_full_q(struct cci_device *cci_dev,
383 enum cci_i2c_master_t master,
384 enum cci_i2c_queue_t queue)
385{
386 int32_t rc = 0;
387
388 if (atomic_read(&cci_dev->cci_master_info[master].q_free[queue]) == 1) {
389 atomic_set(&cci_dev->cci_master_info[master].
390 done_pending[queue], 1);
391 rc = cam_cci_wait(cci_dev, master, queue);
392 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700393 CAM_ERR(CAM_CCI, "failed rc %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800394 return rc;
395 }
396 } else {
397 rc = cam_cci_wait_report_cmd(cci_dev, master, queue);
398 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700399 CAM_ERR(CAM_CCI, "failed rc %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800400 return rc;
401 }
402 }
403
404 return rc;
405}
406
407static int32_t cam_cci_calc_cmd_len(struct cci_device *cci_dev,
408 struct cam_cci_ctrl *c_ctrl, uint32_t cmd_size,
409 struct cam_sensor_i2c_reg_array *i2c_cmd, uint32_t *pack)
410{
411 uint8_t i;
412 uint32_t len = 0;
413 uint8_t data_len = 0, addr_len = 0;
414 uint8_t pack_max_len;
415 struct cam_sensor_i2c_reg_setting *msg;
416 struct cam_sensor_i2c_reg_array *cmd = i2c_cmd;
417 uint32_t size = cmd_size;
418
419 if (!cci_dev || !c_ctrl) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700420 CAM_ERR(CAM_CCI, "failed");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800421 return -EINVAL;
422 }
423
424 msg = &c_ctrl->cfg.cci_i2c_write_cfg;
425 *pack = 0;
426
Karthik Anantha Ram0fb02a32017-08-23 11:52:50 -0700427 if (c_ctrl->cmd == MSM_CCI_I2C_WRITE_SEQ ||
428 c_ctrl->cmd == MSM_CCI_I2C_WRITE_BURST) {
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800429 addr_len = cam_cci_convert_type_to_num_bytes(msg->addr_type);
430 len = (size + addr_len) <= (cci_dev->payload_size) ?
431 (size + addr_len):cci_dev->payload_size;
432 } else {
433 addr_len = cam_cci_convert_type_to_num_bytes(msg->addr_type);
434 data_len = cam_cci_convert_type_to_num_bytes(msg->data_type);
435 len = data_len + addr_len;
436 pack_max_len = size < (cci_dev->payload_size-len) ?
437 size : (cci_dev->payload_size-len);
438 for (i = 0; i < pack_max_len;) {
439 if (cmd->delay || ((cmd - i2c_cmd) >= (cmd_size - 1)))
440 break;
441 if (cmd->reg_addr + 1 ==
442 (cmd+1)->reg_addr) {
443 len += data_len;
Wei Ding86e889b2017-10-25 17:24:20 +0800444 (*pack)++;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800445 } else {
446 break;
447 }
448 i += data_len;
449 cmd++;
450 }
451 }
452
453 if (len > cci_dev->payload_size) {
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700454 CAM_ERR(CAM_CCI, "Len error: %d", len);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800455 return -EINVAL;
456 }
457
458 len += 1; /*add i2c WR command*/
459 len = len/4 + 1;
460
461 return len;
462}
463
464static uint32_t cam_cci_cycles_per_ms(unsigned long clk)
465{
466 uint32_t cycles_per_us;
467
468 if (clk) {
469 cycles_per_us = ((clk/1000)*256)/1000;
470 } else {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700471 CAM_ERR(CAM_CCI, "failed: Can use default: %d",
472 CYCLES_PER_MICRO_SEC_DEFAULT);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800473 cycles_per_us = CYCLES_PER_MICRO_SEC_DEFAULT;
474 }
475
476 return cycles_per_us;
477}
478
Alok Pandey01b1b352017-06-25 20:38:54 +0530479void cam_cci_get_clk_rates(struct cci_device *cci_dev,
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800480 struct cam_cci_ctrl *c_ctrl)
Alok Pandey01b1b352017-06-25 20:38:54 +0530481
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800482{
Alok Pandey01b1b352017-06-25 20:38:54 +0530483 int32_t src_clk_idx, j;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800484 uint32_t cci_clk_src;
485 unsigned long clk;
486 struct cam_cci_clk_params_t *clk_params = NULL;
Alok Pandey01b1b352017-06-25 20:38:54 +0530487
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800488 enum i2c_freq_mode i2c_freq_mode = c_ctrl->cci_info->i2c_freq_mode;
Alok Pandey01b1b352017-06-25 20:38:54 +0530489 struct cam_hw_soc_info *soc_info = &cci_dev->soc_info;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800490
491 if (i2c_freq_mode >= I2C_MAX_MODES ||
492 i2c_freq_mode < I2C_STANDARD_MODE) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700493 CAM_ERR(CAM_CCI, "Invalid frequency mode: %d",
494 (int32_t)i2c_freq_mode);
Alok Pandey01b1b352017-06-25 20:38:54 +0530495 cci_dev->clk_level_index = -1;
496 return;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800497 }
498
499 clk_params = &cci_dev->cci_clk_params[i2c_freq_mode];
500 cci_clk_src = clk_params->cci_clk_src;
501
Alok Pandey01b1b352017-06-25 20:38:54 +0530502 src_clk_idx = soc_info->src_clk_idx;
503
504 if (src_clk_idx < 0) {
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800505 cci_dev->cycles_per_us = CYCLES_PER_MICRO_SEC_DEFAULT;
Alok Pandey01b1b352017-06-25 20:38:54 +0530506 cci_dev->clk_level_index = 0;
507 return;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800508 }
509
510 if (cci_clk_src == 0) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530511 clk = soc_info->clk_rate[0][src_clk_idx];
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800512 cci_dev->cycles_per_us = cam_cci_cycles_per_ms(clk);
Alok Pandey01b1b352017-06-25 20:38:54 +0530513 cci_dev->clk_level_index = 0;
514 return;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800515 }
516
Alok Pandey01b1b352017-06-25 20:38:54 +0530517 for (j = 0; j < CAM_MAX_VOTE; j++) {
518 clk = soc_info->clk_rate[j][src_clk_idx];
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800519 if (clk == cci_clk_src) {
520 cci_dev->cycles_per_us = cam_cci_cycles_per_ms(clk);
Alok Pandey01b1b352017-06-25 20:38:54 +0530521 cci_dev->clk_level_index = j;
522 return;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800523 }
524 }
Alok Pandey01b1b352017-06-25 20:38:54 +0530525 return;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800526}
527
528static int32_t cam_cci_set_clk_param(struct cci_device *cci_dev,
529 struct cam_cci_ctrl *c_ctrl)
530{
531 struct cam_cci_clk_params_t *clk_params = NULL;
532 enum cci_i2c_master_t master = c_ctrl->cci_info->cci_i2c_master;
533 enum i2c_freq_mode i2c_freq_mode = c_ctrl->cci_info->i2c_freq_mode;
Alok Pandey01b1b352017-06-25 20:38:54 +0530534 struct cam_hw_soc_info *soc_info =
535 &cci_dev->soc_info;
536 void __iomem *base = soc_info->reg_map[0].mem_base;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800537
538 if ((i2c_freq_mode >= I2C_MAX_MODES) || (i2c_freq_mode < 0)) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700539 CAM_ERR(CAM_CCI, "invalid i2c_freq_mode = %d", i2c_freq_mode);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800540 return -EINVAL;
541 }
542
543 clk_params = &cci_dev->cci_clk_params[i2c_freq_mode];
544
545 if (cci_dev->i2c_freq_mode[master] == i2c_freq_mode)
546 return 0;
547 if (master == MASTER_0) {
548 cam_io_w_mb(clk_params->hw_thigh << 16 |
549 clk_params->hw_tlow,
Alok Pandey01b1b352017-06-25 20:38:54 +0530550 base + CCI_I2C_M0_SCL_CTL_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800551 cam_io_w_mb(clk_params->hw_tsu_sto << 16 |
552 clk_params->hw_tsu_sta,
Alok Pandey01b1b352017-06-25 20:38:54 +0530553 base + CCI_I2C_M0_SDA_CTL_0_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800554 cam_io_w_mb(clk_params->hw_thd_dat << 16 |
555 clk_params->hw_thd_sta,
Alok Pandey01b1b352017-06-25 20:38:54 +0530556 base + CCI_I2C_M0_SDA_CTL_1_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800557 cam_io_w_mb(clk_params->hw_tbuf,
Alok Pandey01b1b352017-06-25 20:38:54 +0530558 base + CCI_I2C_M0_SDA_CTL_2_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800559 cam_io_w_mb(clk_params->hw_scl_stretch_en << 8 |
560 clk_params->hw_trdhld << 4 | clk_params->hw_tsp,
Alok Pandey01b1b352017-06-25 20:38:54 +0530561 base + CCI_I2C_M0_MISC_CTL_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800562 } else if (master == MASTER_1) {
563 cam_io_w_mb(clk_params->hw_thigh << 16 |
564 clk_params->hw_tlow,
Alok Pandey01b1b352017-06-25 20:38:54 +0530565 base + CCI_I2C_M1_SCL_CTL_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800566 cam_io_w_mb(clk_params->hw_tsu_sto << 16 |
567 clk_params->hw_tsu_sta,
Alok Pandey01b1b352017-06-25 20:38:54 +0530568 base + CCI_I2C_M1_SDA_CTL_0_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800569 cam_io_w_mb(clk_params->hw_thd_dat << 16 |
570 clk_params->hw_thd_sta,
Alok Pandey01b1b352017-06-25 20:38:54 +0530571 base + CCI_I2C_M1_SDA_CTL_1_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800572 cam_io_w_mb(clk_params->hw_tbuf,
Alok Pandey01b1b352017-06-25 20:38:54 +0530573 base + CCI_I2C_M1_SDA_CTL_2_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800574 cam_io_w_mb(clk_params->hw_scl_stretch_en << 8 |
575 clk_params->hw_trdhld << 4 | clk_params->hw_tsp,
Alok Pandey01b1b352017-06-25 20:38:54 +0530576 base + CCI_I2C_M1_MISC_CTL_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800577 }
578 cci_dev->i2c_freq_mode[master] = i2c_freq_mode;
579
580 return 0;
581}
582
583static int32_t cam_cci_data_queue(struct cci_device *cci_dev,
584 struct cam_cci_ctrl *c_ctrl, enum cci_i2c_queue_t queue,
585 enum cci_i2c_sync sync_en)
586{
587 uint16_t i = 0, j = 0, k = 0, h = 0, len = 0;
588 int32_t rc = 0, free_size = 0, en_seq_write = 0;
589 uint8_t data[12];
590 struct cam_sensor_i2c_reg_setting *i2c_msg =
591 &c_ctrl->cfg.cci_i2c_write_cfg;
592 struct cam_sensor_i2c_reg_array *i2c_cmd = i2c_msg->reg_setting;
593 enum cci_i2c_master_t master = c_ctrl->cci_info->cci_i2c_master;
594 uint16_t reg_addr = 0, cmd_size = i2c_msg->size;
595 uint32_t read_val = 0, reg_offset, val, delay = 0;
596 uint32_t max_queue_size, queue_size = 0, cmd = 0;
Alok Pandey01b1b352017-06-25 20:38:54 +0530597 struct cam_hw_soc_info *soc_info =
598 &cci_dev->soc_info;
599 void __iomem *base = soc_info->reg_map[0].mem_base;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800600
601 if (i2c_cmd == NULL) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700602 CAM_ERR(CAM_CCI, "Failed: i2c cmd is NULL");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800603 return -EINVAL;
604 }
605
606 if ((!cmd_size) || (cmd_size > CCI_I2C_MAX_WRITE)) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700607 CAM_ERR(CAM_CCI, "failed: invalid cmd_size %d",
608 cmd_size);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800609 return -EINVAL;
610 }
611
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700612 CAM_DBG(CAM_CCI, "addr type %d data type %d cmd_size %d",
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800613 i2c_msg->addr_type, i2c_msg->data_type, cmd_size);
614
615 if (i2c_msg->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700616 CAM_ERR(CAM_CCI, "failed: invalid addr_type 0x%X",
617 i2c_msg->addr_type);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800618 return -EINVAL;
619 }
620 if (i2c_msg->data_type >= CAMERA_SENSOR_I2C_TYPE_MAX) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700621 CAM_ERR(CAM_CCI, "failed: invalid data_type 0x%X",
622 i2c_msg->data_type);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800623 return -EINVAL;
624 }
625 reg_offset = master * 0x200 + queue * 0x100;
626
627 cam_io_w_mb(cci_dev->cci_wait_sync_cfg.cid,
Alok Pandey01b1b352017-06-25 20:38:54 +0530628 base + CCI_SET_CID_SYNC_TIMER_ADDR +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800629 cci_dev->cci_wait_sync_cfg.csid *
630 CCI_SET_CID_SYNC_TIMER_OFFSET);
631
632 val = CCI_I2C_SET_PARAM_CMD | c_ctrl->cci_info->sid << 4 |
633 c_ctrl->cci_info->retries << 16 |
634 c_ctrl->cci_info->id_map << 18;
635
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700636 CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_LOAD_DATA_ADDR:val 0x%x:0x%x",
637 CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800638 reg_offset, val);
Alok Pandey01b1b352017-06-25 20:38:54 +0530639 cam_io_w_mb(val, base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800640 reg_offset);
641
642 atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 0);
643
644 max_queue_size = cci_dev->cci_i2c_queue_info[master][queue].
645 max_queue_size;
646
647 if (c_ctrl->cmd == MSM_CCI_I2C_WRITE_SEQ)
648 queue_size = max_queue_size;
649 else
650 queue_size = max_queue_size/2;
651 reg_addr = i2c_cmd->reg_addr;
652
653 if (sync_en == MSM_SYNC_ENABLE && cci_dev->valid_sync &&
654 cmd_size < max_queue_size) {
655 val = CCI_I2C_WAIT_SYNC_CMD |
656 ((cci_dev->cci_wait_sync_cfg.line) << 4);
657 cam_io_w_mb(val,
Alok Pandey01b1b352017-06-25 20:38:54 +0530658 base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800659 reg_offset);
660 }
661
662 rc = cam_cci_lock_queue(cci_dev, master, queue, 1);
663 if (rc < 0) {
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700664 CAM_ERR(CAM_CCI, "failed line %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800665 return rc;
666 }
667
668 while (cmd_size) {
669 uint32_t pack = 0;
670
671 len = cam_cci_calc_cmd_len(cci_dev, c_ctrl, cmd_size,
672 i2c_cmd, &pack);
673 if (len <= 0) {
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700674 CAM_ERR(CAM_CCI, "failed");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800675 return -EINVAL;
676 }
677
Alok Pandey01b1b352017-06-25 20:38:54 +0530678 read_val = cam_io_r_mb(base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800679 CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + reg_offset);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700680 CAM_DBG(CAM_CCI, "CUR_WORD_CNT_ADDR %d len %d max %d",
681 read_val, len, max_queue_size);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800682 /* + 1 - space alocation for Report CMD */
683 if ((read_val + len + 1) > queue_size) {
684 if ((read_val + len + 1) > max_queue_size) {
685 rc = cam_cci_process_full_q(cci_dev,
686 master, queue);
687 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700688 CAM_ERR(CAM_CCI, "failed rc: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800689 return rc;
690 }
691 continue;
692 }
693 cam_cci_process_half_q(cci_dev, master, queue);
694 }
695
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700696 CAM_DBG(CAM_CCI, "cmd_size %d addr 0x%x data 0x%x",
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800697 cmd_size, i2c_cmd->reg_addr, i2c_cmd->reg_data);
698 delay = i2c_cmd->delay;
699 i = 0;
700 data[i++] = CCI_I2C_WRITE_CMD;
701
702 /*
703 * in case of multiple command
704 * MSM_CCI_I2C_WRITE : address is not continuous, so update
705 * address for a new packet.
706 * MSM_CCI_I2C_WRITE_SEQ : address is continuous, need to keep
707 * the incremented address for a
708 * new packet
709 */
710 if (c_ctrl->cmd == MSM_CCI_I2C_WRITE ||
711 c_ctrl->cmd == MSM_CCI_I2C_WRITE_ASYNC ||
712 c_ctrl->cmd == MSM_CCI_I2C_WRITE_SYNC ||
713 c_ctrl->cmd == MSM_CCI_I2C_WRITE_SYNC_BLOCK)
714 reg_addr = i2c_cmd->reg_addr;
715
716 if (en_seq_write == 0) {
717 /* either byte or word addr */
718 if (i2c_msg->addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE)
719 data[i++] = reg_addr;
720 else {
721 data[i++] = (reg_addr & 0xFF00) >> 8;
722 data[i++] = reg_addr & 0x00FF;
723 }
724 }
725 /* max of 10 data bytes */
726 do {
727 if (i2c_msg->data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) {
728 data[i++] = i2c_cmd->reg_data;
Karthik Anantha Ram0fb02a32017-08-23 11:52:50 -0700729 if (c_ctrl->cmd == MSM_CCI_I2C_WRITE_SEQ)
730 reg_addr++;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800731 } else {
732 if ((i + 1) <= cci_dev->payload_size) {
Depeng Shaoc06b3972017-11-10 08:37:07 +0800733 switch (i2c_msg->data_type) {
734 case CAMERA_SENSOR_I2C_TYPE_DWORD:
Wei Ding86e889b2017-10-25 17:24:20 +0800735 data[i++] = (i2c_cmd->reg_data &
736 0xFF000000) >> 24;
Depeng Shaoc06b3972017-11-10 08:37:07 +0800737 /* fallthrough */
738 case CAMERA_SENSOR_I2C_TYPE_3B:
Wei Ding86e889b2017-10-25 17:24:20 +0800739 data[i++] = (i2c_cmd->reg_data &
740 0x00FF0000) >> 16;
Depeng Shaoc06b3972017-11-10 08:37:07 +0800741 /* fallthrough */
742 case CAMERA_SENSOR_I2C_TYPE_WORD:
743 data[i++] = (i2c_cmd->reg_data &
744 0x0000FF00) >> 8;
745 /* fallthrough */
746 case CAMERA_SENSOR_I2C_TYPE_BYTE:
747 data[i++] = i2c_cmd->reg_data &
748 0x000000FF;
749 break;
750 default:
751 CAM_ERR(CAM_CCI,
752 "invalid data type: %d",
753 i2c_msg->data_type);
754 return -EINVAL;
Wei Ding86e889b2017-10-25 17:24:20 +0800755 }
Depeng Shaoc06b3972017-11-10 08:37:07 +0800756
Karthik Anantha Ram0fb02a32017-08-23 11:52:50 -0700757 if (c_ctrl->cmd ==
758 MSM_CCI_I2C_WRITE_SEQ)
759 reg_addr++;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800760 } else
761 break;
762 }
763 i2c_cmd++;
764 --cmd_size;
Karthik Anantha Ram0fb02a32017-08-23 11:52:50 -0700765 } while (((c_ctrl->cmd == MSM_CCI_I2C_WRITE_SEQ ||
766 c_ctrl->cmd == MSM_CCI_I2C_WRITE_BURST) || pack--) &&
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800767 (cmd_size > 0) && (i <= cci_dev->payload_size));
768 free_size = cam_cci_get_queue_free_size(cci_dev, master,
769 queue);
Karthik Anantha Ram0fb02a32017-08-23 11:52:50 -0700770 if ((c_ctrl->cmd == MSM_CCI_I2C_WRITE_SEQ ||
771 c_ctrl->cmd == MSM_CCI_I2C_WRITE_BURST) &&
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800772 ((i-1) == MSM_CCI_WRITE_DATA_PAYLOAD_SIZE_11) &&
773 cci_dev->support_seq_write && cmd_size > 0 &&
774 free_size > BURST_MIN_FREE_SIZE) {
775 data[0] |= 0xF0;
776 en_seq_write = 1;
777 } else {
778 data[0] |= ((i-1) << 4);
779 en_seq_write = 0;
780 }
781 len = ((i-1)/4) + 1;
782
Alok Pandey01b1b352017-06-25 20:38:54 +0530783 read_val = cam_io_r_mb(base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800784 CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + reg_offset);
785 for (h = 0, k = 0; h < len; h++) {
786 cmd = 0;
787 for (j = 0; (j < 4 && k < i); j++)
788 cmd |= (data[k++] << (j * 8));
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700789 CAM_DBG(CAM_CCI,
790 "LOAD_DATA_ADDR 0x%x, q: %d, len:%d, cnt: %d",
791 cmd, queue, len, read_val);
Alok Pandey01b1b352017-06-25 20:38:54 +0530792 cam_io_w_mb(cmd, base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800793 CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
794 master * 0x200 + queue * 0x100);
795
796 read_val += 1;
Alok Pandey01b1b352017-06-25 20:38:54 +0530797 cam_io_w_mb(read_val, base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800798 CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + reg_offset);
799 }
800
801 if ((delay > 0) && (delay < CCI_MAX_DELAY) &&
802 en_seq_write == 0) {
803 cmd = (uint32_t)((delay * cci_dev->cycles_per_us) /
804 0x100);
805 cmd <<= 4;
806 cmd |= CCI_I2C_WAIT_CMD;
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700807 CAM_DBG(CAM_CCI,
808 "CCI_I2C_M0_Q0_LOAD_DATA_ADDR 0x%x", cmd);
Alok Pandey01b1b352017-06-25 20:38:54 +0530809 cam_io_w_mb(cmd, base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800810 CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
811 master * 0x200 + queue * 0x100);
812 read_val += 1;
Alok Pandey01b1b352017-06-25 20:38:54 +0530813 cam_io_w_mb(read_val, base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800814 CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + reg_offset);
815 }
816 }
817
818 rc = cam_cci_transfer_end(cci_dev, master, queue);
819 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700820 CAM_ERR(CAM_CCI, "failed rc %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800821 return rc;
822 }
823
824 return rc;
825}
826
827static int32_t cam_cci_read(struct v4l2_subdev *sd,
828 struct cam_cci_ctrl *c_ctrl)
829{
830 int32_t rc = 0;
831 uint32_t val = 0;
832 int32_t read_words = 0, exp_words = 0;
833 int32_t index = 0, first_byte = 0;
834 uint32_t i = 0;
835 enum cci_i2c_master_t master;
836 enum cci_i2c_queue_t queue = QUEUE_1;
837 struct cci_device *cci_dev = NULL;
838 struct cam_cci_read_cfg *read_cfg = NULL;
Alok Pandey01b1b352017-06-25 20:38:54 +0530839 struct cam_hw_soc_info *soc_info = NULL;
840 void __iomem *base = NULL;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800841
842 cci_dev = v4l2_get_subdevdata(sd);
843 master = c_ctrl->cci_info->cci_i2c_master;
844 read_cfg = &c_ctrl->cfg.cci_i2c_read_cfg;
845
846 if (c_ctrl->cci_info->cci_i2c_master >= MASTER_MAX
847 || c_ctrl->cci_info->cci_i2c_master < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700848 CAM_ERR(CAM_CCI, "Invalid I2C master addr");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800849 return -EINVAL;
850 }
Alok Pandey01b1b352017-06-25 20:38:54 +0530851
852 soc_info = &cci_dev->soc_info;
853 base = soc_info->reg_map[0].mem_base;
854
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800855 mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);
856
857 /*
858 * Todo: If there is a change in frequency of operation
859 * Wait for previos transaction to complete
860 */
861
862 /* Set the I2C Frequency */
863 rc = cam_cci_set_clk_param(cci_dev, c_ctrl);
864 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700865 CAM_ERR(CAM_CCI, "cam_cci_set_clk_param failed rc = %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800866 goto rel_mutex;
867 }
868
869 /*
870 * Call validate queue to make sure queue is empty before starting.
871 * If this call fails, don't proceed with i2c_read call. This is to
872 * avoid overflow / underflow of queue
873 */
874 rc = cam_cci_validate_queue(cci_dev,
875 cci_dev->cci_i2c_queue_info[master][queue].max_queue_size - 1,
876 master, queue);
877 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700878 CAM_ERR(CAM_CCI, "Initial validataion failed rc %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800879 goto rel_mutex;
880 }
881
882 if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700883 CAM_ERR(CAM_CCI, "More than max retries");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800884 goto rel_mutex;
885 }
886
887 if (read_cfg->data == NULL) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700888 CAM_ERR(CAM_CCI, "Data ptr is NULL");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800889 goto rel_mutex;
890 }
891
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700892 CAM_DBG(CAM_CCI, "master %d, queue %d", master, queue);
893 CAM_DBG(CAM_CCI, "set param sid 0x%x retries %d id_map %d",
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800894 c_ctrl->cci_info->sid, c_ctrl->cci_info->retries,
895 c_ctrl->cci_info->id_map);
896 val = CCI_I2C_SET_PARAM_CMD | c_ctrl->cci_info->sid << 4 |
897 c_ctrl->cci_info->retries << 16 |
898 c_ctrl->cci_info->id_map << 18;
899 rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
900 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700901 CAM_DBG(CAM_CCI, "failed rc: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800902 goto rel_mutex;
903 }
904
905 val = CCI_I2C_LOCK_CMD;
906 rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
907 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700908 CAM_DBG(CAM_CCI, "failed rc: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800909 goto rel_mutex;
910 }
911
912 if (read_cfg->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700913 CAM_ERR(CAM_CCI, "failed : Invalid addr type: %u",
914 read_cfg->addr_type);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800915 rc = -EINVAL;
916 goto rel_mutex;
917 }
918
919 val = CCI_I2C_WRITE_DISABLE_P_CMD | (read_cfg->addr_type << 4);
920 for (i = 0; i < read_cfg->addr_type; i++) {
921 val |= ((read_cfg->addr >> (i << 3)) & 0xFF) <<
922 ((read_cfg->addr_type - i) << 3);
923 }
924
925 rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
926 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700927 CAM_DBG(CAM_CCI, "failed rc: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800928 goto rel_mutex;
929 }
930
931 val = CCI_I2C_READ_CMD | (read_cfg->num_byte << 4);
932 rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
933 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700934 CAM_DBG(CAM_CCI, "failed rc: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800935 goto rel_mutex;
936 }
937
938 val = CCI_I2C_UNLOCK_CMD;
939 rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
940 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700941 CAM_DBG(CAM_CCI, "failed rc: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800942 goto rel_mutex;
943 }
944
Alok Pandey01b1b352017-06-25 20:38:54 +0530945 val = cam_io_r_mb(base + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800946 + master * 0x200 + queue * 0x100);
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700947 CAM_DBG(CAM_CCI, "cur word cnt 0x%x", val);
Alok Pandey01b1b352017-06-25 20:38:54 +0530948 cam_io_w_mb(val, base + CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800949 + master * 0x200 + queue * 0x100);
950
951 val = 1 << ((master * 2) + queue);
Alok Pandey01b1b352017-06-25 20:38:54 +0530952 cam_io_w_mb(val, base + CCI_QUEUE_START_ADDR);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700953 CAM_DBG(CAM_CCI, "wait_for_completion_timeout");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800954
955 rc = wait_for_completion_timeout(&cci_dev->
956 cci_master_info[master].reset_complete, CCI_TIMEOUT);
957 if (rc <= 0) {
958#ifdef DUMP_CCI_REGISTERS
959 cam_cci_dump_registers(cci_dev, master, queue);
960#endif
961 if (rc == 0)
962 rc = -ETIMEDOUT;
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700963 CAM_ERR(CAM_CCI, "wait_for_completion_timeout rc = %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800964 cam_cci_flush_queue(cci_dev, master);
965 goto rel_mutex;
966 } else {
967 rc = 0;
968 }
969
Alok Pandey01b1b352017-06-25 20:38:54 +0530970 read_words = cam_io_r_mb(base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800971 CCI_I2C_M0_READ_BUF_LEVEL_ADDR + master * 0x100);
972 exp_words = ((read_cfg->num_byte / 4) + 1);
973 if (read_words != exp_words) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700974 CAM_ERR(CAM_CCI, "read_words = %d, exp words = %d",
975 read_words, exp_words);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800976 memset(read_cfg->data, 0, read_cfg->num_byte);
977 rc = -EINVAL;
978 goto rel_mutex;
979 }
980 index = 0;
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700981 CAM_DBG(CAM_CCI, "index %d num_type %d", index, read_cfg->num_byte);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800982 first_byte = 0;
983 do {
Alok Pandey01b1b352017-06-25 20:38:54 +0530984 val = cam_io_r_mb(base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800985 CCI_I2C_M0_READ_DATA_ADDR + master * 0x100);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700986 CAM_DBG(CAM_CCI, "read val 0x%x", val);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800987 for (i = 0; (i < 4) && (index < read_cfg->num_byte); i++) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700988 CAM_DBG(CAM_CCI, "i:%d index:%d", i, index);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800989 if (!first_byte) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700990 CAM_DBG(CAM_CCI, "sid 0x%x", val & 0xFF);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800991 first_byte++;
992 } else {
993 read_cfg->data[index] =
994 (val >> (i * 8)) & 0xFF;
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700995 CAM_DBG(CAM_CCI, "data[%d] 0x%x", index,
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800996 read_cfg->data[index]);
997 index++;
998 }
999 }
1000 } while (--read_words > 0);
1001rel_mutex:
1002 mutex_unlock(&cci_dev->cci_master_info[master].mutex_q[queue]);
1003
1004 return rc;
1005}
1006
1007static int32_t cam_cci_i2c_write(struct v4l2_subdev *sd,
1008 struct cam_cci_ctrl *c_ctrl, enum cci_i2c_queue_t queue,
1009 enum cci_i2c_sync sync_en)
1010{
1011 int32_t rc = 0;
1012 struct cci_device *cci_dev;
1013 enum cci_i2c_master_t master;
1014
1015 cci_dev = v4l2_get_subdevdata(sd);
1016
1017 if (cci_dev->cci_state != CCI_STATE_ENABLED) {
Jigarkumar Zala22223f92017-07-28 12:46:27 -07001018 CAM_ERR(CAM_CCI, "invalid cci state %d",
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001019 cci_dev->cci_state);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001020 return -EINVAL;
1021 }
1022 master = c_ctrl->cci_info->cci_i2c_master;
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001023 CAM_DBG(CAM_CCI, "set param sid 0x%x retries %d id_map %d",
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001024 c_ctrl->cci_info->sid, c_ctrl->cci_info->retries,
1025 c_ctrl->cci_info->id_map);
1026
1027 /* Set the I2C Frequency */
1028 rc = cam_cci_set_clk_param(cci_dev, c_ctrl);
1029 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001030 CAM_ERR(CAM_CCI, "cam_cci_set_clk_param failed rc = %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001031 return rc;
1032 }
1033 /*
1034 * Call validate queue to make sure queue is empty before starting.
1035 * If this call fails, don't proceed with i2c_write call. This is to
1036 * avoid overflow / underflow of queue
1037 */
1038 rc = cam_cci_validate_queue(cci_dev,
1039 cci_dev->cci_i2c_queue_info[master][queue].max_queue_size-1,
1040 master, queue);
1041 if (rc < 0) {
Jigarkumar Zala22223f92017-07-28 12:46:27 -07001042 CAM_ERR(CAM_CCI, "Initial validataion failed rc %d",
1043 rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001044 return rc;
1045 }
1046 if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001047 CAM_ERR(CAM_CCI, "More than max retries");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001048 return rc;
1049 }
1050 rc = cam_cci_data_queue(cci_dev, c_ctrl, queue, sync_en);
1051 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001052 CAM_ERR(CAM_CCI, "failed rc: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001053 return rc;
1054 }
1055
1056 return rc;
1057}
1058
1059static void cam_cci_write_async_helper(struct work_struct *work)
1060{
1061 int rc;
1062 struct cci_device *cci_dev;
1063 struct cci_write_async *write_async =
1064 container_of(work, struct cci_write_async, work);
1065 struct cam_sensor_i2c_reg_setting *i2c_msg;
1066 enum cci_i2c_master_t master;
1067 struct cam_cci_master_info *cci_master_info;
1068
1069 cci_dev = write_async->cci_dev;
1070 i2c_msg = &write_async->c_ctrl.cfg.cci_i2c_write_cfg;
1071 master = write_async->c_ctrl.cci_info->cci_i2c_master;
1072 cci_master_info = &cci_dev->cci_master_info[master];
1073
1074 mutex_lock(&cci_master_info->mutex_q[write_async->queue]);
1075 rc = cam_cci_i2c_write(&(cci_dev->v4l2_dev_str.sd),
1076 &write_async->c_ctrl, write_async->queue, write_async->sync_en);
1077 mutex_unlock(&cci_master_info->mutex_q[write_async->queue]);
1078 if (rc < 0)
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001079 CAM_ERR(CAM_CCI, "failed rc: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001080
1081 kfree(write_async->c_ctrl.cfg.cci_i2c_write_cfg.reg_setting);
1082 kfree(write_async);
1083}
1084
1085static int32_t cam_cci_i2c_write_async(struct v4l2_subdev *sd,
1086 struct cam_cci_ctrl *c_ctrl, enum cci_i2c_queue_t queue,
1087 enum cci_i2c_sync sync_en)
1088{
1089 int32_t rc = 0;
1090 struct cci_write_async *write_async;
1091 struct cci_device *cci_dev;
1092 struct cam_sensor_i2c_reg_setting *cci_i2c_write_cfg;
1093 struct cam_sensor_i2c_reg_setting *cci_i2c_write_cfg_w;
1094
1095 cci_dev = v4l2_get_subdevdata(sd);
1096
1097 write_async = kzalloc(sizeof(*write_async), GFP_KERNEL);
1098 if (!write_async)
1099 return -ENOMEM;
1100
1101
1102 INIT_WORK(&write_async->work, cam_cci_write_async_helper);
1103 write_async->cci_dev = cci_dev;
1104 write_async->c_ctrl = *c_ctrl;
1105 write_async->queue = queue;
1106 write_async->sync_en = sync_en;
1107
1108 cci_i2c_write_cfg = &c_ctrl->cfg.cci_i2c_write_cfg;
1109 cci_i2c_write_cfg_w = &write_async->c_ctrl.cfg.cci_i2c_write_cfg;
1110
1111 if (cci_i2c_write_cfg->size == 0) {
1112 kfree(write_async);
1113 return -EINVAL;
1114 }
1115
1116 cci_i2c_write_cfg_w->reg_setting =
1117 kzalloc(sizeof(struct cam_sensor_i2c_reg_array)*
1118 cci_i2c_write_cfg->size, GFP_KERNEL);
1119 if (!cci_i2c_write_cfg_w->reg_setting) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001120 CAM_ERR(CAM_CCI, "Couldn't allocate memory");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001121 kfree(write_async);
1122 return -ENOMEM;
1123 }
1124 memcpy(cci_i2c_write_cfg_w->reg_setting,
1125 cci_i2c_write_cfg->reg_setting,
1126 (sizeof(struct cam_sensor_i2c_reg_array)*
1127 cci_i2c_write_cfg->size));
1128
1129 cci_i2c_write_cfg_w->addr_type = cci_i2c_write_cfg->addr_type;
1130 cci_i2c_write_cfg_w->addr_type = cci_i2c_write_cfg->addr_type;
1131 cci_i2c_write_cfg_w->data_type = cci_i2c_write_cfg->data_type;
1132 cci_i2c_write_cfg_w->size = cci_i2c_write_cfg->size;
1133 cci_i2c_write_cfg_w->delay = cci_i2c_write_cfg->delay;
1134
1135 queue_work(cci_dev->write_wq[write_async->queue], &write_async->work);
1136
1137 return rc;
1138}
1139
1140static int32_t cam_cci_read_bytes(struct v4l2_subdev *sd,
1141 struct cam_cci_ctrl *c_ctrl)
1142{
1143 int32_t rc = 0;
1144 struct cci_device *cci_dev = NULL;
1145 enum cci_i2c_master_t master;
1146 struct cam_cci_read_cfg *read_cfg = NULL;
1147 uint16_t read_bytes = 0;
1148
1149 if (!sd || !c_ctrl) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001150 CAM_ERR(CAM_CCI, "sd %pK c_ctrl %pK", sd, c_ctrl);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001151 return -EINVAL;
1152 }
1153 if (!c_ctrl->cci_info) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001154 CAM_ERR(CAM_CCI, "cci_info NULL");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001155 return -EINVAL;
1156 }
1157 cci_dev = v4l2_get_subdevdata(sd);
1158 if (!cci_dev) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001159 CAM_ERR(CAM_CCI, "cci_dev NULL");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001160 return -EINVAL;
1161 }
1162 if (cci_dev->cci_state != CCI_STATE_ENABLED) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001163 CAM_ERR(CAM_CCI, "invalid cci state %d", cci_dev->cci_state);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001164 return -EINVAL;
1165 }
1166
1167 if (c_ctrl->cci_info->cci_i2c_master >= MASTER_MAX
1168 || c_ctrl->cci_info->cci_i2c_master < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001169 CAM_ERR(CAM_CCI, "Invalid I2C master addr");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001170 return -EINVAL;
1171 }
1172
1173 master = c_ctrl->cci_info->cci_i2c_master;
1174 read_cfg = &c_ctrl->cfg.cci_i2c_read_cfg;
1175 if ((!read_cfg->num_byte) || (read_cfg->num_byte > CCI_I2C_MAX_READ)) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001176 CAM_ERR(CAM_CCI, "read num bytes 0");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001177 rc = -EINVAL;
1178 goto ERROR;
1179 }
1180
1181 read_bytes = read_cfg->num_byte;
1182 do {
1183 if (read_bytes > CCI_READ_MAX)
1184 read_cfg->num_byte = CCI_READ_MAX;
1185 else
1186 read_cfg->num_byte = read_bytes;
1187 rc = cam_cci_read(sd, c_ctrl);
1188 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001189 CAM_ERR(CAM_CCI, "failed rc %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001190 goto ERROR;
1191 }
1192 if (read_bytes > CCI_READ_MAX) {
1193 read_cfg->addr += CCI_READ_MAX;
1194 read_cfg->data += CCI_READ_MAX;
1195 read_bytes -= CCI_READ_MAX;
1196 } else {
1197 read_bytes = 0;
1198 }
1199 } while (read_bytes);
1200
1201ERROR:
1202 return rc;
1203}
1204
1205static int32_t cam_cci_i2c_set_sync_prms(struct v4l2_subdev *sd,
1206 struct cam_cci_ctrl *c_ctrl)
1207{
1208 int32_t rc = 0;
1209 struct cci_device *cci_dev;
1210
1211 cci_dev = v4l2_get_subdevdata(sd);
1212 if (!cci_dev || !c_ctrl) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001213 CAM_ERR(CAM_CCI, "failed: invalid params %pK %pK",
1214 cci_dev, c_ctrl);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001215 rc = -EINVAL;
1216 return rc;
1217 }
1218 cci_dev->cci_wait_sync_cfg = c_ctrl->cfg.cci_wait_sync_cfg;
1219 cci_dev->valid_sync = cci_dev->cci_wait_sync_cfg.csid < 0 ? 0 : 1;
1220
1221 return rc;
1222}
1223
1224static int32_t cam_cci_release(struct v4l2_subdev *sd)
1225{
1226 uint8_t rc = 0;
1227 struct cci_device *cci_dev;
1228
1229 cci_dev = v4l2_get_subdevdata(sd);
1230
1231 rc = cam_cci_soc_release(cci_dev);
1232 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001233 CAM_ERR(CAM_CCI, "Failed in releasing the cci: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001234 return rc;
1235 }
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001236
1237 return rc;
1238}
1239
1240static int32_t cam_cci_write(struct v4l2_subdev *sd,
1241 struct cam_cci_ctrl *c_ctrl)
1242{
1243 int32_t rc = 0;
1244 struct cci_device *cci_dev;
1245 enum cci_i2c_master_t master;
1246 struct cam_cci_master_info *cci_master_info;
1247 uint32_t i;
1248
1249 cci_dev = v4l2_get_subdevdata(sd);
1250 if (!cci_dev || !c_ctrl) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001251 CAM_ERR(CAM_CCI, "failed: invalid params %pK %pK",
1252 cci_dev, c_ctrl);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001253 rc = -EINVAL;
1254 return rc;
1255 }
1256
1257 master = c_ctrl->cci_info->cci_i2c_master;
1258
1259 if (c_ctrl->cci_info->cci_i2c_master >= MASTER_MAX
1260 || c_ctrl->cci_info->cci_i2c_master < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001261 CAM_ERR(CAM_CCI, "Invalid I2C master addr");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001262 return -EINVAL;
1263 }
1264
1265 cci_master_info = &cci_dev->cci_master_info[master];
1266
1267 switch (c_ctrl->cmd) {
1268 case MSM_CCI_I2C_WRITE_SYNC_BLOCK:
1269 mutex_lock(&cci_master_info->mutex_q[SYNC_QUEUE]);
1270 rc = cam_cci_i2c_write(sd, c_ctrl,
1271 SYNC_QUEUE, MSM_SYNC_ENABLE);
1272 mutex_unlock(&cci_master_info->mutex_q[SYNC_QUEUE]);
1273 break;
1274 case MSM_CCI_I2C_WRITE_SYNC:
1275 rc = cam_cci_i2c_write_async(sd, c_ctrl,
1276 SYNC_QUEUE, MSM_SYNC_ENABLE);
1277 break;
1278 case MSM_CCI_I2C_WRITE:
1279 case MSM_CCI_I2C_WRITE_SEQ:
Karthik Anantha Ram0fb02a32017-08-23 11:52:50 -07001280 case MSM_CCI_I2C_WRITE_BURST:
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001281 for (i = 0; i < NUM_QUEUES; i++) {
1282 if (mutex_trylock(&cci_master_info->mutex_q[i])) {
1283 rc = cam_cci_i2c_write(sd, c_ctrl, i,
1284 MSM_SYNC_DISABLE);
1285 mutex_unlock(&cci_master_info->mutex_q[i]);
1286 return rc;
1287 }
1288 }
1289 mutex_lock(&cci_master_info->mutex_q[PRIORITY_QUEUE]);
1290 rc = cam_cci_i2c_write(sd, c_ctrl,
1291 PRIORITY_QUEUE, MSM_SYNC_DISABLE);
1292 mutex_unlock(&cci_master_info->mutex_q[PRIORITY_QUEUE]);
1293 break;
1294 case MSM_CCI_I2C_WRITE_ASYNC:
1295 rc = cam_cci_i2c_write_async(sd, c_ctrl,
1296 PRIORITY_QUEUE, MSM_SYNC_DISABLE);
1297 break;
1298 default:
1299 rc = -ENOIOCTLCMD;
1300 }
1301
1302 return rc;
1303}
1304
1305int32_t cam_cci_core_cfg(struct v4l2_subdev *sd,
1306 struct cam_cci_ctrl *cci_ctrl)
1307{
1308 int32_t rc = 0;
1309
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001310 CAM_DBG(CAM_CCI, "cmd %d", cci_ctrl->cmd);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001311 switch (cci_ctrl->cmd) {
1312 case MSM_CCI_INIT:
1313 rc = cam_cci_init(sd, cci_ctrl);
1314 break;
1315 case MSM_CCI_RELEASE:
1316 rc = cam_cci_release(sd);
1317 break;
1318 case MSM_CCI_I2C_READ:
1319 rc = cam_cci_read_bytes(sd, cci_ctrl);
1320 break;
1321 case MSM_CCI_I2C_WRITE:
1322 case MSM_CCI_I2C_WRITE_SEQ:
Karthik Anantha Ram0fb02a32017-08-23 11:52:50 -07001323 case MSM_CCI_I2C_WRITE_BURST:
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001324 case MSM_CCI_I2C_WRITE_SYNC:
1325 case MSM_CCI_I2C_WRITE_ASYNC:
1326 case MSM_CCI_I2C_WRITE_SYNC_BLOCK:
1327 rc = cam_cci_write(sd, cci_ctrl);
1328 break;
1329 case MSM_CCI_GPIO_WRITE:
1330 break;
1331 case MSM_CCI_SET_SYNC_CID:
1332 rc = cam_cci_i2c_set_sync_prms(sd, cci_ctrl);
1333 break;
1334
1335 default:
1336 rc = -ENOIOCTLCMD;
1337 }
1338
1339 cci_ctrl->status = rc;
1340
1341 return rc;
1342}