blob: 9a711ec40e86de05fffb85c6890a35560f9af86a [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 Zala3865c1c2017-11-28 12:08:50 -0800122 CAM_ERR(CAM_CCI, "Wait_for_completion_timeout: rc: %d",
123 rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800124 if (rc == 0)
125 rc = -ETIMEDOUT;
126 cam_cci_flush_queue(cci_dev, master);
127 return rc;
128 }
129 rc = cci_dev->cci_master_info[master].status;
130 if (rc < 0)
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700131 CAM_ERR(CAM_CCI, "Failed rc %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800132 }
133
134 return rc;
135}
136
137static int32_t cam_cci_write_i2c_queue(struct cci_device *cci_dev,
138 uint32_t val,
139 enum cci_i2c_master_t master,
140 enum cci_i2c_queue_t queue)
141{
142 int32_t rc = 0;
143 uint32_t reg_offset = master * 0x200 + queue * 0x100;
Alok Pandey01b1b352017-06-25 20:38:54 +0530144 struct cam_hw_soc_info *soc_info =
145 &cci_dev->soc_info;
146 void __iomem *base = soc_info->reg_map[0].mem_base;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800147
148 if (!cci_dev) {
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700149 CAM_ERR(CAM_CCI, "Failed");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800150 return -EINVAL;
151 }
152
153 rc = cam_cci_validate_queue(cci_dev, 1, master, queue);
154 if (rc < 0) {
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700155 CAM_ERR(CAM_CCI, "Failed %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800156 return rc;
157 }
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700158 CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_LOAD_DATA_ADDR:val 0x%x:0x%x",
159 CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800160 reg_offset, val);
Alok Pandey01b1b352017-06-25 20:38:54 +0530161 cam_io_w_mb(val, base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800162 reg_offset);
163 return rc;
164}
165
166static int32_t cam_cci_lock_queue(struct cci_device *cci_dev,
167 enum cci_i2c_master_t master,
168 enum cci_i2c_queue_t queue, uint32_t en)
169{
170 uint32_t val;
171
172 if (queue != PRIORITY_QUEUE)
173 return 0;
174
175 val = en ? CCI_I2C_LOCK_CMD : CCI_I2C_UNLOCK_CMD;
176 return cam_cci_write_i2c_queue(cci_dev, val, master, queue);
177}
178
179#ifdef DUMP_CCI_REGISTERS
180static void cam_cci_dump_registers(struct cci_device *cci_dev,
181 enum cci_i2c_master_t master, enum cci_i2c_queue_t queue)
182{
183 uint32_t read_val = 0;
184 uint32_t i = 0;
185 uint32_t reg_offset = 0;
186
187 /* CCI Top Registers */
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700188 CAM_DBG(CAM_CCI, "****CCI TOP Registers ****");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800189 for (i = 0; i < DEBUG_TOP_REG_COUNT; i++) {
190 reg_offset = DEBUG_TOP_REG_START + i * 4;
191 read_val = cam_io_r_mb(cci_dev->base + reg_offset);
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700192 CAM_DBG(CAM_CCI, "offset = 0x%X value = 0x%X",
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700193 reg_offset, read_val);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800194 }
195
196 /* CCI Master registers */
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700197 CAM_DBG(CAM_CCI, "****CCI MASTER %d Registers ****",
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700198 master);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800199 for (i = 0; i < DEBUG_MASTER_REG_COUNT; i++) {
200 if (i == 6)
201 continue;
202 reg_offset = DEBUG_MASTER_REG_START + master*0x100 + i * 4;
203 read_val = cam_io_r_mb(cci_dev->base + reg_offset);
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700204 CAM_DBG(CAM_CCI, "offset = 0x%X value = 0x%X",
205 reg_offset, read_val);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800206 }
207
208 /* CCI Master Queue registers */
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700209 CAM_DBG(CAM_CCI, " **** CCI MASTER%d QUEUE%d Registers ****",
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700210 master, queue);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800211 for (i = 0; i < DEBUG_MASTER_QUEUE_REG_COUNT; i++) {
212 reg_offset = DEBUG_MASTER_QUEUE_REG_START + master*0x200 +
213 queue*0x100 + i * 4;
214 read_val = cam_io_r_mb(cci_dev->base + reg_offset);
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700215 CAM_DBG(CAM_CCI, "offset = 0x%X value = 0x%X",
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700216 reg_offset, read_val);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800217 }
218
219 /* CCI Interrupt registers */
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700220 CAM_DBG(CAM_CCI, " ****CCI Interrupt Registers ****");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800221 for (i = 0; i < DEBUG_INTR_REG_COUNT; i++) {
222 reg_offset = DEBUG_INTR_REG_START + i * 4;
223 read_val = cam_io_r_mb(cci_dev->base + reg_offset);
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700224 CAM_DBG(CAM_CCI, "offset = 0x%X value = 0x%X",
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700225 reg_offset, read_val);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800226 }
227}
228#endif
229
230static uint32_t cam_cci_wait(struct cci_device *cci_dev,
231 enum cci_i2c_master_t master,
232 enum cci_i2c_queue_t queue)
233{
234 int32_t rc = 0;
235
236 if (!cci_dev) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700237 CAM_ERR(CAM_CCI, "failed");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800238 return -EINVAL;
239 }
240
241 rc = wait_for_completion_timeout(&cci_dev->
242 cci_master_info[master].report_q[queue], CCI_TIMEOUT);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700243 CAM_DBG(CAM_CCI, "wait DONE_for_completion_timeout");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800244
245 if (rc <= 0) {
246#ifdef DUMP_CCI_REGISTERS
247 cam_cci_dump_registers(cci_dev, master, queue);
248#endif
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700249 CAM_ERR(CAM_CCI, "wait for queue: %d", queue);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800250 if (rc == 0)
251 rc = -ETIMEDOUT;
252 cam_cci_flush_queue(cci_dev, master);
253 return rc;
254 }
255 rc = cci_dev->cci_master_info[master].status;
256 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700257 CAM_ERR(CAM_CCI, "failed rc %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800258 return rc;
259 }
260
261 return 0;
262}
263
264static void cam_cci_load_report_cmd(struct cci_device *cci_dev,
265 enum cci_i2c_master_t master,
266 enum cci_i2c_queue_t queue)
267{
Alok Pandey01b1b352017-06-25 20:38:54 +0530268 struct cam_hw_soc_info *soc_info =
269 &cci_dev->soc_info;
270 void __iomem *base = soc_info->reg_map[0].mem_base;
271
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800272 uint32_t reg_offset = master * 0x200 + queue * 0x100;
Alok Pandey01b1b352017-06-25 20:38:54 +0530273 uint32_t read_val = cam_io_r_mb(base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800274 CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + reg_offset);
275 uint32_t report_val = CCI_I2C_REPORT_CMD | (1 << 8);
276
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700277 CAM_DBG(CAM_CCI, "CCI_I2C_REPORT_CMD curr_w_cnt: %d", read_val);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800278 cam_io_w_mb(report_val,
Alok Pandey01b1b352017-06-25 20:38:54 +0530279 base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800280 reg_offset);
281 read_val++;
282
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700283 CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR %d", read_val);
Alok Pandey01b1b352017-06-25 20:38:54 +0530284 cam_io_w_mb(read_val, base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800285 CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + reg_offset);
286}
287
288static int32_t cam_cci_wait_report_cmd(struct cci_device *cci_dev,
289 enum cci_i2c_master_t master,
290 enum cci_i2c_queue_t queue)
291{
Alok Pandey01b1b352017-06-25 20:38:54 +0530292 struct cam_hw_soc_info *soc_info =
293 &cci_dev->soc_info;
294 void __iomem *base = soc_info->reg_map[0].mem_base;
295
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800296 uint32_t reg_val = 1 << ((master * 2) + queue);
297
298 cam_cci_load_report_cmd(cci_dev, master, queue);
299 atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 1);
300 atomic_set(&cci_dev->cci_master_info[master].done_pending[queue], 1);
Alok Pandey01b1b352017-06-25 20:38:54 +0530301 cam_io_w_mb(reg_val, base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800302 CCI_QUEUE_START_ADDR);
303
304 return cam_cci_wait(cci_dev, master, queue);
305}
306
307static int32_t cam_cci_transfer_end(struct cci_device *cci_dev,
308 enum cci_i2c_master_t master,
309 enum cci_i2c_queue_t queue)
310{
311 int32_t rc = 0;
312
313 if (atomic_read(&cci_dev->cci_master_info[master].q_free[queue]) == 0) {
314 rc = cam_cci_lock_queue(cci_dev, master, queue, 0);
315 if (rc < 0) {
Jigarkumar Zala3865c1c2017-11-28 12:08:50 -0800316 CAM_ERR(CAM_CCI, "failed rc: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800317 return rc;
318 }
319 rc = cam_cci_wait_report_cmd(cci_dev, master, queue);
320 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700321 CAM_ERR(CAM_CCI, "failed rc %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800322 return rc;
323 }
324 } else {
325 atomic_set(&cci_dev->cci_master_info[master].
326 done_pending[queue], 1);
327 rc = cam_cci_wait(cci_dev, master, queue);
328 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700329 CAM_ERR(CAM_CCI, "failed rc %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800330 return rc;
331 }
332 rc = cam_cci_lock_queue(cci_dev, master, queue, 0);
333 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700334 CAM_ERR(CAM_CCI, "failed rc %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800335 return rc;
336 }
337 rc = cam_cci_wait_report_cmd(cci_dev, master, queue);
338 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700339 CAM_ERR(CAM_CCI, "Failed rc %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800340 return rc;
341 }
342 }
343
344 return rc;
345}
346
347static int32_t cam_cci_get_queue_free_size(struct cci_device *cci_dev,
348 enum cci_i2c_master_t master,
349 enum cci_i2c_queue_t queue)
350{
351 uint32_t read_val = 0;
352 uint32_t reg_offset = master * 0x200 + queue * 0x100;
Alok Pandey01b1b352017-06-25 20:38:54 +0530353 struct cam_hw_soc_info *soc_info =
354 &cci_dev->soc_info;
355 void __iomem *base = soc_info->reg_map[0].mem_base;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800356
Alok Pandey01b1b352017-06-25 20:38:54 +0530357 read_val = cam_io_r_mb(base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800358 CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + reg_offset);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700359 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 -0800360 cci_dev->cci_i2c_queue_info[master][queue].max_queue_size);
361 return (cci_dev->
362 cci_i2c_queue_info[master][queue].max_queue_size) -
363 read_val;
364}
365
366static void cam_cci_process_half_q(struct cci_device *cci_dev,
367 enum cci_i2c_master_t master,
368 enum cci_i2c_queue_t queue)
369{
Alok Pandey01b1b352017-06-25 20:38:54 +0530370 struct cam_hw_soc_info *soc_info =
371 &cci_dev->soc_info;
372 void __iomem *base = soc_info->reg_map[0].mem_base;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800373 uint32_t reg_val = 1 << ((master * 2) + queue);
374
375 if (atomic_read(&cci_dev->cci_master_info[master].q_free[queue]) == 0) {
376 cam_cci_load_report_cmd(cci_dev, master, queue);
377 atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 1);
Alok Pandey01b1b352017-06-25 20:38:54 +0530378 cam_io_w_mb(reg_val, base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800379 CCI_QUEUE_START_ADDR);
380 }
381}
382
383static int32_t cam_cci_process_full_q(struct cci_device *cci_dev,
384 enum cci_i2c_master_t master,
385 enum cci_i2c_queue_t queue)
386{
387 int32_t rc = 0;
388
389 if (atomic_read(&cci_dev->cci_master_info[master].q_free[queue]) == 1) {
390 atomic_set(&cci_dev->cci_master_info[master].
391 done_pending[queue], 1);
392 rc = cam_cci_wait(cci_dev, master, queue);
393 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700394 CAM_ERR(CAM_CCI, "failed rc %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800395 return rc;
396 }
397 } else {
398 rc = cam_cci_wait_report_cmd(cci_dev, master, queue);
399 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700400 CAM_ERR(CAM_CCI, "failed rc %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800401 return rc;
402 }
403 }
404
405 return rc;
406}
407
408static int32_t cam_cci_calc_cmd_len(struct cci_device *cci_dev,
409 struct cam_cci_ctrl *c_ctrl, uint32_t cmd_size,
410 struct cam_sensor_i2c_reg_array *i2c_cmd, uint32_t *pack)
411{
412 uint8_t i;
413 uint32_t len = 0;
414 uint8_t data_len = 0, addr_len = 0;
415 uint8_t pack_max_len;
416 struct cam_sensor_i2c_reg_setting *msg;
417 struct cam_sensor_i2c_reg_array *cmd = i2c_cmd;
418 uint32_t size = cmd_size;
419
420 if (!cci_dev || !c_ctrl) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700421 CAM_ERR(CAM_CCI, "failed");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800422 return -EINVAL;
423 }
424
425 msg = &c_ctrl->cfg.cci_i2c_write_cfg;
426 *pack = 0;
427
Karthik Anantha Ram0fb02a32017-08-23 11:52:50 -0700428 if (c_ctrl->cmd == MSM_CCI_I2C_WRITE_SEQ ||
429 c_ctrl->cmd == MSM_CCI_I2C_WRITE_BURST) {
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800430 addr_len = cam_cci_convert_type_to_num_bytes(msg->addr_type);
431 len = (size + addr_len) <= (cci_dev->payload_size) ?
432 (size + addr_len):cci_dev->payload_size;
433 } else {
434 addr_len = cam_cci_convert_type_to_num_bytes(msg->addr_type);
435 data_len = cam_cci_convert_type_to_num_bytes(msg->data_type);
436 len = data_len + addr_len;
437 pack_max_len = size < (cci_dev->payload_size-len) ?
438 size : (cci_dev->payload_size-len);
439 for (i = 0; i < pack_max_len;) {
440 if (cmd->delay || ((cmd - i2c_cmd) >= (cmd_size - 1)))
441 break;
442 if (cmd->reg_addr + 1 ==
443 (cmd+1)->reg_addr) {
444 len += data_len;
Wei Ding86e889b2017-10-25 17:24:20 +0800445 (*pack)++;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800446 } else {
447 break;
448 }
449 i += data_len;
450 cmd++;
451 }
452 }
453
454 if (len > cci_dev->payload_size) {
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700455 CAM_ERR(CAM_CCI, "Len error: %d", len);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800456 return -EINVAL;
457 }
458
459 len += 1; /*add i2c WR command*/
460 len = len/4 + 1;
461
462 return len;
463}
464
465static uint32_t cam_cci_cycles_per_ms(unsigned long clk)
466{
467 uint32_t cycles_per_us;
468
469 if (clk) {
470 cycles_per_us = ((clk/1000)*256)/1000;
471 } else {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700472 CAM_ERR(CAM_CCI, "failed: Can use default: %d",
473 CYCLES_PER_MICRO_SEC_DEFAULT);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800474 cycles_per_us = CYCLES_PER_MICRO_SEC_DEFAULT;
475 }
476
477 return cycles_per_us;
478}
479
Alok Pandey01b1b352017-06-25 20:38:54 +0530480void cam_cci_get_clk_rates(struct cci_device *cci_dev,
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800481 struct cam_cci_ctrl *c_ctrl)
Alok Pandey01b1b352017-06-25 20:38:54 +0530482
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800483{
Alok Pandey01b1b352017-06-25 20:38:54 +0530484 int32_t src_clk_idx, j;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800485 uint32_t cci_clk_src;
486 unsigned long clk;
487 struct cam_cci_clk_params_t *clk_params = NULL;
Alok Pandey01b1b352017-06-25 20:38:54 +0530488
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800489 enum i2c_freq_mode i2c_freq_mode = c_ctrl->cci_info->i2c_freq_mode;
Alok Pandey01b1b352017-06-25 20:38:54 +0530490 struct cam_hw_soc_info *soc_info = &cci_dev->soc_info;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800491
492 if (i2c_freq_mode >= I2C_MAX_MODES ||
493 i2c_freq_mode < I2C_STANDARD_MODE) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700494 CAM_ERR(CAM_CCI, "Invalid frequency mode: %d",
495 (int32_t)i2c_freq_mode);
Alok Pandey01b1b352017-06-25 20:38:54 +0530496 cci_dev->clk_level_index = -1;
497 return;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800498 }
499
500 clk_params = &cci_dev->cci_clk_params[i2c_freq_mode];
501 cci_clk_src = clk_params->cci_clk_src;
502
Alok Pandey01b1b352017-06-25 20:38:54 +0530503 src_clk_idx = soc_info->src_clk_idx;
504
505 if (src_clk_idx < 0) {
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800506 cci_dev->cycles_per_us = CYCLES_PER_MICRO_SEC_DEFAULT;
Alok Pandey01b1b352017-06-25 20:38:54 +0530507 cci_dev->clk_level_index = 0;
508 return;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800509 }
510
511 if (cci_clk_src == 0) {
Alok Pandey01b1b352017-06-25 20:38:54 +0530512 clk = soc_info->clk_rate[0][src_clk_idx];
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800513 cci_dev->cycles_per_us = cam_cci_cycles_per_ms(clk);
Alok Pandey01b1b352017-06-25 20:38:54 +0530514 cci_dev->clk_level_index = 0;
515 return;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800516 }
517
Alok Pandey01b1b352017-06-25 20:38:54 +0530518 for (j = 0; j < CAM_MAX_VOTE; j++) {
519 clk = soc_info->clk_rate[j][src_clk_idx];
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800520 if (clk == cci_clk_src) {
521 cci_dev->cycles_per_us = cam_cci_cycles_per_ms(clk);
Alok Pandey01b1b352017-06-25 20:38:54 +0530522 cci_dev->clk_level_index = j;
523 return;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800524 }
525 }
Alok Pandey01b1b352017-06-25 20:38:54 +0530526 return;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800527}
528
529static int32_t cam_cci_set_clk_param(struct cci_device *cci_dev,
530 struct cam_cci_ctrl *c_ctrl)
531{
532 struct cam_cci_clk_params_t *clk_params = NULL;
533 enum cci_i2c_master_t master = c_ctrl->cci_info->cci_i2c_master;
534 enum i2c_freq_mode i2c_freq_mode = c_ctrl->cci_info->i2c_freq_mode;
Alok Pandey01b1b352017-06-25 20:38:54 +0530535 struct cam_hw_soc_info *soc_info =
536 &cci_dev->soc_info;
537 void __iomem *base = soc_info->reg_map[0].mem_base;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800538
539 if ((i2c_freq_mode >= I2C_MAX_MODES) || (i2c_freq_mode < 0)) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700540 CAM_ERR(CAM_CCI, "invalid i2c_freq_mode = %d", i2c_freq_mode);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800541 return -EINVAL;
542 }
543
544 clk_params = &cci_dev->cci_clk_params[i2c_freq_mode];
545
546 if (cci_dev->i2c_freq_mode[master] == i2c_freq_mode)
547 return 0;
548 if (master == MASTER_0) {
549 cam_io_w_mb(clk_params->hw_thigh << 16 |
550 clk_params->hw_tlow,
Alok Pandey01b1b352017-06-25 20:38:54 +0530551 base + CCI_I2C_M0_SCL_CTL_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800552 cam_io_w_mb(clk_params->hw_tsu_sto << 16 |
553 clk_params->hw_tsu_sta,
Alok Pandey01b1b352017-06-25 20:38:54 +0530554 base + CCI_I2C_M0_SDA_CTL_0_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800555 cam_io_w_mb(clk_params->hw_thd_dat << 16 |
556 clk_params->hw_thd_sta,
Alok Pandey01b1b352017-06-25 20:38:54 +0530557 base + CCI_I2C_M0_SDA_CTL_1_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800558 cam_io_w_mb(clk_params->hw_tbuf,
Alok Pandey01b1b352017-06-25 20:38:54 +0530559 base + CCI_I2C_M0_SDA_CTL_2_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800560 cam_io_w_mb(clk_params->hw_scl_stretch_en << 8 |
561 clk_params->hw_trdhld << 4 | clk_params->hw_tsp,
Alok Pandey01b1b352017-06-25 20:38:54 +0530562 base + CCI_I2C_M0_MISC_CTL_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800563 } else if (master == MASTER_1) {
564 cam_io_w_mb(clk_params->hw_thigh << 16 |
565 clk_params->hw_tlow,
Alok Pandey01b1b352017-06-25 20:38:54 +0530566 base + CCI_I2C_M1_SCL_CTL_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800567 cam_io_w_mb(clk_params->hw_tsu_sto << 16 |
568 clk_params->hw_tsu_sta,
Alok Pandey01b1b352017-06-25 20:38:54 +0530569 base + CCI_I2C_M1_SDA_CTL_0_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800570 cam_io_w_mb(clk_params->hw_thd_dat << 16 |
571 clk_params->hw_thd_sta,
Alok Pandey01b1b352017-06-25 20:38:54 +0530572 base + CCI_I2C_M1_SDA_CTL_1_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800573 cam_io_w_mb(clk_params->hw_tbuf,
Alok Pandey01b1b352017-06-25 20:38:54 +0530574 base + CCI_I2C_M1_SDA_CTL_2_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800575 cam_io_w_mb(clk_params->hw_scl_stretch_en << 8 |
576 clk_params->hw_trdhld << 4 | clk_params->hw_tsp,
Alok Pandey01b1b352017-06-25 20:38:54 +0530577 base + CCI_I2C_M1_MISC_CTL_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800578 }
579 cci_dev->i2c_freq_mode[master] = i2c_freq_mode;
580
581 return 0;
582}
583
584static int32_t cam_cci_data_queue(struct cci_device *cci_dev,
585 struct cam_cci_ctrl *c_ctrl, enum cci_i2c_queue_t queue,
586 enum cci_i2c_sync sync_en)
587{
588 uint16_t i = 0, j = 0, k = 0, h = 0, len = 0;
589 int32_t rc = 0, free_size = 0, en_seq_write = 0;
590 uint8_t data[12];
591 struct cam_sensor_i2c_reg_setting *i2c_msg =
592 &c_ctrl->cfg.cci_i2c_write_cfg;
593 struct cam_sensor_i2c_reg_array *i2c_cmd = i2c_msg->reg_setting;
594 enum cci_i2c_master_t master = c_ctrl->cci_info->cci_i2c_master;
595 uint16_t reg_addr = 0, cmd_size = i2c_msg->size;
596 uint32_t read_val = 0, reg_offset, val, delay = 0;
597 uint32_t max_queue_size, queue_size = 0, cmd = 0;
Alok Pandey01b1b352017-06-25 20:38:54 +0530598 struct cam_hw_soc_info *soc_info =
599 &cci_dev->soc_info;
600 void __iomem *base = soc_info->reg_map[0].mem_base;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800601
602 if (i2c_cmd == NULL) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700603 CAM_ERR(CAM_CCI, "Failed: i2c cmd is NULL");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800604 return -EINVAL;
605 }
606
607 if ((!cmd_size) || (cmd_size > CCI_I2C_MAX_WRITE)) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700608 CAM_ERR(CAM_CCI, "failed: invalid cmd_size %d",
609 cmd_size);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800610 return -EINVAL;
611 }
612
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700613 CAM_DBG(CAM_CCI, "addr type %d data type %d cmd_size %d",
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800614 i2c_msg->addr_type, i2c_msg->data_type, cmd_size);
615
616 if (i2c_msg->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700617 CAM_ERR(CAM_CCI, "failed: invalid addr_type 0x%X",
618 i2c_msg->addr_type);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800619 return -EINVAL;
620 }
621 if (i2c_msg->data_type >= CAMERA_SENSOR_I2C_TYPE_MAX) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700622 CAM_ERR(CAM_CCI, "failed: invalid data_type 0x%X",
623 i2c_msg->data_type);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800624 return -EINVAL;
625 }
626 reg_offset = master * 0x200 + queue * 0x100;
627
628 cam_io_w_mb(cci_dev->cci_wait_sync_cfg.cid,
Alok Pandey01b1b352017-06-25 20:38:54 +0530629 base + CCI_SET_CID_SYNC_TIMER_ADDR +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800630 cci_dev->cci_wait_sync_cfg.csid *
631 CCI_SET_CID_SYNC_TIMER_OFFSET);
632
633 val = CCI_I2C_SET_PARAM_CMD | c_ctrl->cci_info->sid << 4 |
634 c_ctrl->cci_info->retries << 16 |
635 c_ctrl->cci_info->id_map << 18;
636
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700637 CAM_DBG(CAM_CCI, "CCI_I2C_M0_Q0_LOAD_DATA_ADDR:val 0x%x:0x%x",
638 CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800639 reg_offset, val);
Alok Pandey01b1b352017-06-25 20:38:54 +0530640 cam_io_w_mb(val, base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800641 reg_offset);
642
643 atomic_set(&cci_dev->cci_master_info[master].q_free[queue], 0);
644
645 max_queue_size = cci_dev->cci_i2c_queue_info[master][queue].
646 max_queue_size;
647
648 if (c_ctrl->cmd == MSM_CCI_I2C_WRITE_SEQ)
649 queue_size = max_queue_size;
650 else
651 queue_size = max_queue_size/2;
652 reg_addr = i2c_cmd->reg_addr;
653
654 if (sync_en == MSM_SYNC_ENABLE && cci_dev->valid_sync &&
655 cmd_size < max_queue_size) {
656 val = CCI_I2C_WAIT_SYNC_CMD |
657 ((cci_dev->cci_wait_sync_cfg.line) << 4);
658 cam_io_w_mb(val,
Alok Pandey01b1b352017-06-25 20:38:54 +0530659 base + CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800660 reg_offset);
661 }
662
663 rc = cam_cci_lock_queue(cci_dev, master, queue, 1);
664 if (rc < 0) {
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700665 CAM_ERR(CAM_CCI, "failed line %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800666 return rc;
667 }
668
669 while (cmd_size) {
670 uint32_t pack = 0;
671
672 len = cam_cci_calc_cmd_len(cci_dev, c_ctrl, cmd_size,
673 i2c_cmd, &pack);
674 if (len <= 0) {
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700675 CAM_ERR(CAM_CCI, "failed");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800676 return -EINVAL;
677 }
678
Alok Pandey01b1b352017-06-25 20:38:54 +0530679 read_val = cam_io_r_mb(base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800680 CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + reg_offset);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700681 CAM_DBG(CAM_CCI, "CUR_WORD_CNT_ADDR %d len %d max %d",
682 read_val, len, max_queue_size);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800683 /* + 1 - space alocation for Report CMD */
684 if ((read_val + len + 1) > queue_size) {
685 if ((read_val + len + 1) > max_queue_size) {
686 rc = cam_cci_process_full_q(cci_dev,
687 master, queue);
688 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700689 CAM_ERR(CAM_CCI, "failed rc: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800690 return rc;
691 }
692 continue;
693 }
694 cam_cci_process_half_q(cci_dev, master, queue);
695 }
696
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700697 CAM_DBG(CAM_CCI, "cmd_size %d addr 0x%x data 0x%x",
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800698 cmd_size, i2c_cmd->reg_addr, i2c_cmd->reg_data);
699 delay = i2c_cmd->delay;
700 i = 0;
701 data[i++] = CCI_I2C_WRITE_CMD;
702
703 /*
704 * in case of multiple command
705 * MSM_CCI_I2C_WRITE : address is not continuous, so update
706 * address for a new packet.
707 * MSM_CCI_I2C_WRITE_SEQ : address is continuous, need to keep
708 * the incremented address for a
709 * new packet
710 */
711 if (c_ctrl->cmd == MSM_CCI_I2C_WRITE ||
712 c_ctrl->cmd == MSM_CCI_I2C_WRITE_ASYNC ||
713 c_ctrl->cmd == MSM_CCI_I2C_WRITE_SYNC ||
714 c_ctrl->cmd == MSM_CCI_I2C_WRITE_SYNC_BLOCK)
715 reg_addr = i2c_cmd->reg_addr;
716
717 if (en_seq_write == 0) {
718 /* either byte or word addr */
719 if (i2c_msg->addr_type == CAMERA_SENSOR_I2C_TYPE_BYTE)
720 data[i++] = reg_addr;
721 else {
722 data[i++] = (reg_addr & 0xFF00) >> 8;
723 data[i++] = reg_addr & 0x00FF;
724 }
725 }
726 /* max of 10 data bytes */
727 do {
728 if (i2c_msg->data_type == CAMERA_SENSOR_I2C_TYPE_BYTE) {
729 data[i++] = i2c_cmd->reg_data;
Karthik Anantha Ram0fb02a32017-08-23 11:52:50 -0700730 if (c_ctrl->cmd == MSM_CCI_I2C_WRITE_SEQ)
731 reg_addr++;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800732 } else {
733 if ((i + 1) <= cci_dev->payload_size) {
Depeng Shaoc06b3972017-11-10 08:37:07 +0800734 switch (i2c_msg->data_type) {
735 case CAMERA_SENSOR_I2C_TYPE_DWORD:
Wei Ding86e889b2017-10-25 17:24:20 +0800736 data[i++] = (i2c_cmd->reg_data &
737 0xFF000000) >> 24;
Depeng Shaoc06b3972017-11-10 08:37:07 +0800738 /* fallthrough */
739 case CAMERA_SENSOR_I2C_TYPE_3B:
Wei Ding86e889b2017-10-25 17:24:20 +0800740 data[i++] = (i2c_cmd->reg_data &
741 0x00FF0000) >> 16;
Depeng Shaoc06b3972017-11-10 08:37:07 +0800742 /* fallthrough */
743 case CAMERA_SENSOR_I2C_TYPE_WORD:
744 data[i++] = (i2c_cmd->reg_data &
745 0x0000FF00) >> 8;
746 /* fallthrough */
747 case CAMERA_SENSOR_I2C_TYPE_BYTE:
748 data[i++] = i2c_cmd->reg_data &
749 0x000000FF;
750 break;
751 default:
752 CAM_ERR(CAM_CCI,
753 "invalid data type: %d",
754 i2c_msg->data_type);
755 return -EINVAL;
Wei Ding86e889b2017-10-25 17:24:20 +0800756 }
Depeng Shaoc06b3972017-11-10 08:37:07 +0800757
Karthik Anantha Ram0fb02a32017-08-23 11:52:50 -0700758 if (c_ctrl->cmd ==
759 MSM_CCI_I2C_WRITE_SEQ)
760 reg_addr++;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800761 } else
762 break;
763 }
764 i2c_cmd++;
765 --cmd_size;
Karthik Anantha Ram0fb02a32017-08-23 11:52:50 -0700766 } while (((c_ctrl->cmd == MSM_CCI_I2C_WRITE_SEQ ||
767 c_ctrl->cmd == MSM_CCI_I2C_WRITE_BURST) || pack--) &&
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800768 (cmd_size > 0) && (i <= cci_dev->payload_size));
769 free_size = cam_cci_get_queue_free_size(cci_dev, master,
770 queue);
Karthik Anantha Ram0fb02a32017-08-23 11:52:50 -0700771 if ((c_ctrl->cmd == MSM_CCI_I2C_WRITE_SEQ ||
772 c_ctrl->cmd == MSM_CCI_I2C_WRITE_BURST) &&
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800773 ((i-1) == MSM_CCI_WRITE_DATA_PAYLOAD_SIZE_11) &&
774 cci_dev->support_seq_write && cmd_size > 0 &&
775 free_size > BURST_MIN_FREE_SIZE) {
776 data[0] |= 0xF0;
777 en_seq_write = 1;
778 } else {
779 data[0] |= ((i-1) << 4);
780 en_seq_write = 0;
781 }
782 len = ((i-1)/4) + 1;
783
Alok Pandey01b1b352017-06-25 20:38:54 +0530784 read_val = cam_io_r_mb(base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800785 CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + reg_offset);
786 for (h = 0, k = 0; h < len; h++) {
787 cmd = 0;
788 for (j = 0; (j < 4 && k < i); j++)
789 cmd |= (data[k++] << (j * 8));
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700790 CAM_DBG(CAM_CCI,
791 "LOAD_DATA_ADDR 0x%x, q: %d, len:%d, cnt: %d",
792 cmd, queue, len, read_val);
Alok Pandey01b1b352017-06-25 20:38:54 +0530793 cam_io_w_mb(cmd, base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800794 CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
795 master * 0x200 + queue * 0x100);
796
797 read_val += 1;
Alok Pandey01b1b352017-06-25 20:38:54 +0530798 cam_io_w_mb(read_val, base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800799 CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + reg_offset);
800 }
801
802 if ((delay > 0) && (delay < CCI_MAX_DELAY) &&
803 en_seq_write == 0) {
804 cmd = (uint32_t)((delay * cci_dev->cycles_per_us) /
805 0x100);
806 cmd <<= 4;
807 cmd |= CCI_I2C_WAIT_CMD;
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700808 CAM_DBG(CAM_CCI,
809 "CCI_I2C_M0_Q0_LOAD_DATA_ADDR 0x%x", cmd);
Alok Pandey01b1b352017-06-25 20:38:54 +0530810 cam_io_w_mb(cmd, base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800811 CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
812 master * 0x200 + queue * 0x100);
813 read_val += 1;
Alok Pandey01b1b352017-06-25 20:38:54 +0530814 cam_io_w_mb(read_val, base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800815 CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + reg_offset);
816 }
817 }
818
819 rc = cam_cci_transfer_end(cci_dev, master, queue);
820 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700821 CAM_ERR(CAM_CCI, "failed rc %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800822 return rc;
823 }
824
825 return rc;
826}
827
828static int32_t cam_cci_read(struct v4l2_subdev *sd,
829 struct cam_cci_ctrl *c_ctrl)
830{
831 int32_t rc = 0;
832 uint32_t val = 0;
833 int32_t read_words = 0, exp_words = 0;
834 int32_t index = 0, first_byte = 0;
835 uint32_t i = 0;
836 enum cci_i2c_master_t master;
837 enum cci_i2c_queue_t queue = QUEUE_1;
838 struct cci_device *cci_dev = NULL;
839 struct cam_cci_read_cfg *read_cfg = NULL;
Alok Pandey01b1b352017-06-25 20:38:54 +0530840 struct cam_hw_soc_info *soc_info = NULL;
841 void __iomem *base = NULL;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800842
843 cci_dev = v4l2_get_subdevdata(sd);
844 master = c_ctrl->cci_info->cci_i2c_master;
845 read_cfg = &c_ctrl->cfg.cci_i2c_read_cfg;
846
847 if (c_ctrl->cci_info->cci_i2c_master >= MASTER_MAX
848 || c_ctrl->cci_info->cci_i2c_master < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700849 CAM_ERR(CAM_CCI, "Invalid I2C master addr");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800850 return -EINVAL;
851 }
Alok Pandey01b1b352017-06-25 20:38:54 +0530852
853 soc_info = &cci_dev->soc_info;
854 base = soc_info->reg_map[0].mem_base;
855
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800856 mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);
857
858 /*
859 * Todo: If there is a change in frequency of operation
860 * Wait for previos transaction to complete
861 */
862
863 /* Set the I2C Frequency */
864 rc = cam_cci_set_clk_param(cci_dev, c_ctrl);
865 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700866 CAM_ERR(CAM_CCI, "cam_cci_set_clk_param failed rc = %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800867 goto rel_mutex;
868 }
869
870 /*
871 * Call validate queue to make sure queue is empty before starting.
872 * If this call fails, don't proceed with i2c_read call. This is to
873 * avoid overflow / underflow of queue
874 */
875 rc = cam_cci_validate_queue(cci_dev,
876 cci_dev->cci_i2c_queue_info[master][queue].max_queue_size - 1,
877 master, queue);
878 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700879 CAM_ERR(CAM_CCI, "Initial validataion failed rc %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800880 goto rel_mutex;
881 }
882
883 if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700884 CAM_ERR(CAM_CCI, "More than max retries");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800885 goto rel_mutex;
886 }
887
888 if (read_cfg->data == NULL) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700889 CAM_ERR(CAM_CCI, "Data ptr is NULL");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800890 goto rel_mutex;
891 }
892
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700893 CAM_DBG(CAM_CCI, "master %d, queue %d", master, queue);
894 CAM_DBG(CAM_CCI, "set param sid 0x%x retries %d id_map %d",
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800895 c_ctrl->cci_info->sid, c_ctrl->cci_info->retries,
896 c_ctrl->cci_info->id_map);
897 val = CCI_I2C_SET_PARAM_CMD | c_ctrl->cci_info->sid << 4 |
898 c_ctrl->cci_info->retries << 16 |
899 c_ctrl->cci_info->id_map << 18;
900 rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
901 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700902 CAM_DBG(CAM_CCI, "failed rc: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800903 goto rel_mutex;
904 }
905
906 val = CCI_I2C_LOCK_CMD;
907 rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
908 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700909 CAM_DBG(CAM_CCI, "failed rc: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800910 goto rel_mutex;
911 }
912
913 if (read_cfg->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700914 CAM_ERR(CAM_CCI, "failed : Invalid addr type: %u",
915 read_cfg->addr_type);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800916 rc = -EINVAL;
917 goto rel_mutex;
918 }
919
920 val = CCI_I2C_WRITE_DISABLE_P_CMD | (read_cfg->addr_type << 4);
921 for (i = 0; i < read_cfg->addr_type; i++) {
922 val |= ((read_cfg->addr >> (i << 3)) & 0xFF) <<
923 ((read_cfg->addr_type - i) << 3);
924 }
925
926 rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
927 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700928 CAM_DBG(CAM_CCI, "failed rc: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800929 goto rel_mutex;
930 }
931
932 val = CCI_I2C_READ_CMD | (read_cfg->num_byte << 4);
933 rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
934 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700935 CAM_DBG(CAM_CCI, "failed rc: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800936 goto rel_mutex;
937 }
938
939 val = CCI_I2C_UNLOCK_CMD;
940 rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
941 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700942 CAM_DBG(CAM_CCI, "failed rc: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800943 goto rel_mutex;
944 }
945
Alok Pandey01b1b352017-06-25 20:38:54 +0530946 val = cam_io_r_mb(base + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800947 + master * 0x200 + queue * 0x100);
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700948 CAM_DBG(CAM_CCI, "cur word cnt 0x%x", val);
Alok Pandey01b1b352017-06-25 20:38:54 +0530949 cam_io_w_mb(val, base + CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800950 + master * 0x200 + queue * 0x100);
951
952 val = 1 << ((master * 2) + queue);
Alok Pandey01b1b352017-06-25 20:38:54 +0530953 cam_io_w_mb(val, base + CCI_QUEUE_START_ADDR);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700954 CAM_DBG(CAM_CCI, "wait_for_completion_timeout");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800955
956 rc = wait_for_completion_timeout(&cci_dev->
957 cci_master_info[master].reset_complete, CCI_TIMEOUT);
958 if (rc <= 0) {
959#ifdef DUMP_CCI_REGISTERS
960 cam_cci_dump_registers(cci_dev, master, queue);
961#endif
962 if (rc == 0)
963 rc = -ETIMEDOUT;
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700964 CAM_ERR(CAM_CCI, "wait_for_completion_timeout rc = %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800965 cam_cci_flush_queue(cci_dev, master);
966 goto rel_mutex;
967 } else {
968 rc = 0;
969 }
970
Alok Pandey01b1b352017-06-25 20:38:54 +0530971 read_words = cam_io_r_mb(base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800972 CCI_I2C_M0_READ_BUF_LEVEL_ADDR + master * 0x100);
973 exp_words = ((read_cfg->num_byte / 4) + 1);
974 if (read_words != exp_words) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700975 CAM_ERR(CAM_CCI, "read_words = %d, exp words = %d",
976 read_words, exp_words);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800977 memset(read_cfg->data, 0, read_cfg->num_byte);
978 rc = -EINVAL;
979 goto rel_mutex;
980 }
981 index = 0;
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700982 CAM_DBG(CAM_CCI, "index %d num_type %d", index, read_cfg->num_byte);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800983 first_byte = 0;
984 do {
Alok Pandey01b1b352017-06-25 20:38:54 +0530985 val = cam_io_r_mb(base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800986 CCI_I2C_M0_READ_DATA_ADDR + master * 0x100);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700987 CAM_DBG(CAM_CCI, "read val 0x%x", val);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800988 for (i = 0; (i < 4) && (index < read_cfg->num_byte); i++) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700989 CAM_DBG(CAM_CCI, "i:%d index:%d", i, index);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800990 if (!first_byte) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700991 CAM_DBG(CAM_CCI, "sid 0x%x", val & 0xFF);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800992 first_byte++;
993 } else {
994 read_cfg->data[index] =
995 (val >> (i * 8)) & 0xFF;
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700996 CAM_DBG(CAM_CCI, "data[%d] 0x%x", index,
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800997 read_cfg->data[index]);
998 index++;
999 }
1000 }
1001 } while (--read_words > 0);
1002rel_mutex:
1003 mutex_unlock(&cci_dev->cci_master_info[master].mutex_q[queue]);
1004
1005 return rc;
1006}
1007
1008static int32_t cam_cci_i2c_write(struct v4l2_subdev *sd,
1009 struct cam_cci_ctrl *c_ctrl, enum cci_i2c_queue_t queue,
1010 enum cci_i2c_sync sync_en)
1011{
1012 int32_t rc = 0;
1013 struct cci_device *cci_dev;
1014 enum cci_i2c_master_t master;
1015
1016 cci_dev = v4l2_get_subdevdata(sd);
1017
1018 if (cci_dev->cci_state != CCI_STATE_ENABLED) {
Jigarkumar Zala22223f92017-07-28 12:46:27 -07001019 CAM_ERR(CAM_CCI, "invalid cci state %d",
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001020 cci_dev->cci_state);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001021 return -EINVAL;
1022 }
1023 master = c_ctrl->cci_info->cci_i2c_master;
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001024 CAM_DBG(CAM_CCI, "set param sid 0x%x retries %d id_map %d",
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001025 c_ctrl->cci_info->sid, c_ctrl->cci_info->retries,
1026 c_ctrl->cci_info->id_map);
1027
1028 /* Set the I2C Frequency */
1029 rc = cam_cci_set_clk_param(cci_dev, c_ctrl);
1030 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001031 CAM_ERR(CAM_CCI, "cam_cci_set_clk_param failed rc = %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001032 return rc;
1033 }
1034 /*
1035 * Call validate queue to make sure queue is empty before starting.
1036 * If this call fails, don't proceed with i2c_write call. This is to
1037 * avoid overflow / underflow of queue
1038 */
1039 rc = cam_cci_validate_queue(cci_dev,
1040 cci_dev->cci_i2c_queue_info[master][queue].max_queue_size-1,
1041 master, queue);
1042 if (rc < 0) {
Jigarkumar Zala22223f92017-07-28 12:46:27 -07001043 CAM_ERR(CAM_CCI, "Initial validataion failed rc %d",
1044 rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001045 return rc;
1046 }
1047 if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001048 CAM_ERR(CAM_CCI, "More than max retries");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001049 return rc;
1050 }
1051 rc = cam_cci_data_queue(cci_dev, c_ctrl, queue, sync_en);
1052 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001053 CAM_ERR(CAM_CCI, "failed rc: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001054 return rc;
1055 }
1056
1057 return rc;
1058}
1059
1060static void cam_cci_write_async_helper(struct work_struct *work)
1061{
1062 int rc;
1063 struct cci_device *cci_dev;
1064 struct cci_write_async *write_async =
1065 container_of(work, struct cci_write_async, work);
1066 struct cam_sensor_i2c_reg_setting *i2c_msg;
1067 enum cci_i2c_master_t master;
1068 struct cam_cci_master_info *cci_master_info;
1069
1070 cci_dev = write_async->cci_dev;
1071 i2c_msg = &write_async->c_ctrl.cfg.cci_i2c_write_cfg;
1072 master = write_async->c_ctrl.cci_info->cci_i2c_master;
1073 cci_master_info = &cci_dev->cci_master_info[master];
1074
1075 mutex_lock(&cci_master_info->mutex_q[write_async->queue]);
1076 rc = cam_cci_i2c_write(&(cci_dev->v4l2_dev_str.sd),
1077 &write_async->c_ctrl, write_async->queue, write_async->sync_en);
1078 mutex_unlock(&cci_master_info->mutex_q[write_async->queue]);
1079 if (rc < 0)
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001080 CAM_ERR(CAM_CCI, "failed rc: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001081
1082 kfree(write_async->c_ctrl.cfg.cci_i2c_write_cfg.reg_setting);
1083 kfree(write_async);
1084}
1085
1086static int32_t cam_cci_i2c_write_async(struct v4l2_subdev *sd,
1087 struct cam_cci_ctrl *c_ctrl, enum cci_i2c_queue_t queue,
1088 enum cci_i2c_sync sync_en)
1089{
1090 int32_t rc = 0;
1091 struct cci_write_async *write_async;
1092 struct cci_device *cci_dev;
1093 struct cam_sensor_i2c_reg_setting *cci_i2c_write_cfg;
1094 struct cam_sensor_i2c_reg_setting *cci_i2c_write_cfg_w;
1095
1096 cci_dev = v4l2_get_subdevdata(sd);
1097
1098 write_async = kzalloc(sizeof(*write_async), GFP_KERNEL);
1099 if (!write_async)
1100 return -ENOMEM;
1101
1102
1103 INIT_WORK(&write_async->work, cam_cci_write_async_helper);
1104 write_async->cci_dev = cci_dev;
1105 write_async->c_ctrl = *c_ctrl;
1106 write_async->queue = queue;
1107 write_async->sync_en = sync_en;
1108
1109 cci_i2c_write_cfg = &c_ctrl->cfg.cci_i2c_write_cfg;
1110 cci_i2c_write_cfg_w = &write_async->c_ctrl.cfg.cci_i2c_write_cfg;
1111
1112 if (cci_i2c_write_cfg->size == 0) {
1113 kfree(write_async);
1114 return -EINVAL;
1115 }
1116
1117 cci_i2c_write_cfg_w->reg_setting =
1118 kzalloc(sizeof(struct cam_sensor_i2c_reg_array)*
1119 cci_i2c_write_cfg->size, GFP_KERNEL);
1120 if (!cci_i2c_write_cfg_w->reg_setting) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001121 CAM_ERR(CAM_CCI, "Couldn't allocate memory");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001122 kfree(write_async);
1123 return -ENOMEM;
1124 }
1125 memcpy(cci_i2c_write_cfg_w->reg_setting,
1126 cci_i2c_write_cfg->reg_setting,
1127 (sizeof(struct cam_sensor_i2c_reg_array)*
1128 cci_i2c_write_cfg->size));
1129
1130 cci_i2c_write_cfg_w->addr_type = cci_i2c_write_cfg->addr_type;
1131 cci_i2c_write_cfg_w->addr_type = cci_i2c_write_cfg->addr_type;
1132 cci_i2c_write_cfg_w->data_type = cci_i2c_write_cfg->data_type;
1133 cci_i2c_write_cfg_w->size = cci_i2c_write_cfg->size;
1134 cci_i2c_write_cfg_w->delay = cci_i2c_write_cfg->delay;
1135
1136 queue_work(cci_dev->write_wq[write_async->queue], &write_async->work);
1137
1138 return rc;
1139}
1140
1141static int32_t cam_cci_read_bytes(struct v4l2_subdev *sd,
1142 struct cam_cci_ctrl *c_ctrl)
1143{
1144 int32_t rc = 0;
1145 struct cci_device *cci_dev = NULL;
1146 enum cci_i2c_master_t master;
1147 struct cam_cci_read_cfg *read_cfg = NULL;
1148 uint16_t read_bytes = 0;
1149
1150 if (!sd || !c_ctrl) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001151 CAM_ERR(CAM_CCI, "sd %pK c_ctrl %pK", sd, c_ctrl);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001152 return -EINVAL;
1153 }
1154 if (!c_ctrl->cci_info) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001155 CAM_ERR(CAM_CCI, "cci_info NULL");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001156 return -EINVAL;
1157 }
1158 cci_dev = v4l2_get_subdevdata(sd);
1159 if (!cci_dev) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001160 CAM_ERR(CAM_CCI, "cci_dev NULL");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001161 return -EINVAL;
1162 }
1163 if (cci_dev->cci_state != CCI_STATE_ENABLED) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001164 CAM_ERR(CAM_CCI, "invalid cci state %d", cci_dev->cci_state);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001165 return -EINVAL;
1166 }
1167
1168 if (c_ctrl->cci_info->cci_i2c_master >= MASTER_MAX
1169 || c_ctrl->cci_info->cci_i2c_master < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001170 CAM_ERR(CAM_CCI, "Invalid I2C master addr");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001171 return -EINVAL;
1172 }
1173
1174 master = c_ctrl->cci_info->cci_i2c_master;
1175 read_cfg = &c_ctrl->cfg.cci_i2c_read_cfg;
1176 if ((!read_cfg->num_byte) || (read_cfg->num_byte > CCI_I2C_MAX_READ)) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001177 CAM_ERR(CAM_CCI, "read num bytes 0");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001178 rc = -EINVAL;
1179 goto ERROR;
1180 }
1181
1182 read_bytes = read_cfg->num_byte;
1183 do {
1184 if (read_bytes > CCI_READ_MAX)
1185 read_cfg->num_byte = CCI_READ_MAX;
1186 else
1187 read_cfg->num_byte = read_bytes;
1188 rc = cam_cci_read(sd, c_ctrl);
1189 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001190 CAM_ERR(CAM_CCI, "failed rc %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001191 goto ERROR;
1192 }
1193 if (read_bytes > CCI_READ_MAX) {
1194 read_cfg->addr += CCI_READ_MAX;
1195 read_cfg->data += CCI_READ_MAX;
1196 read_bytes -= CCI_READ_MAX;
1197 } else {
1198 read_bytes = 0;
1199 }
1200 } while (read_bytes);
1201
1202ERROR:
1203 return rc;
1204}
1205
1206static int32_t cam_cci_i2c_set_sync_prms(struct v4l2_subdev *sd,
1207 struct cam_cci_ctrl *c_ctrl)
1208{
1209 int32_t rc = 0;
1210 struct cci_device *cci_dev;
1211
1212 cci_dev = v4l2_get_subdevdata(sd);
1213 if (!cci_dev || !c_ctrl) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001214 CAM_ERR(CAM_CCI, "failed: invalid params %pK %pK",
1215 cci_dev, c_ctrl);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001216 rc = -EINVAL;
1217 return rc;
1218 }
1219 cci_dev->cci_wait_sync_cfg = c_ctrl->cfg.cci_wait_sync_cfg;
1220 cci_dev->valid_sync = cci_dev->cci_wait_sync_cfg.csid < 0 ? 0 : 1;
1221
1222 return rc;
1223}
1224
1225static int32_t cam_cci_release(struct v4l2_subdev *sd)
1226{
1227 uint8_t rc = 0;
1228 struct cci_device *cci_dev;
1229
1230 cci_dev = v4l2_get_subdevdata(sd);
1231
1232 rc = cam_cci_soc_release(cci_dev);
1233 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001234 CAM_ERR(CAM_CCI, "Failed in releasing the cci: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001235 return rc;
1236 }
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001237
1238 return rc;
1239}
1240
1241static int32_t cam_cci_write(struct v4l2_subdev *sd,
1242 struct cam_cci_ctrl *c_ctrl)
1243{
1244 int32_t rc = 0;
1245 struct cci_device *cci_dev;
1246 enum cci_i2c_master_t master;
1247 struct cam_cci_master_info *cci_master_info;
1248 uint32_t i;
1249
1250 cci_dev = v4l2_get_subdevdata(sd);
1251 if (!cci_dev || !c_ctrl) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001252 CAM_ERR(CAM_CCI, "failed: invalid params %pK %pK",
1253 cci_dev, c_ctrl);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001254 rc = -EINVAL;
1255 return rc;
1256 }
1257
1258 master = c_ctrl->cci_info->cci_i2c_master;
1259
1260 if (c_ctrl->cci_info->cci_i2c_master >= MASTER_MAX
1261 || c_ctrl->cci_info->cci_i2c_master < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001262 CAM_ERR(CAM_CCI, "Invalid I2C master addr");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001263 return -EINVAL;
1264 }
1265
1266 cci_master_info = &cci_dev->cci_master_info[master];
1267
1268 switch (c_ctrl->cmd) {
1269 case MSM_CCI_I2C_WRITE_SYNC_BLOCK:
1270 mutex_lock(&cci_master_info->mutex_q[SYNC_QUEUE]);
1271 rc = cam_cci_i2c_write(sd, c_ctrl,
1272 SYNC_QUEUE, MSM_SYNC_ENABLE);
1273 mutex_unlock(&cci_master_info->mutex_q[SYNC_QUEUE]);
1274 break;
1275 case MSM_CCI_I2C_WRITE_SYNC:
1276 rc = cam_cci_i2c_write_async(sd, c_ctrl,
1277 SYNC_QUEUE, MSM_SYNC_ENABLE);
1278 break;
1279 case MSM_CCI_I2C_WRITE:
1280 case MSM_CCI_I2C_WRITE_SEQ:
Karthik Anantha Ram0fb02a32017-08-23 11:52:50 -07001281 case MSM_CCI_I2C_WRITE_BURST:
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001282 for (i = 0; i < NUM_QUEUES; i++) {
1283 if (mutex_trylock(&cci_master_info->mutex_q[i])) {
1284 rc = cam_cci_i2c_write(sd, c_ctrl, i,
1285 MSM_SYNC_DISABLE);
1286 mutex_unlock(&cci_master_info->mutex_q[i]);
1287 return rc;
1288 }
1289 }
1290 mutex_lock(&cci_master_info->mutex_q[PRIORITY_QUEUE]);
1291 rc = cam_cci_i2c_write(sd, c_ctrl,
1292 PRIORITY_QUEUE, MSM_SYNC_DISABLE);
1293 mutex_unlock(&cci_master_info->mutex_q[PRIORITY_QUEUE]);
1294 break;
1295 case MSM_CCI_I2C_WRITE_ASYNC:
1296 rc = cam_cci_i2c_write_async(sd, c_ctrl,
1297 PRIORITY_QUEUE, MSM_SYNC_DISABLE);
1298 break;
1299 default:
1300 rc = -ENOIOCTLCMD;
1301 }
1302
1303 return rc;
1304}
1305
1306int32_t cam_cci_core_cfg(struct v4l2_subdev *sd,
1307 struct cam_cci_ctrl *cci_ctrl)
1308{
1309 int32_t rc = 0;
1310
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001311 CAM_DBG(CAM_CCI, "cmd %d", cci_ctrl->cmd);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001312 switch (cci_ctrl->cmd) {
1313 case MSM_CCI_INIT:
1314 rc = cam_cci_init(sd, cci_ctrl);
1315 break;
1316 case MSM_CCI_RELEASE:
1317 rc = cam_cci_release(sd);
1318 break;
1319 case MSM_CCI_I2C_READ:
1320 rc = cam_cci_read_bytes(sd, cci_ctrl);
1321 break;
1322 case MSM_CCI_I2C_WRITE:
1323 case MSM_CCI_I2C_WRITE_SEQ:
Karthik Anantha Ram0fb02a32017-08-23 11:52:50 -07001324 case MSM_CCI_I2C_WRITE_BURST:
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001325 case MSM_CCI_I2C_WRITE_SYNC:
1326 case MSM_CCI_I2C_WRITE_ASYNC:
1327 case MSM_CCI_I2C_WRITE_SYNC_BLOCK:
1328 rc = cam_cci_write(sd, cci_ctrl);
1329 break;
1330 case MSM_CCI_GPIO_WRITE:
1331 break;
1332 case MSM_CCI_SET_SYNC_CID:
1333 rc = cam_cci_i2c_set_sync_prms(sd, cci_ctrl);
1334 break;
1335
1336 default:
1337 rc = -ENOIOCTLCMD;
1338 }
1339
1340 cci_ctrl->status = rc;
1341
1342 return rc;
1343}