blob: 8de447261fd1e7c59f4946eb426f6fc239fd9693 [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 "cam_cci_dev.h"
14#include "cam_cci_core.h"
15
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -080016int cam_cci_init(struct v4l2_subdev *sd,
17 struct cam_cci_ctrl *c_ctrl)
18{
19 uint8_t i = 0, j = 0;
Alok Pandey01b1b352017-06-25 20:38:54 +053020 int32_t rc = 0;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -080021 struct cci_device *cci_dev;
22 enum cci_i2c_master_t master = MASTER_0;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -080023 struct cam_ahb_vote ahb_vote;
24 struct cam_axi_vote axi_vote;
Alok Pandey01b1b352017-06-25 20:38:54 +053025 struct cam_hw_soc_info *soc_info = NULL;
26 void __iomem *base = NULL;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -080027
28 cci_dev = v4l2_get_subdevdata(sd);
29 if (!cci_dev || !c_ctrl) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -070030 CAM_ERR(CAM_CCI, "failed: invalid params %pK %pK",
31 cci_dev, c_ctrl);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -080032 rc = -EINVAL;
33 return rc;
34 }
35
Alok Pandey01b1b352017-06-25 20:38:54 +053036 soc_info = &cci_dev->soc_info;
37 base = soc_info->reg_map[0].mem_base;
38
39 if (!soc_info || !base) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -070040 CAM_ERR(CAM_CCI, "failed: invalid params %pK %pK",
41 soc_info, base);
Alok Pandey01b1b352017-06-25 20:38:54 +053042 rc = -EINVAL;
43 return rc;
44 }
45
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -070046 CAM_DBG(CAM_CCI, "Base address %pK", base);
Alok Pandey01b1b352017-06-25 20:38:54 +053047
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -080048 if (cci_dev->ref_count++) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -070049 CAM_DBG(CAM_CCI, "ref_count %d", cci_dev->ref_count);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -080050 master = c_ctrl->cci_info->cci_i2c_master;
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -070051 CAM_DBG(CAM_CCI, "master %d", master);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -080052 if (master < MASTER_MAX && master >= 0) {
53 mutex_lock(&cci_dev->cci_master_info[master].mutex);
54 flush_workqueue(cci_dev->write_wq[master]);
55 /* Re-initialize the completion */
56 reinit_completion(&cci_dev->
57 cci_master_info[master].reset_complete);
58 for (i = 0; i < NUM_QUEUES; i++)
59 reinit_completion(&cci_dev->
60 cci_master_info[master].report_q[i]);
61 /* Set reset pending flag to TRUE */
62 cci_dev->cci_master_info[master].reset_pending = TRUE;
63 /* Set proper mask to RESET CMD address */
64 if (master == MASTER_0)
65 cam_io_w_mb(CCI_M0_RESET_RMSK,
Alok Pandey01b1b352017-06-25 20:38:54 +053066 base + CCI_RESET_CMD_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -080067 else
68 cam_io_w_mb(CCI_M1_RESET_RMSK,
Alok Pandey01b1b352017-06-25 20:38:54 +053069 base + CCI_RESET_CMD_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -080070 /* wait for reset done irq */
71 rc = wait_for_completion_timeout(
72 &cci_dev->cci_master_info[master].
73 reset_complete,
74 CCI_TIMEOUT);
75 if (rc <= 0)
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -070076 CAM_ERR(CAM_CCI, "wait failed %d", rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -080077 mutex_unlock(&cci_dev->cci_master_info[master].mutex);
78 }
79 return 0;
80 }
81
82 ahb_vote.type = CAM_VOTE_ABSOLUTE;
83 ahb_vote.vote.level = CAM_SVS_VOTE;
84 axi_vote.compressed_bw = CAM_CPAS_DEFAULT_AXI_BW;
85 axi_vote.uncompressed_bw = CAM_CPAS_DEFAULT_AXI_BW;
86
87 rc = cam_cpas_start(cci_dev->cpas_handle,
88 &ahb_vote, &axi_vote);
89 if (rc != 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -070090 CAM_ERR(CAM_CCI, "CPAS start failed");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -080091 }
Alok Pandey01b1b352017-06-25 20:38:54 +053092 cam_cci_get_clk_rates(cci_dev, c_ctrl);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -080093
94 /* Re-initialize the completion */
95 reinit_completion(&cci_dev->cci_master_info[master].reset_complete);
96 for (i = 0; i < NUM_QUEUES; i++)
97 reinit_completion(&cci_dev->cci_master_info[master].
98 report_q[i]);
Alok Pandey01b1b352017-06-25 20:38:54 +053099
100 /* Enable Regulators and IRQ*/
101 rc = cam_soc_util_enable_platform_resource(soc_info, true,
102 CAM_TURBO_VOTE, true);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800103 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700104 CAM_DBG(CAM_CCI, "request platform resources failed");
Alok Pandey01b1b352017-06-25 20:38:54 +0530105 goto platform_enable_failed;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800106 }
Alok Pandey01b1b352017-06-25 20:38:54 +0530107
108 cci_dev->hw_version = cam_io_r_mb(base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800109 CCI_HW_VERSION_ADDR);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700110 CAM_DBG(CAM_CCI, "hw_version = 0x%x", cci_dev->hw_version);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800111
112 cci_dev->payload_size =
113 MSM_CCI_WRITE_DATA_PAYLOAD_SIZE_11;
114 cci_dev->support_seq_write = 1;
115
116 for (i = 0; i < NUM_MASTERS; i++) {
117 for (j = 0; j < NUM_QUEUES; j++) {
118 if (j == QUEUE_0)
119 cci_dev->cci_i2c_queue_info[i][j].
120 max_queue_size =
121 CCI_I2C_QUEUE_0_SIZE;
122 else
123 cci_dev->cci_i2c_queue_info[i][j].
124 max_queue_size =
125 CCI_I2C_QUEUE_1_SIZE;
126
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700127 CAM_DBG(CAM_CCI, "CCI Master[%d] :: Q0 : %d Q1 : %d", i
128 , cci_dev->cci_i2c_queue_info[i][j].
129 max_queue_size,
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800130 cci_dev->cci_i2c_queue_info[i][j].
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700131 max_queue_size);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800132 }
133 }
134
135 cci_dev->cci_master_info[MASTER_0].reset_pending = TRUE;
Alok Pandey01b1b352017-06-25 20:38:54 +0530136 cam_io_w_mb(CCI_RESET_CMD_RMSK, base +
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800137 CCI_RESET_CMD_ADDR);
Alok Pandey01b1b352017-06-25 20:38:54 +0530138 cam_io_w_mb(0x1, base + CCI_RESET_CMD_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800139 rc = wait_for_completion_timeout(
140 &cci_dev->cci_master_info[MASTER_0].reset_complete,
141 CCI_TIMEOUT);
142 if (rc <= 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700143 CAM_ERR(CAM_CCI, "wait_for_completion_timeout");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800144 if (rc == 0)
145 rc = -ETIMEDOUT;
146 goto reset_complete_failed;
147 }
148 for (i = 0; i < MASTER_MAX; i++)
149 cci_dev->i2c_freq_mode[i] = I2C_MAX_MODES;
150 cam_io_w_mb(CCI_IRQ_MASK_0_RMSK,
Alok Pandey01b1b352017-06-25 20:38:54 +0530151 base + CCI_IRQ_MASK_0_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800152 cam_io_w_mb(CCI_IRQ_MASK_0_RMSK,
Alok Pandey01b1b352017-06-25 20:38:54 +0530153 base + CCI_IRQ_CLEAR_0_ADDR);
154 cam_io_w_mb(0x1, base + CCI_IRQ_GLOBAL_CLEAR_CMD_ADDR);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800155
156 for (i = 0; i < MASTER_MAX; i++) {
157 if (!cci_dev->write_wq[i]) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700158 CAM_ERR(CAM_CCI, "Failed to flush write wq");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800159 rc = -ENOMEM;
160 goto reset_complete_failed;
161 } else {
162 flush_workqueue(cci_dev->write_wq[i]);
163 }
164 }
165 cci_dev->cci_state = CCI_STATE_ENABLED;
166
167 return 0;
168
169reset_complete_failed:
Alok Pandey01b1b352017-06-25 20:38:54 +0530170 cam_soc_util_disable_platform_resource(soc_info, 1, 1);
171
172platform_enable_failed:
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800173 cci_dev->ref_count--;
174 cam_cpas_stop(cci_dev->cpas_handle);
175
176 return rc;
177}
178
179void cam_cci_soc_remove(struct platform_device *pdev,
180 struct cci_device *cci_dev)
181{
Alok Pandey01b1b352017-06-25 20:38:54 +0530182 struct cam_hw_soc_info *soc_info = &cci_dev->soc_info;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800183
Alok Pandey01b1b352017-06-25 20:38:54 +0530184 cam_soc_util_release_platform_resource(soc_info);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800185}
186
187static void cam_cci_init_cci_params(struct cci_device *new_cci_dev)
188{
189 uint8_t i = 0, j = 0;
190
191 for (i = 0; i < NUM_MASTERS; i++) {
192 new_cci_dev->cci_master_info[i].status = 0;
193 mutex_init(&new_cci_dev->cci_master_info[i].mutex);
194 init_completion(&new_cci_dev->
195 cci_master_info[i].reset_complete);
196
197 for (j = 0; j < NUM_QUEUES; j++) {
198 mutex_init(&new_cci_dev->cci_master_info[i].mutex_q[j]);
199 init_completion(&new_cci_dev->
200 cci_master_info[i].report_q[j]);
201 }
202 }
203}
204
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800205static void cam_cci_init_default_clk_params(struct cci_device *cci_dev,
206 uint8_t index)
207{
208 /* default clock params are for 100Khz */
209 cci_dev->cci_clk_params[index].hw_thigh = 201;
210 cci_dev->cci_clk_params[index].hw_tlow = 174;
211 cci_dev->cci_clk_params[index].hw_tsu_sto = 204;
212 cci_dev->cci_clk_params[index].hw_tsu_sta = 231;
213 cci_dev->cci_clk_params[index].hw_thd_dat = 22;
214 cci_dev->cci_clk_params[index].hw_thd_sta = 162;
215 cci_dev->cci_clk_params[index].hw_tbuf = 227;
216 cci_dev->cci_clk_params[index].hw_scl_stretch_en = 0;
217 cci_dev->cci_clk_params[index].hw_trdhld = 6;
218 cci_dev->cci_clk_params[index].hw_tsp = 3;
219 cci_dev->cci_clk_params[index].cci_clk_src = 37500000;
220}
221
222static void cam_cci_init_clk_params(struct cci_device *cci_dev)
223{
224 int32_t rc = 0;
225 uint32_t val = 0;
226 uint8_t count = 0;
227 struct device_node *of_node = cci_dev->v4l2_dev_str.pdev->dev.of_node;
228 struct device_node *src_node = NULL;
229
230 for (count = 0; count < I2C_MAX_MODES; count++) {
231
232 if (count == I2C_STANDARD_MODE)
233 src_node = of_find_node_by_name(of_node,
234 "qcom,i2c_standard_mode");
235 else if (count == I2C_FAST_MODE)
236 src_node = of_find_node_by_name(of_node,
237 "qcom,i2c_fast_mode");
238 else if (count == I2C_FAST_PLUS_MODE)
239 src_node = of_find_node_by_name(of_node,
240 "qcom,i2c_fast_plus_mode");
241 else
242 src_node = of_find_node_by_name(of_node,
243 "qcom,i2c_custom_mode");
244
Alok Pandey01b1b352017-06-25 20:38:54 +0530245 rc = of_property_read_u32(src_node, "hw-thigh", &val);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700246 CAM_DBG(CAM_CCI, "hw-thigh %d, rc %d", val, rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800247 if (!rc) {
248 cci_dev->cci_clk_params[count].hw_thigh = val;
Alok Pandey01b1b352017-06-25 20:38:54 +0530249 rc = of_property_read_u32(src_node, "hw-tlow",
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800250 &val);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700251 CAM_DBG(CAM_CCI, "hw-tlow %d, rc %d",
Alok Pandey01b1b352017-06-25 20:38:54 +0530252 val, rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800253 }
254 if (!rc) {
255 cci_dev->cci_clk_params[count].hw_tlow = val;
Alok Pandey01b1b352017-06-25 20:38:54 +0530256 rc = of_property_read_u32(src_node, "hw-tsu-sto",
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800257 &val);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700258 CAM_DBG(CAM_CCI, "hw-tsu-sto %d, rc %d",
259 val, rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800260 }
261 if (!rc) {
262 cci_dev->cci_clk_params[count].hw_tsu_sto = val;
Alok Pandey01b1b352017-06-25 20:38:54 +0530263 rc = of_property_read_u32(src_node, "hw-tsu-sta",
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800264 &val);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700265 CAM_DBG(CAM_CCI, "hw-tsu-sta %d, rc %d",
266 val, rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800267 }
268 if (!rc) {
269 cci_dev->cci_clk_params[count].hw_tsu_sta = val;
Alok Pandey01b1b352017-06-25 20:38:54 +0530270 rc = of_property_read_u32(src_node, "hw-thd-dat",
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800271 &val);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700272 CAM_DBG(CAM_CCI, "hw-thd-dat %d, rc %d",
273 val, rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800274 }
275 if (!rc) {
276 cci_dev->cci_clk_params[count].hw_thd_dat = val;
Alok Pandey01b1b352017-06-25 20:38:54 +0530277 rc = of_property_read_u32(src_node, "hw-thd-sta",
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800278 &val);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700279 CAM_DBG(CAM_CCI, "hw-thd-sta %d, rc %d",
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800280 val, rc);
281 }
282 if (!rc) {
283 cci_dev->cci_clk_params[count].hw_thd_sta = val;
Alok Pandey01b1b352017-06-25 20:38:54 +0530284 rc = of_property_read_u32(src_node, "hw-tbuf",
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800285 &val);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700286 CAM_DBG(CAM_CCI, "hw-tbuf %d, rc %d",
Alok Pandey01b1b352017-06-25 20:38:54 +0530287 val, rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800288 }
289 if (!rc) {
290 cci_dev->cci_clk_params[count].hw_tbuf = val;
291 rc = of_property_read_u32(src_node,
Alok Pandey01b1b352017-06-25 20:38:54 +0530292 "hw-scl-stretch-en", &val);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700293 CAM_DBG(CAM_CCI, "hw-scl-stretch-en %d, rc %d",
294 val, rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800295 }
296 if (!rc) {
297 cci_dev->cci_clk_params[count].hw_scl_stretch_en = val;
Alok Pandey01b1b352017-06-25 20:38:54 +0530298 rc = of_property_read_u32(src_node, "hw-trdhld",
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800299 &val);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700300 CAM_DBG(CAM_CCI, "hw-trdhld %d, rc %d",
301 val, rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800302 }
303 if (!rc) {
304 cci_dev->cci_clk_params[count].hw_trdhld = val;
Alok Pandey01b1b352017-06-25 20:38:54 +0530305 rc = of_property_read_u32(src_node, "hw-tsp",
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800306 &val);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700307 CAM_DBG(CAM_CCI, "hw-tsp %d, rc %d", val, rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800308 }
309 if (!rc) {
310 cci_dev->cci_clk_params[count].hw_tsp = val;
311 val = 0;
Alok Pandey01b1b352017-06-25 20:38:54 +0530312 rc = of_property_read_u32(src_node, "cci-clk-src",
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800313 &val);
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700314 CAM_DBG(CAM_CCI, "cci-clk-src %d, rc %d", val, rc);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800315 cci_dev->cci_clk_params[count].cci_clk_src = val;
316 } else
317 cam_cci_init_default_clk_params(cci_dev, count);
318
319 of_node_put(src_node);
320 }
321}
322
323int cam_cci_parse_dt_info(struct platform_device *pdev,
324 struct cci_device *new_cci_dev)
325{
326 int rc = 0, i = 0;
Alok Pandey01b1b352017-06-25 20:38:54 +0530327 struct cam_hw_soc_info *soc_info =
328 &new_cci_dev->soc_info;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800329
Alok Pandey01b1b352017-06-25 20:38:54 +0530330 rc = cam_soc_util_get_dt_properties(soc_info);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800331 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700332 CAM_ERR(CAM_CCI, "Parsing DT data failed:%d", rc);
Alok Pandey01b1b352017-06-25 20:38:54 +0530333 return -EINVAL;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800334 }
335
336 new_cci_dev->ref_count = 0;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800337
Alok Pandey01b1b352017-06-25 20:38:54 +0530338 rc = cam_soc_util_request_platform_resource(soc_info,
339 cam_cci_irq, new_cci_dev);
340 if (rc < 0) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700341 CAM_ERR(CAM_CCI, "requesting platform resources failed:%d", rc);
Alok Pandey01b1b352017-06-25 20:38:54 +0530342 return -EINVAL;
343 }
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800344 new_cci_dev->v4l2_dev_str.pdev = pdev;
345 cam_cci_init_cci_params(new_cci_dev);
346 cam_cci_init_clk_params(new_cci_dev);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800347
348 rc = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
349 if (rc)
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700350 CAM_ERR(CAM_CCI, "failed to add child nodes, rc=%d", rc);
Alok Pandey01b1b352017-06-25 20:38:54 +0530351
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800352 for (i = 0; i < MASTER_MAX; i++) {
353 new_cci_dev->write_wq[i] = create_singlethread_workqueue(
354 "cam_cci_wq");
355 if (!new_cci_dev->write_wq[i])
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700356 CAM_ERR(CAM_CCI, "Failed to create write wq");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800357 }
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700358 CAM_DBG(CAM_CCI, "Exit");
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800359 return 0;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800360}
361
362int cam_cci_soc_release(struct cci_device *cci_dev)
363{
364 uint8_t i = 0, rc = 0;
Alok Pandey01b1b352017-06-25 20:38:54 +0530365 struct cam_hw_soc_info *soc_info =
366 &cci_dev->soc_info;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800367
368 if (!cci_dev->ref_count || cci_dev->cci_state != CCI_STATE_ENABLED) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700369 CAM_ERR(CAM_CCI, "invalid ref count %d / cci state %d",
370 cci_dev->ref_count, cci_dev->cci_state);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800371 return -EINVAL;
372 }
373 if (--cci_dev->ref_count) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700374 CAM_DBG(CAM_CCI, "ref_count Exit %d", cci_dev->ref_count);
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800375 return 0;
376 }
377 for (i = 0; i < MASTER_MAX; i++)
378 if (cci_dev->write_wq[i])
379 flush_workqueue(cci_dev->write_wq[i]);
380
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800381 for (i = 0; i < MASTER_MAX; i++)
382 cci_dev->i2c_freq_mode[i] = I2C_MAX_MODES;
Alok Pandey01b1b352017-06-25 20:38:54 +0530383
384 rc = cam_soc_util_disable_platform_resource(soc_info, true, true);
385 if (rc) {
Jigarkumar Zalacbb5a382017-07-17 19:06:42 -0700386 CAM_ERR(CAM_CCI, "platform resources disable failed, rc=%d",
387 rc);
Alok Pandey01b1b352017-06-25 20:38:54 +0530388 return rc;
389 }
390
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800391 cci_dev->cci_state = CCI_STATE_DISABLED;
392 cci_dev->cycles_per_us = 0;
Alok Pandey01b1b352017-06-25 20:38:54 +0530393 soc_info->src_clk_idx = 0;
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800394
Viswanadha Raju Thotakura2e185a42017-08-24 18:32:54 -0700395 cam_cpas_stop(cci_dev->cpas_handle);
396
Viswanadha Raju Thotakura9a3795e2017-02-25 13:27:08 -0800397 return rc;
398}