blob: c62b2510041495d8e00ddcf77aac8e0d971c5ff1 [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;
444 *pack += data_len;
445 } 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) {
733 data[i++] = (i2c_cmd->reg_data &
734 0xFF00) >> 8; /* MSB */
735 data[i++] = i2c_cmd->reg_data &
736 0x00FF; /* LSB */
Karthik Anantha Ram0fb02a32017-08-23 11:52:50 -0700737 if (c_ctrl->cmd ==
738 MSM_CCI_I2C_WRITE_SEQ)
739 reg_addr++;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800740 } else
741 break;
742 }
743 i2c_cmd++;
744 --cmd_size;
Karthik Anantha Ram0fb02a32017-08-23 11:52:50 -0700745 } while (((c_ctrl->cmd == MSM_CCI_I2C_WRITE_SEQ ||
746 c_ctrl->cmd == MSM_CCI_I2C_WRITE_BURST) || pack--) &&
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800747 (cmd_size > 0) && (i <= cci_dev->payload_size));
748 free_size = cam_cci_get_queue_free_size(cci_dev, master,
749 queue);
Karthik Anantha Ram0fb02a32017-08-23 11:52:50 -0700750 if ((c_ctrl->cmd == MSM_CCI_I2C_WRITE_SEQ ||
751 c_ctrl->cmd == MSM_CCI_I2C_WRITE_BURST) &&
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800752 ((i-1) == MSM_CCI_WRITE_DATA_PAYLOAD_SIZE_11) &&
753 cci_dev->support_seq_write && cmd_size > 0 &&
754 free_size > BURST_MIN_FREE_SIZE) {
755 data[0] |= 0xF0;
756 en_seq_write = 1;
757 } else {
758 data[0] |= ((i-1) << 4);
759 en_seq_write = 0;
760 }
761 len = ((i-1)/4) + 1;
762
Alok Pandey01b1b352017-06-25 20:38:54 +0530763 read_val = cam_io_r_mb(base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800764 CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR + reg_offset);
765 for (h = 0, k = 0; h < len; h++) {
766 cmd = 0;
767 for (j = 0; (j < 4 && k < i); j++)
768 cmd |= (data[k++] << (j * 8));
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700769 CAM_DBG(CAM_CCI,
770 "LOAD_DATA_ADDR 0x%x, q: %d, len:%d, cnt: %d",
771 cmd, queue, len, read_val);
Alok Pandey01b1b352017-06-25 20:38:54 +0530772 cam_io_w_mb(cmd, base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800773 CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
774 master * 0x200 + queue * 0x100);
775
776 read_val += 1;
Alok Pandey01b1b352017-06-25 20:38:54 +0530777 cam_io_w_mb(read_val, base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800778 CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + reg_offset);
779 }
780
781 if ((delay > 0) && (delay < CCI_MAX_DELAY) &&
782 en_seq_write == 0) {
783 cmd = (uint32_t)((delay * cci_dev->cycles_per_us) /
784 0x100);
785 cmd <<= 4;
786 cmd |= CCI_I2C_WAIT_CMD;
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700787 CAM_DBG(CAM_CCI,
788 "CCI_I2C_M0_Q0_LOAD_DATA_ADDR 0x%x", cmd);
Alok Pandey01b1b352017-06-25 20:38:54 +0530789 cam_io_w_mb(cmd, base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800790 CCI_I2C_M0_Q0_LOAD_DATA_ADDR +
791 master * 0x200 + queue * 0x100);
792 read_val += 1;
Alok Pandey01b1b352017-06-25 20:38:54 +0530793 cam_io_w_mb(read_val, base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800794 CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR + reg_offset);
795 }
796 }
797
798 rc = cam_cci_transfer_end(cci_dev, master, queue);
799 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700800 CAM_ERR(CAM_CCI, "failed rc %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800801 return rc;
802 }
803
804 return rc;
805}
806
807static int32_t cam_cci_read(struct v4l2_subdev *sd,
808 struct cam_cci_ctrl *c_ctrl)
809{
810 int32_t rc = 0;
811 uint32_t val = 0;
812 int32_t read_words = 0, exp_words = 0;
813 int32_t index = 0, first_byte = 0;
814 uint32_t i = 0;
815 enum cci_i2c_master_t master;
816 enum cci_i2c_queue_t queue = QUEUE_1;
817 struct cci_device *cci_dev = NULL;
818 struct cam_cci_read_cfg *read_cfg = NULL;
Alok Pandey01b1b352017-06-25 20:38:54 +0530819 struct cam_hw_soc_info *soc_info = NULL;
820 void __iomem *base = NULL;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800821
822 cci_dev = v4l2_get_subdevdata(sd);
823 master = c_ctrl->cci_info->cci_i2c_master;
824 read_cfg = &c_ctrl->cfg.cci_i2c_read_cfg;
825
826 if (c_ctrl->cci_info->cci_i2c_master >= MASTER_MAX
827 || c_ctrl->cci_info->cci_i2c_master < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700828 CAM_ERR(CAM_CCI, "Invalid I2C master addr");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800829 return -EINVAL;
830 }
Alok Pandey01b1b352017-06-25 20:38:54 +0530831
832 soc_info = &cci_dev->soc_info;
833 base = soc_info->reg_map[0].mem_base;
834
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800835 mutex_lock(&cci_dev->cci_master_info[master].mutex_q[queue]);
836
837 /*
838 * Todo: If there is a change in frequency of operation
839 * Wait for previos transaction to complete
840 */
841
842 /* Set the I2C Frequency */
843 rc = cam_cci_set_clk_param(cci_dev, c_ctrl);
844 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700845 CAM_ERR(CAM_CCI, "cam_cci_set_clk_param failed rc = %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800846 goto rel_mutex;
847 }
848
849 /*
850 * Call validate queue to make sure queue is empty before starting.
851 * If this call fails, don't proceed with i2c_read call. This is to
852 * avoid overflow / underflow of queue
853 */
854 rc = cam_cci_validate_queue(cci_dev,
855 cci_dev->cci_i2c_queue_info[master][queue].max_queue_size - 1,
856 master, queue);
857 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700858 CAM_ERR(CAM_CCI, "Initial validataion failed rc %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800859 goto rel_mutex;
860 }
861
862 if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700863 CAM_ERR(CAM_CCI, "More than max retries");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800864 goto rel_mutex;
865 }
866
867 if (read_cfg->data == NULL) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700868 CAM_ERR(CAM_CCI, "Data ptr is NULL");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800869 goto rel_mutex;
870 }
871
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700872 CAM_DBG(CAM_CCI, "master %d, queue %d", master, queue);
873 CAM_DBG(CAM_CCI, "set param sid 0x%x retries %d id_map %d",
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800874 c_ctrl->cci_info->sid, c_ctrl->cci_info->retries,
875 c_ctrl->cci_info->id_map);
876 val = CCI_I2C_SET_PARAM_CMD | c_ctrl->cci_info->sid << 4 |
877 c_ctrl->cci_info->retries << 16 |
878 c_ctrl->cci_info->id_map << 18;
879 rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
880 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700881 CAM_DBG(CAM_CCI, "failed rc: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800882 goto rel_mutex;
883 }
884
885 val = CCI_I2C_LOCK_CMD;
886 rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
887 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700888 CAM_DBG(CAM_CCI, "failed rc: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800889 goto rel_mutex;
890 }
891
892 if (read_cfg->addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700893 CAM_ERR(CAM_CCI, "failed : Invalid addr type: %u",
894 read_cfg->addr_type);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800895 rc = -EINVAL;
896 goto rel_mutex;
897 }
898
899 val = CCI_I2C_WRITE_DISABLE_P_CMD | (read_cfg->addr_type << 4);
900 for (i = 0; i < read_cfg->addr_type; i++) {
901 val |= ((read_cfg->addr >> (i << 3)) & 0xFF) <<
902 ((read_cfg->addr_type - i) << 3);
903 }
904
905 rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
906 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700907 CAM_DBG(CAM_CCI, "failed rc: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800908 goto rel_mutex;
909 }
910
911 val = CCI_I2C_READ_CMD | (read_cfg->num_byte << 4);
912 rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
913 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700914 CAM_DBG(CAM_CCI, "failed rc: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800915 goto rel_mutex;
916 }
917
918 val = CCI_I2C_UNLOCK_CMD;
919 rc = cam_cci_write_i2c_queue(cci_dev, val, master, queue);
920 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700921 CAM_DBG(CAM_CCI, "failed rc: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800922 goto rel_mutex;
923 }
924
Alok Pandey01b1b352017-06-25 20:38:54 +0530925 val = cam_io_r_mb(base + CCI_I2C_M0_Q0_CUR_WORD_CNT_ADDR
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800926 + master * 0x200 + queue * 0x100);
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700927 CAM_DBG(CAM_CCI, "cur word cnt 0x%x", val);
Alok Pandey01b1b352017-06-25 20:38:54 +0530928 cam_io_w_mb(val, base + CCI_I2C_M0_Q0_EXEC_WORD_CNT_ADDR
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800929 + master * 0x200 + queue * 0x100);
930
931 val = 1 << ((master * 2) + queue);
Alok Pandey01b1b352017-06-25 20:38:54 +0530932 cam_io_w_mb(val, base + CCI_QUEUE_START_ADDR);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700933 CAM_DBG(CAM_CCI, "wait_for_completion_timeout");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800934
935 rc = wait_for_completion_timeout(&cci_dev->
936 cci_master_info[master].reset_complete, CCI_TIMEOUT);
937 if (rc <= 0) {
938#ifdef DUMP_CCI_REGISTERS
939 cam_cci_dump_registers(cci_dev, master, queue);
940#endif
941 if (rc == 0)
942 rc = -ETIMEDOUT;
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700943 CAM_ERR(CAM_CCI, "wait_for_completion_timeout rc = %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800944 cam_cci_flush_queue(cci_dev, master);
945 goto rel_mutex;
946 } else {
947 rc = 0;
948 }
949
Alok Pandey01b1b352017-06-25 20:38:54 +0530950 read_words = cam_io_r_mb(base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800951 CCI_I2C_M0_READ_BUF_LEVEL_ADDR + master * 0x100);
952 exp_words = ((read_cfg->num_byte / 4) + 1);
953 if (read_words != exp_words) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700954 CAM_ERR(CAM_CCI, "read_words = %d, exp words = %d",
955 read_words, exp_words);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800956 memset(read_cfg->data, 0, read_cfg->num_byte);
957 rc = -EINVAL;
958 goto rel_mutex;
959 }
960 index = 0;
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700961 CAM_DBG(CAM_CCI, "index %d num_type %d", index, read_cfg->num_byte);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800962 first_byte = 0;
963 do {
Alok Pandey01b1b352017-06-25 20:38:54 +0530964 val = cam_io_r_mb(base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800965 CCI_I2C_M0_READ_DATA_ADDR + master * 0x100);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700966 CAM_DBG(CAM_CCI, "read val 0x%x", val);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800967 for (i = 0; (i < 4) && (index < read_cfg->num_byte); i++) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700968 CAM_DBG(CAM_CCI, "i:%d index:%d", i, index);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800969 if (!first_byte) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700970 CAM_DBG(CAM_CCI, "sid 0x%x", val & 0xFF);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800971 first_byte++;
972 } else {
973 read_cfg->data[index] =
974 (val >> (i * 8)) & 0xFF;
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700975 CAM_DBG(CAM_CCI, "data[%d] 0x%x", index,
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800976 read_cfg->data[index]);
977 index++;
978 }
979 }
980 } while (--read_words > 0);
981rel_mutex:
982 mutex_unlock(&cci_dev->cci_master_info[master].mutex_q[queue]);
983
984 return rc;
985}
986
987static int32_t cam_cci_i2c_write(struct v4l2_subdev *sd,
988 struct cam_cci_ctrl *c_ctrl, enum cci_i2c_queue_t queue,
989 enum cci_i2c_sync sync_en)
990{
991 int32_t rc = 0;
992 struct cci_device *cci_dev;
993 enum cci_i2c_master_t master;
994
995 cci_dev = v4l2_get_subdevdata(sd);
996
997 if (cci_dev->cci_state != CCI_STATE_ENABLED) {
Jigarkumar Zala22223f92017-07-28 12:46:27 -0700998 CAM_ERR(CAM_CCI, "invalid cci state %d",
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700999 cci_dev->cci_state);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001000 return -EINVAL;
1001 }
1002 master = c_ctrl->cci_info->cci_i2c_master;
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001003 CAM_DBG(CAM_CCI, "set param sid 0x%x retries %d id_map %d",
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001004 c_ctrl->cci_info->sid, c_ctrl->cci_info->retries,
1005 c_ctrl->cci_info->id_map);
1006
1007 /* Set the I2C Frequency */
1008 rc = cam_cci_set_clk_param(cci_dev, c_ctrl);
1009 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001010 CAM_ERR(CAM_CCI, "cam_cci_set_clk_param failed rc = %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001011 return rc;
1012 }
1013 /*
1014 * Call validate queue to make sure queue is empty before starting.
1015 * If this call fails, don't proceed with i2c_write call. This is to
1016 * avoid overflow / underflow of queue
1017 */
1018 rc = cam_cci_validate_queue(cci_dev,
1019 cci_dev->cci_i2c_queue_info[master][queue].max_queue_size-1,
1020 master, queue);
1021 if (rc < 0) {
Jigarkumar Zala22223f92017-07-28 12:46:27 -07001022 CAM_ERR(CAM_CCI, "Initial validataion failed rc %d",
1023 rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001024 return rc;
1025 }
1026 if (c_ctrl->cci_info->retries > CCI_I2C_READ_MAX_RETRIES) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001027 CAM_ERR(CAM_CCI, "More than max retries");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001028 return rc;
1029 }
1030 rc = cam_cci_data_queue(cci_dev, c_ctrl, queue, sync_en);
1031 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001032 CAM_ERR(CAM_CCI, "failed rc: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001033 return rc;
1034 }
1035
1036 return rc;
1037}
1038
1039static void cam_cci_write_async_helper(struct work_struct *work)
1040{
1041 int rc;
1042 struct cci_device *cci_dev;
1043 struct cci_write_async *write_async =
1044 container_of(work, struct cci_write_async, work);
1045 struct cam_sensor_i2c_reg_setting *i2c_msg;
1046 enum cci_i2c_master_t master;
1047 struct cam_cci_master_info *cci_master_info;
1048
1049 cci_dev = write_async->cci_dev;
1050 i2c_msg = &write_async->c_ctrl.cfg.cci_i2c_write_cfg;
1051 master = write_async->c_ctrl.cci_info->cci_i2c_master;
1052 cci_master_info = &cci_dev->cci_master_info[master];
1053
1054 mutex_lock(&cci_master_info->mutex_q[write_async->queue]);
1055 rc = cam_cci_i2c_write(&(cci_dev->v4l2_dev_str.sd),
1056 &write_async->c_ctrl, write_async->queue, write_async->sync_en);
1057 mutex_unlock(&cci_master_info->mutex_q[write_async->queue]);
1058 if (rc < 0)
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001059 CAM_ERR(CAM_CCI, "failed rc: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001060
1061 kfree(write_async->c_ctrl.cfg.cci_i2c_write_cfg.reg_setting);
1062 kfree(write_async);
1063}
1064
1065static int32_t cam_cci_i2c_write_async(struct v4l2_subdev *sd,
1066 struct cam_cci_ctrl *c_ctrl, enum cci_i2c_queue_t queue,
1067 enum cci_i2c_sync sync_en)
1068{
1069 int32_t rc = 0;
1070 struct cci_write_async *write_async;
1071 struct cci_device *cci_dev;
1072 struct cam_sensor_i2c_reg_setting *cci_i2c_write_cfg;
1073 struct cam_sensor_i2c_reg_setting *cci_i2c_write_cfg_w;
1074
1075 cci_dev = v4l2_get_subdevdata(sd);
1076
1077 write_async = kzalloc(sizeof(*write_async), GFP_KERNEL);
1078 if (!write_async)
1079 return -ENOMEM;
1080
1081
1082 INIT_WORK(&write_async->work, cam_cci_write_async_helper);
1083 write_async->cci_dev = cci_dev;
1084 write_async->c_ctrl = *c_ctrl;
1085 write_async->queue = queue;
1086 write_async->sync_en = sync_en;
1087
1088 cci_i2c_write_cfg = &c_ctrl->cfg.cci_i2c_write_cfg;
1089 cci_i2c_write_cfg_w = &write_async->c_ctrl.cfg.cci_i2c_write_cfg;
1090
1091 if (cci_i2c_write_cfg->size == 0) {
1092 kfree(write_async);
1093 return -EINVAL;
1094 }
1095
1096 cci_i2c_write_cfg_w->reg_setting =
1097 kzalloc(sizeof(struct cam_sensor_i2c_reg_array)*
1098 cci_i2c_write_cfg->size, GFP_KERNEL);
1099 if (!cci_i2c_write_cfg_w->reg_setting) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001100 CAM_ERR(CAM_CCI, "Couldn't allocate memory");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001101 kfree(write_async);
1102 return -ENOMEM;
1103 }
1104 memcpy(cci_i2c_write_cfg_w->reg_setting,
1105 cci_i2c_write_cfg->reg_setting,
1106 (sizeof(struct cam_sensor_i2c_reg_array)*
1107 cci_i2c_write_cfg->size));
1108
1109 cci_i2c_write_cfg_w->addr_type = cci_i2c_write_cfg->addr_type;
1110 cci_i2c_write_cfg_w->addr_type = cci_i2c_write_cfg->addr_type;
1111 cci_i2c_write_cfg_w->data_type = cci_i2c_write_cfg->data_type;
1112 cci_i2c_write_cfg_w->size = cci_i2c_write_cfg->size;
1113 cci_i2c_write_cfg_w->delay = cci_i2c_write_cfg->delay;
1114
1115 queue_work(cci_dev->write_wq[write_async->queue], &write_async->work);
1116
1117 return rc;
1118}
1119
1120static int32_t cam_cci_read_bytes(struct v4l2_subdev *sd,
1121 struct cam_cci_ctrl *c_ctrl)
1122{
1123 int32_t rc = 0;
1124 struct cci_device *cci_dev = NULL;
1125 enum cci_i2c_master_t master;
1126 struct cam_cci_read_cfg *read_cfg = NULL;
1127 uint16_t read_bytes = 0;
1128
1129 if (!sd || !c_ctrl) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001130 CAM_ERR(CAM_CCI, "sd %pK c_ctrl %pK", sd, c_ctrl);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001131 return -EINVAL;
1132 }
1133 if (!c_ctrl->cci_info) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001134 CAM_ERR(CAM_CCI, "cci_info NULL");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001135 return -EINVAL;
1136 }
1137 cci_dev = v4l2_get_subdevdata(sd);
1138 if (!cci_dev) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001139 CAM_ERR(CAM_CCI, "cci_dev NULL");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001140 return -EINVAL;
1141 }
1142 if (cci_dev->cci_state != CCI_STATE_ENABLED) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001143 CAM_ERR(CAM_CCI, "invalid cci state %d", cci_dev->cci_state);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001144 return -EINVAL;
1145 }
1146
1147 if (c_ctrl->cci_info->cci_i2c_master >= MASTER_MAX
1148 || c_ctrl->cci_info->cci_i2c_master < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001149 CAM_ERR(CAM_CCI, "Invalid I2C master addr");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001150 return -EINVAL;
1151 }
1152
1153 master = c_ctrl->cci_info->cci_i2c_master;
1154 read_cfg = &c_ctrl->cfg.cci_i2c_read_cfg;
1155 if ((!read_cfg->num_byte) || (read_cfg->num_byte > CCI_I2C_MAX_READ)) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001156 CAM_ERR(CAM_CCI, "read num bytes 0");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001157 rc = -EINVAL;
1158 goto ERROR;
1159 }
1160
1161 read_bytes = read_cfg->num_byte;
1162 do {
1163 if (read_bytes > CCI_READ_MAX)
1164 read_cfg->num_byte = CCI_READ_MAX;
1165 else
1166 read_cfg->num_byte = read_bytes;
1167 rc = cam_cci_read(sd, c_ctrl);
1168 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001169 CAM_ERR(CAM_CCI, "failed rc %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001170 goto ERROR;
1171 }
1172 if (read_bytes > CCI_READ_MAX) {
1173 read_cfg->addr += CCI_READ_MAX;
1174 read_cfg->data += CCI_READ_MAX;
1175 read_bytes -= CCI_READ_MAX;
1176 } else {
1177 read_bytes = 0;
1178 }
1179 } while (read_bytes);
1180
1181ERROR:
1182 return rc;
1183}
1184
1185static int32_t cam_cci_i2c_set_sync_prms(struct v4l2_subdev *sd,
1186 struct cam_cci_ctrl *c_ctrl)
1187{
1188 int32_t rc = 0;
1189 struct cci_device *cci_dev;
1190
1191 cci_dev = v4l2_get_subdevdata(sd);
1192 if (!cci_dev || !c_ctrl) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001193 CAM_ERR(CAM_CCI, "failed: invalid params %pK %pK",
1194 cci_dev, c_ctrl);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001195 rc = -EINVAL;
1196 return rc;
1197 }
1198 cci_dev->cci_wait_sync_cfg = c_ctrl->cfg.cci_wait_sync_cfg;
1199 cci_dev->valid_sync = cci_dev->cci_wait_sync_cfg.csid < 0 ? 0 : 1;
1200
1201 return rc;
1202}
1203
1204static int32_t cam_cci_release(struct v4l2_subdev *sd)
1205{
1206 uint8_t rc = 0;
1207 struct cci_device *cci_dev;
1208
1209 cci_dev = v4l2_get_subdevdata(sd);
1210
1211 rc = cam_cci_soc_release(cci_dev);
1212 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001213 CAM_ERR(CAM_CCI, "Failed in releasing the cci: %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001214 return rc;
1215 }
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001216
1217 return rc;
1218}
1219
1220static int32_t cam_cci_write(struct v4l2_subdev *sd,
1221 struct cam_cci_ctrl *c_ctrl)
1222{
1223 int32_t rc = 0;
1224 struct cci_device *cci_dev;
1225 enum cci_i2c_master_t master;
1226 struct cam_cci_master_info *cci_master_info;
1227 uint32_t i;
1228
1229 cci_dev = v4l2_get_subdevdata(sd);
1230 if (!cci_dev || !c_ctrl) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001231 CAM_ERR(CAM_CCI, "failed: invalid params %pK %pK",
1232 cci_dev, c_ctrl);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001233 rc = -EINVAL;
1234 return rc;
1235 }
1236
1237 master = c_ctrl->cci_info->cci_i2c_master;
1238
1239 if (c_ctrl->cci_info->cci_i2c_master >= MASTER_MAX
1240 || c_ctrl->cci_info->cci_i2c_master < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001241 CAM_ERR(CAM_CCI, "Invalid I2C master addr");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001242 return -EINVAL;
1243 }
1244
1245 cci_master_info = &cci_dev->cci_master_info[master];
1246
1247 switch (c_ctrl->cmd) {
1248 case MSM_CCI_I2C_WRITE_SYNC_BLOCK:
1249 mutex_lock(&cci_master_info->mutex_q[SYNC_QUEUE]);
1250 rc = cam_cci_i2c_write(sd, c_ctrl,
1251 SYNC_QUEUE, MSM_SYNC_ENABLE);
1252 mutex_unlock(&cci_master_info->mutex_q[SYNC_QUEUE]);
1253 break;
1254 case MSM_CCI_I2C_WRITE_SYNC:
1255 rc = cam_cci_i2c_write_async(sd, c_ctrl,
1256 SYNC_QUEUE, MSM_SYNC_ENABLE);
1257 break;
1258 case MSM_CCI_I2C_WRITE:
1259 case MSM_CCI_I2C_WRITE_SEQ:
Karthik Anantha Ram0fb02a32017-08-23 11:52:50 -07001260 case MSM_CCI_I2C_WRITE_BURST:
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001261 for (i = 0; i < NUM_QUEUES; i++) {
1262 if (mutex_trylock(&cci_master_info->mutex_q[i])) {
1263 rc = cam_cci_i2c_write(sd, c_ctrl, i,
1264 MSM_SYNC_DISABLE);
1265 mutex_unlock(&cci_master_info->mutex_q[i]);
1266 return rc;
1267 }
1268 }
1269 mutex_lock(&cci_master_info->mutex_q[PRIORITY_QUEUE]);
1270 rc = cam_cci_i2c_write(sd, c_ctrl,
1271 PRIORITY_QUEUE, MSM_SYNC_DISABLE);
1272 mutex_unlock(&cci_master_info->mutex_q[PRIORITY_QUEUE]);
1273 break;
1274 case MSM_CCI_I2C_WRITE_ASYNC:
1275 rc = cam_cci_i2c_write_async(sd, c_ctrl,
1276 PRIORITY_QUEUE, MSM_SYNC_DISABLE);
1277 break;
1278 default:
1279 rc = -ENOIOCTLCMD;
1280 }
1281
1282 return rc;
1283}
1284
1285int32_t cam_cci_core_cfg(struct v4l2_subdev *sd,
1286 struct cam_cci_ctrl *cci_ctrl)
1287{
1288 int32_t rc = 0;
1289
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -07001290 CAM_DBG(CAM_CCI, "cmd %d", cci_ctrl->cmd);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001291 switch (cci_ctrl->cmd) {
1292 case MSM_CCI_INIT:
1293 rc = cam_cci_init(sd, cci_ctrl);
1294 break;
1295 case MSM_CCI_RELEASE:
1296 rc = cam_cci_release(sd);
1297 break;
1298 case MSM_CCI_I2C_READ:
1299 rc = cam_cci_read_bytes(sd, cci_ctrl);
1300 break;
1301 case MSM_CCI_I2C_WRITE:
1302 case MSM_CCI_I2C_WRITE_SEQ:
Karthik Anantha Ram0fb02a32017-08-23 11:52:50 -07001303 case MSM_CCI_I2C_WRITE_BURST:
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -08001304 case MSM_CCI_I2C_WRITE_SYNC:
1305 case MSM_CCI_I2C_WRITE_ASYNC:
1306 case MSM_CCI_I2C_WRITE_SYNC_BLOCK:
1307 rc = cam_cci_write(sd, cci_ctrl);
1308 break;
1309 case MSM_CCI_GPIO_WRITE:
1310 break;
1311 case MSM_CCI_SET_SYNC_CID:
1312 rc = cam_cci_i2c_set_sync_prms(sd, cci_ctrl);
1313 break;
1314
1315 default:
1316 rc = -ENOIOCTLCMD;
1317 }
1318
1319 cci_ctrl->status = rc;
1320
1321 return rc;
1322}