blob: 0b1896fc9ed6fc8920d49f8926ab75e0069d6394 [file] [log] [blame]
Abhilash Kumar9f3f5122018-01-23 11:15:11 +05301/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
Harsh Shahbbe33742017-03-14 18:09:54 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
Harsh Shahbbe33742017-03-14 18:09:54 -070013#include <linux/of.h>
14#include <linux/clk.h>
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -070015#include <linux/slab.h>
16#include <linux/gpio.h>
17#include <linux/of_gpio.h>
Harsh Shahbbe33742017-03-14 18:09:54 -070018#include "cam_soc_util.h"
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -070019#include "cam_debug_util.h"
Harsh Shahbbe33742017-03-14 18:09:54 -070020
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -070021int cam_soc_util_get_level_from_string(const char *string,
22 enum cam_vote_level *level)
23{
24 if (!level)
25 return -EINVAL;
26
27 if (!strcmp(string, "suspend")) {
28 *level = CAM_SUSPEND_VOTE;
29 } else if (!strcmp(string, "minsvs")) {
30 *level = CAM_MINSVS_VOTE;
31 } else if (!strcmp(string, "lowsvs")) {
32 *level = CAM_LOWSVS_VOTE;
33 } else if (!strcmp(string, "svs")) {
34 *level = CAM_SVS_VOTE;
35 } else if (!strcmp(string, "svs_l1")) {
36 *level = CAM_SVSL1_VOTE;
37 } else if (!strcmp(string, "nominal")) {
38 *level = CAM_NOMINAL_VOTE;
39 } else if (!strcmp(string, "turbo")) {
40 *level = CAM_TURBO_VOTE;
41 } else {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -070042 CAM_ERR(CAM_UTIL, "Invalid string %s", string);
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -070043 return -EINVAL;
44 }
45
46 return 0;
47}
48
49/**
50 * cam_soc_util_get_clk_level_to_apply()
51 *
52 * @brief: Get the clock level to apply. If the requested level
53 * is not valid, bump the level to next available valid
54 * level. If no higher level found, return failure.
55 *
56 * @soc_info: Device soc struct to be populated
57 * @req_level: Requested level
58 * @apply_level Level to apply
59 *
60 * @return: success or failure
61 */
62static int cam_soc_util_get_clk_level_to_apply(
63 struct cam_hw_soc_info *soc_info, enum cam_vote_level req_level,
64 enum cam_vote_level *apply_level)
65{
66 if (req_level >= CAM_MAX_VOTE) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -070067 CAM_ERR(CAM_UTIL, "Invalid clock level parameter %d",
68 req_level);
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -070069 return -EINVAL;
70 }
71
72 if (soc_info->clk_level_valid[req_level] == true) {
73 *apply_level = req_level;
74 } else {
75 int i;
76
77 for (i = (req_level + 1); i < CAM_MAX_VOTE; i++)
78 if (soc_info->clk_level_valid[i] == true) {
79 *apply_level = i;
80 break;
81 }
82
83 if (i == CAM_MAX_VOTE) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -070084 CAM_ERR(CAM_UTIL,
85 "No valid clock level found to apply, req=%d",
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -070086 req_level);
87 return -EINVAL;
88 }
89 }
90
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -070091 CAM_DBG(CAM_UTIL, "Req level %d, Applying %d",
92 req_level, *apply_level);
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -070093
94 return 0;
95}
96
Harsh Shahbbe33742017-03-14 18:09:54 -070097int cam_soc_util_irq_enable(struct cam_hw_soc_info *soc_info)
98{
99 if (!soc_info) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700100 CAM_ERR(CAM_UTIL, "Invalid arguments");
Harsh Shahbbe33742017-03-14 18:09:54 -0700101 return -EINVAL;
102 }
103
104 if (!soc_info->irq_line) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700105 CAM_ERR(CAM_UTIL, "No IRQ line available");
Harsh Shahbbe33742017-03-14 18:09:54 -0700106 return -ENODEV;
107 }
108
109 enable_irq(soc_info->irq_line->start);
110
111 return 0;
112}
113
114int cam_soc_util_irq_disable(struct cam_hw_soc_info *soc_info)
115{
116 if (!soc_info) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700117 CAM_ERR(CAM_UTIL, "Invalid arguments");
Harsh Shahbbe33742017-03-14 18:09:54 -0700118 return -EINVAL;
119 }
120
121 if (!soc_info->irq_line) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700122 CAM_ERR(CAM_UTIL, "No IRQ line available");
Harsh Shahbbe33742017-03-14 18:09:54 -0700123 return -ENODEV;
124 }
125
126 disable_irq(soc_info->irq_line->start);
127
128 return 0;
129}
130
Pavan Kumar Chilamkurthia440b402017-07-27 13:37:20 -0700131long cam_soc_util_get_clk_round_rate(struct cam_hw_soc_info *soc_info,
132 uint32_t clk_index, unsigned long clk_rate)
133{
134 if (!soc_info || (clk_index >= soc_info->num_clk) || (clk_rate == 0)) {
Jigarkumar Zala3865c1c2017-11-28 12:08:50 -0800135 CAM_ERR(CAM_UTIL, "Invalid input params %pK, %d %lu",
Pavan Kumar Chilamkurthia440b402017-07-27 13:37:20 -0700136 soc_info, clk_index, clk_rate);
137 return clk_rate;
138 }
139
140 return clk_round_rate(soc_info->clk[clk_index], clk_rate);
141}
142
143int cam_soc_util_set_clk_flags(struct cam_hw_soc_info *soc_info,
144 uint32_t clk_index, unsigned long flags)
145{
146 if (!soc_info || (clk_index >= soc_info->num_clk)) {
147 CAM_ERR(CAM_UTIL, "Invalid input params %pK, %d",
148 soc_info, clk_index);
149 return -EINVAL;
150 }
151
152 return clk_set_flags(soc_info->clk[clk_index], flags);
153}
154
Alok Pandey01b1b352017-06-25 20:38:54 +0530155int cam_soc_util_set_clk_rate(struct clk *clk, const char *clk_name,
Harsh Shahbbe33742017-03-14 18:09:54 -0700156 int32_t clk_rate)
157{
158 int rc = 0;
159 long clk_rate_round;
160
Harsh Shahc3ac9b92017-03-27 15:03:47 -0700161 if (!clk || !clk_name)
Harsh Shahbbe33742017-03-14 18:09:54 -0700162 return -EINVAL;
163
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700164 CAM_DBG(CAM_UTIL, "set %s, rate %d", clk_name, clk_rate);
Harsh Shahbbe33742017-03-14 18:09:54 -0700165 if (clk_rate > 0) {
166 clk_rate_round = clk_round_rate(clk, clk_rate);
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700167 CAM_DBG(CAM_UTIL, "new_rate %ld", clk_rate_round);
Harsh Shahbbe33742017-03-14 18:09:54 -0700168 if (clk_rate_round < 0) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700169 CAM_ERR(CAM_UTIL, "round failed for clock %s rc = %ld",
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700170 clk_name, clk_rate_round);
Harsh Shahbbe33742017-03-14 18:09:54 -0700171 return clk_rate_round;
172 }
173 rc = clk_set_rate(clk, clk_rate_round);
174 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700175 CAM_ERR(CAM_UTIL, "set_rate failed on %s", clk_name);
Harsh Shahbbe33742017-03-14 18:09:54 -0700176 return rc;
177 }
178 } else if (clk_rate == INIT_RATE) {
179 clk_rate_round = clk_get_rate(clk);
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700180 CAM_DBG(CAM_UTIL, "init new_rate %ld", clk_rate_round);
Harsh Shahbbe33742017-03-14 18:09:54 -0700181 if (clk_rate_round == 0) {
182 clk_rate_round = clk_round_rate(clk, 0);
183 if (clk_rate_round <= 0) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700184 CAM_ERR(CAM_UTIL, "round rate failed on %s",
185 clk_name);
Harsh Shahbbe33742017-03-14 18:09:54 -0700186 return clk_rate_round;
187 }
188 }
189 rc = clk_set_rate(clk, clk_rate_round);
190 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700191 CAM_ERR(CAM_UTIL, "set_rate failed on %s", clk_name);
Harsh Shahbbe33742017-03-14 18:09:54 -0700192 return rc;
193 }
194 }
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700195
196 return rc;
197}
198
Harsh Shahb81eb442017-10-27 00:05:11 -0700199int cam_soc_util_clk_put(struct clk **clk)
200{
201 if (!(*clk)) {
202 CAM_ERR(CAM_UTIL, "Invalid params clk");
203 return -EINVAL;
204 }
205
206 clk_put(*clk);
207 *clk = NULL;
208
209 return 0;
210}
211
212static struct clk *cam_soc_util_option_clk_get(struct device_node *np,
213 int index)
214{
215 struct of_phandle_args clkspec;
216 struct clk *clk;
217 int rc;
218
219 if (index < 0)
220 return ERR_PTR(-EINVAL);
221
222 rc = of_parse_phandle_with_args(np, "clocks-option", "#clock-cells",
223 index, &clkspec);
224 if (rc)
225 return ERR_PTR(rc);
226
227 clk = of_clk_get_from_provider(&clkspec);
228 of_node_put(clkspec.np);
229
230 return clk;
231}
232
233int cam_soc_util_get_option_clk_by_name(struct cam_hw_soc_info *soc_info,
234 const char *clk_name, struct clk **clk, int32_t *clk_index,
235 int32_t *clk_rate)
236{
237 int index = 0;
238 int rc = 0;
239 struct device_node *of_node = NULL;
240
241 if (!soc_info || !clk_name || !clk) {
242 CAM_ERR(CAM_UTIL,
243 "Invalid params soc_info %pK clk_name %s clk %pK",
244 soc_info, clk_name, clk);
245 return -EINVAL;
246 }
247
248 of_node = soc_info->dev->of_node;
249
250 index = of_property_match_string(of_node, "clock-names-option",
251 clk_name);
252
253 *clk = cam_soc_util_option_clk_get(of_node, index);
254 if (IS_ERR(*clk)) {
255 CAM_ERR(CAM_UTIL, "No clk named %s found. Dev %s", clk_name,
256 soc_info->dev_name);
257 *clk_index = -1;
258 return -EFAULT;
259 }
260 *clk_index = index;
261
262 rc = of_property_read_u32_index(of_node, "clock-rates-option",
263 index, clk_rate);
264 if (rc) {
265 CAM_ERR(CAM_UTIL,
266 "Error reading clock-rates clk_name %s index %d",
267 clk_name, index);
268 cam_soc_util_clk_put(clk);
269 *clk_rate = 0;
270 return rc;
271 }
272
273 /*
274 * Option clocks are assumed to be available to single Device here.
275 * Hence use INIT_RATE instead of NO_SET_RATE.
276 */
277 *clk_rate = (*clk_rate == 0) ? (int32_t)INIT_RATE : *clk_rate;
278
279 CAM_DBG(CAM_UTIL, "clk_name %s index %d clk_rate %d",
280 clk_name, *clk_index, *clk_rate);
281
282 return 0;
283}
284
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700285int cam_soc_util_clk_enable(struct clk *clk, const char *clk_name,
286 int32_t clk_rate)
287{
288 int rc = 0;
289
290 if (!clk || !clk_name)
291 return -EINVAL;
292
293 rc = cam_soc_util_set_clk_rate(clk, clk_name, clk_rate);
294 if (rc)
295 return rc;
296
Harsh Shahbbe33742017-03-14 18:09:54 -0700297 rc = clk_prepare_enable(clk);
298 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700299 CAM_ERR(CAM_UTIL, "enable failed for %s: rc(%d)", clk_name, rc);
Harsh Shahbbe33742017-03-14 18:09:54 -0700300 return rc;
301 }
302
303 return rc;
304}
305
306int cam_soc_util_clk_disable(struct clk *clk, const char *clk_name)
307{
308 if (!clk || !clk_name)
309 return -EINVAL;
310
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700311 CAM_DBG(CAM_UTIL, "disable %s", clk_name);
Harsh Shahbbe33742017-03-14 18:09:54 -0700312 clk_disable_unprepare(clk);
313
314 return 0;
315}
316
317/**
318 * cam_soc_util_clk_enable_default()
319 *
320 * @brief: This function enables the default clocks present
321 * in soc_info
322 *
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700323 * @soc_info: Device soc struct to be populated
324 * @clk_level: Clk level to apply while enabling
Harsh Shahbbe33742017-03-14 18:09:54 -0700325 *
326 * @return: success or failure
327 */
Junzhe Zoubc37c562017-11-20 18:23:49 -0800328int cam_soc_util_clk_enable_default(struct cam_hw_soc_info *soc_info,
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700329 enum cam_vote_level clk_level)
Harsh Shahbbe33742017-03-14 18:09:54 -0700330{
331 int i, rc = 0;
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700332 enum cam_vote_level apply_level;
Harsh Shahbbe33742017-03-14 18:09:54 -0700333
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700334 if ((soc_info->num_clk == 0) ||
335 (soc_info->num_clk >= CAM_SOC_MAX_CLK)) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700336 CAM_ERR(CAM_UTIL, "Invalid number of clock %d",
337 soc_info->num_clk);
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700338 return -EINVAL;
339 }
340
341 rc = cam_soc_util_get_clk_level_to_apply(soc_info, clk_level,
342 &apply_level);
343 if (rc)
Harsh Shahbbe33742017-03-14 18:09:54 -0700344 return rc;
345
346 for (i = 0; i < soc_info->num_clk; i++) {
347 rc = cam_soc_util_clk_enable(soc_info->clk[i],
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700348 soc_info->clk_name[i],
349 soc_info->clk_rate[apply_level][i]);
Harsh Shahbbe33742017-03-14 18:09:54 -0700350 if (rc)
351 goto clk_disable;
352 }
353
354 return rc;
355
356clk_disable:
357 for (i--; i >= 0; i--) {
358 cam_soc_util_clk_disable(soc_info->clk[i],
359 soc_info->clk_name[i]);
360 }
361
362 return rc;
363}
364
365/**
366 * cam_soc_util_clk_disable_default()
367 *
368 * @brief: This function disables the default clocks present
369 * in soc_info
370 *
371 * @soc_info: device soc struct to be populated
372 *
373 * @return: success or failure
374 */
Junzhe Zoubc37c562017-11-20 18:23:49 -0800375void cam_soc_util_clk_disable_default(struct cam_hw_soc_info *soc_info)
Harsh Shahbbe33742017-03-14 18:09:54 -0700376{
377 int i;
378
379 if (soc_info->num_clk == 0)
380 return;
381
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700382 for (i = soc_info->num_clk - 1; i >= 0; i--)
Harsh Shahbbe33742017-03-14 18:09:54 -0700383 cam_soc_util_clk_disable(soc_info->clk[i],
384 soc_info->clk_name[i]);
Harsh Shahbbe33742017-03-14 18:09:54 -0700385}
386
387/**
388 * cam_soc_util_get_dt_clk_info()
389 *
390 * @brief: Parse the DT and populate the Clock properties
391 *
392 * @soc_info: device soc struct to be populated
393 * @src_clk_str name of src clock that has rate control
394 *
395 * @return: success or failure
396 */
397static int cam_soc_util_get_dt_clk_info(struct cam_hw_soc_info *soc_info)
398{
399 struct device_node *of_node = NULL;
400 int count;
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700401 int num_clk_rates, num_clk_levels;
402 int i, j, rc;
403 int32_t num_clk_level_strings;
Harsh Shahbbe33742017-03-14 18:09:54 -0700404 const char *src_clk_str = NULL;
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700405 const char *clk_cntl_lvl_string = NULL;
406 enum cam_vote_level level;
Harsh Shahbbe33742017-03-14 18:09:54 -0700407
Jigarkumar Zalaae152332017-07-18 17:21:48 -0700408 if (!soc_info || !soc_info->dev)
Harsh Shahbbe33742017-03-14 18:09:54 -0700409 return -EINVAL;
410
Jigarkumar Zalaae152332017-07-18 17:21:48 -0700411 of_node = soc_info->dev->of_node;
Harsh Shahbbe33742017-03-14 18:09:54 -0700412
Depeng Shaof3b03fa2017-11-15 19:46:09 +0800413 if (!of_property_read_bool(of_node, "use-shared-clk")) {
414 CAM_DBG(CAM_UTIL, "No shared clk parameter defined");
415 soc_info->use_shared_clk = false;
416 } else {
417 soc_info->use_shared_clk = true;
418 }
419
Harsh Shahbbe33742017-03-14 18:09:54 -0700420 count = of_property_count_strings(of_node, "clock-names");
421
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700422 CAM_DBG(CAM_UTIL, "count = %d", count);
Harsh Shahbbe33742017-03-14 18:09:54 -0700423 if (count > CAM_SOC_MAX_CLK) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700424 CAM_ERR(CAM_UTIL, "invalid count of clocks, count=%d", count);
Harsh Shahbbe33742017-03-14 18:09:54 -0700425 rc = -EINVAL;
426 return rc;
427 }
428 if (count <= 0) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700429 CAM_DBG(CAM_UTIL, "No clock-names found");
Harsh Shahbbe33742017-03-14 18:09:54 -0700430 count = 0;
431 soc_info->num_clk = count;
432 return 0;
433 }
434 soc_info->num_clk = count;
435
436 for (i = 0; i < count; i++) {
437 rc = of_property_read_string_index(of_node, "clock-names",
438 i, &(soc_info->clk_name[i]));
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700439 CAM_DBG(CAM_UTIL, "clock-names[%d] = %s",
440 i, soc_info->clk_name[i]);
Harsh Shahbbe33742017-03-14 18:09:54 -0700441 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700442 CAM_ERR(CAM_UTIL,
443 "i= %d count= %d reading clock-names failed",
Harsh Shahbbe33742017-03-14 18:09:54 -0700444 i, count);
445 return rc;
446 }
447 }
448
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700449 num_clk_rates = of_property_count_u32_elems(of_node, "clock-rates");
450 if (num_clk_rates <= 0) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700451 CAM_ERR(CAM_UTIL, "reading clock-rates count failed");
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700452 return -EINVAL;
Harsh Shahbbe33742017-03-14 18:09:54 -0700453 }
454
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700455 if ((num_clk_rates % soc_info->num_clk) != 0) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700456 CAM_ERR(CAM_UTIL,
457 "mismatch clk/rates, No of clocks=%d, No of rates=%d",
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700458 soc_info->num_clk, num_clk_rates);
459 return -EINVAL;
460 }
461
462 num_clk_levels = (num_clk_rates / soc_info->num_clk);
463
464 num_clk_level_strings = of_property_count_strings(of_node,
465 "clock-cntl-level");
466 if (num_clk_level_strings != num_clk_levels) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700467 CAM_ERR(CAM_UTIL,
468 "Mismatch No of levels=%d, No of level string=%d",
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700469 num_clk_levels, num_clk_level_strings);
470 return -EINVAL;
471 }
472
473 for (i = 0; i < num_clk_levels; i++) {
474 rc = of_property_read_string_index(of_node,
475 "clock-cntl-level", i, &clk_cntl_lvl_string);
476 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700477 CAM_ERR(CAM_UTIL,
478 "Error reading clock-cntl-level, rc=%d", rc);
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700479 return rc;
480 }
481
482 rc = cam_soc_util_get_level_from_string(clk_cntl_lvl_string,
483 &level);
484 if (rc)
485 return rc;
486
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700487 CAM_DBG(CAM_UTIL,
488 "[%d] : %s %d", i, clk_cntl_lvl_string, level);
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700489 soc_info->clk_level_valid[level] = true;
490 for (j = 0; j < soc_info->num_clk; j++) {
491 rc = of_property_read_u32_index(of_node, "clock-rates",
492 ((i * soc_info->num_clk) + j),
493 &soc_info->clk_rate[level][j]);
494 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700495 CAM_ERR(CAM_UTIL,
496 "Error reading clock-rates, rc=%d",
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700497 rc);
498 return rc;
499 }
500
501 soc_info->clk_rate[level][j] =
502 (soc_info->clk_rate[level][j] == 0) ?
Harsh Shahb81eb442017-10-27 00:05:11 -0700503 (int32_t)NO_SET_RATE :
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700504 soc_info->clk_rate[level][j];
505
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700506 CAM_DBG(CAM_UTIL, "soc_info->clk_rate[%d][%d] = %d",
507 level, j,
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700508 soc_info->clk_rate[level][j]);
509 }
510 }
511
512 soc_info->src_clk_idx = -1;
Harsh Shahc3ac9b92017-03-27 15:03:47 -0700513 rc = of_property_read_string_index(of_node, "src-clock-name", 0,
514 &src_clk_str);
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700515 if (rc || !src_clk_str) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700516 CAM_DBG(CAM_UTIL, "No src_clk_str found");
Harsh Shahbbe33742017-03-14 18:09:54 -0700517 rc = 0;
518 /* Bottom loop is dependent on src_clk_str. So return here */
519 return rc;
520 }
521
522 for (i = 0; i < soc_info->num_clk; i++) {
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700523 if (strcmp(soc_info->clk_name[i], src_clk_str) == 0) {
Harsh Shahbbe33742017-03-14 18:09:54 -0700524 soc_info->src_clk_idx = i;
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700525 CAM_DBG(CAM_UTIL, "src clock = %s, index = %d",
526 src_clk_str, i);
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700527 break;
Harsh Shahbbe33742017-03-14 18:09:54 -0700528 }
Harsh Shahbbe33742017-03-14 18:09:54 -0700529 }
530
531 return rc;
532}
533
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700534int cam_soc_util_set_clk_rate_level(struct cam_hw_soc_info *soc_info,
535 enum cam_vote_level clk_level)
536{
537 int i, rc = 0;
538 enum cam_vote_level apply_level;
539
540 if ((soc_info->num_clk == 0) ||
541 (soc_info->num_clk >= CAM_SOC_MAX_CLK)) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700542 CAM_ERR(CAM_UTIL, "Invalid number of clock %d",
543 soc_info->num_clk);
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -0700544 return -EINVAL;
545 }
546
547 rc = cam_soc_util_get_clk_level_to_apply(soc_info, clk_level,
548 &apply_level);
549 if (rc)
550 return rc;
551
552 for (i = 0; i < soc_info->num_clk; i++) {
553 rc = cam_soc_util_set_clk_rate(soc_info->clk[i],
554 soc_info->clk_name[i],
555 soc_info->clk_rate[apply_level][i]);
556 if (rc)
557 break;
558 }
559
560 return rc;
561};
562
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700563static int cam_soc_util_get_dt_gpio_req_tbl(struct device_node *of_node,
564 struct cam_soc_gpio_data *gconf, uint16_t *gpio_array,
565 uint16_t gpio_array_size)
566{
567 int32_t rc = 0, i = 0;
568 uint32_t count = 0;
569 uint32_t *val_array = NULL;
570
571 if (!of_get_property(of_node, "gpio-req-tbl-num", &count))
572 return 0;
573
574 count /= sizeof(uint32_t);
575 if (!count) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700576 CAM_ERR(CAM_UTIL, "gpio-req-tbl-num 0");
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700577 return 0;
578 }
579
580 val_array = kcalloc(count, sizeof(uint32_t), GFP_KERNEL);
581 if (!val_array)
582 return -ENOMEM;
583
584 gconf->cam_gpio_req_tbl = kcalloc(count, sizeof(struct gpio),
585 GFP_KERNEL);
586 if (!gconf->cam_gpio_req_tbl) {
587 rc = -ENOMEM;
588 goto free_val_array;
589 }
590 gconf->cam_gpio_req_tbl_size = count;
591
592 rc = of_property_read_u32_array(of_node, "gpio-req-tbl-num",
593 val_array, count);
594 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700595 CAM_ERR(CAM_UTIL, "failed in reading gpio-req-tbl-num, rc = %d",
596 rc);
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700597 goto free_gpio_req_tbl;
598 }
599
600 for (i = 0; i < count; i++) {
601 if (val_array[i] >= gpio_array_size) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700602 CAM_ERR(CAM_UTIL, "gpio req tbl index %d invalid",
603 val_array[i]);
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700604 goto free_gpio_req_tbl;
605 }
606 gconf->cam_gpio_req_tbl[i].gpio = gpio_array[val_array[i]];
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700607 CAM_DBG(CAM_UTIL, "cam_gpio_req_tbl[%d].gpio = %d", i,
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700608 gconf->cam_gpio_req_tbl[i].gpio);
609 }
610
611 rc = of_property_read_u32_array(of_node, "gpio-req-tbl-flags",
612 val_array, count);
613 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700614 CAM_ERR(CAM_UTIL, "Failed in gpio-req-tbl-flags, rc %d", rc);
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700615 goto free_gpio_req_tbl;
616 }
617
618 for (i = 0; i < count; i++) {
619 gconf->cam_gpio_req_tbl[i].flags = val_array[i];
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700620 CAM_DBG(CAM_UTIL, "cam_gpio_req_tbl[%d].flags = %ld", i,
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700621 gconf->cam_gpio_req_tbl[i].flags);
622 }
623
624 for (i = 0; i < count; i++) {
625 rc = of_property_read_string_index(of_node,
626 "gpio-req-tbl-label", i,
627 &gconf->cam_gpio_req_tbl[i].label);
628 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700629 CAM_ERR(CAM_UTIL, "Failed rc %d", rc);
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700630 goto free_gpio_req_tbl;
631 }
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700632 CAM_DBG(CAM_UTIL, "cam_gpio_req_tbl[%d].label = %s", i,
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700633 gconf->cam_gpio_req_tbl[i].label);
634 }
635
636 kfree(val_array);
637
638 return rc;
639
640free_gpio_req_tbl:
641 kfree(gconf->cam_gpio_req_tbl);
642free_val_array:
643 kfree(val_array);
644 gconf->cam_gpio_req_tbl_size = 0;
645
646 return rc;
647}
648
649static int cam_soc_util_get_gpio_info(struct cam_hw_soc_info *soc_info)
650{
651 int32_t rc = 0, i = 0;
652 uint16_t *gpio_array = NULL;
653 int16_t gpio_array_size = 0;
654 struct cam_soc_gpio_data *gconf = NULL;
655 struct device_node *of_node = NULL;
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700656
Jigarkumar Zalaae152332017-07-18 17:21:48 -0700657 if (!soc_info || !soc_info->dev)
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700658 return -EINVAL;
659
Jigarkumar Zalaae152332017-07-18 17:21:48 -0700660 of_node = soc_info->dev->of_node;
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700661
662 /* Validate input parameters */
663 if (!of_node) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700664 CAM_ERR(CAM_UTIL, "Invalid param of_node");
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700665 return -EINVAL;
666 }
667
668 gpio_array_size = of_gpio_count(of_node);
669
670 if (gpio_array_size <= 0)
671 return 0;
672
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700673 CAM_DBG(CAM_UTIL, "gpio count %d", gpio_array_size);
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700674
675 gpio_array = kcalloc(gpio_array_size, sizeof(uint16_t), GFP_KERNEL);
676 if (!gpio_array)
677 goto free_gpio_conf;
678
679 for (i = 0; i < gpio_array_size; i++) {
680 gpio_array[i] = of_get_gpio(of_node, i);
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700681 CAM_DBG(CAM_UTIL, "gpio_array[%d] = %d", i, gpio_array[i]);
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700682 }
683
684 gconf = kzalloc(sizeof(*gconf), GFP_KERNEL);
685 if (!gconf)
686 return -ENOMEM;
687
688 rc = cam_soc_util_get_dt_gpio_req_tbl(of_node, gconf, gpio_array,
689 gpio_array_size);
690 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700691 CAM_ERR(CAM_UTIL, "failed in msm_camera_get_dt_gpio_req_tbl");
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700692 goto free_gpio_array;
693 }
694
695 gconf->cam_gpio_common_tbl = kcalloc(gpio_array_size,
696 sizeof(struct gpio), GFP_KERNEL);
697 if (!gconf->cam_gpio_common_tbl) {
698 rc = -ENOMEM;
699 goto free_gpio_array;
700 }
701
Soundrapandian Jeyaprakash37f206c2017-07-12 11:27:16 -0700702 for (i = 0; i < gpio_array_size; i++)
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700703 gconf->cam_gpio_common_tbl[i].gpio = gpio_array[i];
704
705 gconf->cam_gpio_common_tbl_size = gpio_array_size;
706 soc_info->gpio_data = gconf;
707 kfree(gpio_array);
708
709 return rc;
710
711free_gpio_array:
712 kfree(gpio_array);
713free_gpio_conf:
714 kfree(gconf);
715 soc_info->gpio_data = NULL;
716
717 return rc;
718}
719
720static int cam_soc_util_request_gpio_table(
721 struct cam_hw_soc_info *soc_info, bool gpio_en)
722{
723 int rc = 0, i = 0;
724 uint8_t size = 0;
725 struct cam_soc_gpio_data *gpio_conf =
726 soc_info->gpio_data;
727 struct gpio *gpio_tbl = NULL;
728
729
730 if (!gpio_conf) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700731 CAM_DBG(CAM_UTIL, "No GPIO entry");
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700732 return 0;
733 }
734 if (gpio_conf->cam_gpio_common_tbl_size <= 0) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700735 CAM_ERR(CAM_UTIL, "GPIO table size is invalid");
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700736 return -EINVAL;
737 }
738 size = gpio_conf->cam_gpio_req_tbl_size;
739 gpio_tbl = gpio_conf->cam_gpio_req_tbl;
740
741 if (!gpio_tbl || !size) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700742 CAM_ERR(CAM_UTIL, "Invalid gpio_tbl %pK / size %d",
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700743 gpio_tbl, size);
744 return -EINVAL;
745 }
746 for (i = 0; i < size; i++) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700747 CAM_DBG(CAM_UTIL, "i=%d, gpio=%d dir=%ld", i,
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700748 gpio_tbl[i].gpio, gpio_tbl[i].flags);
749 }
750 if (gpio_en) {
751 for (i = 0; i < size; i++) {
752 rc = gpio_request_one(gpio_tbl[i].gpio,
753 gpio_tbl[i].flags, gpio_tbl[i].label);
754 if (rc) {
755 /*
756 * After GPIO request fails, contine to
757 * apply new gpios, outout a error message
758 * for driver bringup debug
759 */
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700760 CAM_ERR(CAM_UTIL, "gpio %d:%s request fails",
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700761 gpio_tbl[i].gpio, gpio_tbl[i].label);
762 }
763 }
764 } else {
765 gpio_free_array(gpio_tbl, size);
766 }
767
768 return rc;
769}
770
771static int cam_soc_util_get_dt_regulator_info
772 (struct cam_hw_soc_info *soc_info)
773{
774 int rc = 0, count = 0, i = 0;
775 struct device_node *of_node = NULL;
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700776
Jigarkumar Zalaae152332017-07-18 17:21:48 -0700777 if (!soc_info || !soc_info->dev) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700778 CAM_ERR(CAM_UTIL, "Invalid parameters");
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700779 return -EINVAL;
780 }
781
Jigarkumar Zalaae152332017-07-18 17:21:48 -0700782 of_node = soc_info->dev->of_node;
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700783
784 soc_info->num_rgltr = 0;
785 count = of_property_count_strings(of_node, "regulator-names");
786 if (count != -EINVAL) {
787 if (count <= 0) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700788 CAM_ERR(CAM_UTIL, "no regulators found");
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700789 count = 0;
790 return -EINVAL;
791 }
792
793 soc_info->num_rgltr = count;
794
795 } else {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700796 CAM_DBG(CAM_UTIL, "No regulators node found");
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700797 return 0;
798 }
799
800 for (i = 0; i < soc_info->num_rgltr; i++) {
801 rc = of_property_read_string_index(of_node,
802 "regulator-names", i, &soc_info->rgltr_name[i]);
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700803 CAM_DBG(CAM_UTIL, "rgltr_name[%d] = %s",
804 i, soc_info->rgltr_name[i]);
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700805 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700806 CAM_ERR(CAM_UTIL, "no regulator resource at cnt=%d", i);
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700807 return -ENODEV;
808 }
809 }
810
811 if (!of_property_read_bool(of_node, "rgltr-cntrl-support")) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700812 CAM_DBG(CAM_UTIL, "No regulator control parameter defined");
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700813 soc_info->rgltr_ctrl_support = false;
814 return 0;
815 }
816
817 soc_info->rgltr_ctrl_support = true;
818
819 rc = of_property_read_u32_array(of_node, "rgltr-min-voltage",
820 soc_info->rgltr_min_volt, soc_info->num_rgltr);
821 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700822 CAM_ERR(CAM_UTIL, "No minimum volatage value found, rc=%d", rc);
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700823 return -EINVAL;
824 }
825
826 rc = of_property_read_u32_array(of_node, "rgltr-max-voltage",
827 soc_info->rgltr_max_volt, soc_info->num_rgltr);
828 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700829 CAM_ERR(CAM_UTIL, "No maximum volatage value found, rc=%d", rc);
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700830 return -EINVAL;
831 }
832
833 rc = of_property_read_u32_array(of_node, "rgltr-load-current",
834 soc_info->rgltr_op_mode, soc_info->num_rgltr);
835 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700836 CAM_ERR(CAM_UTIL, "No Load curent found rc=%d", rc);
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700837 return -EINVAL;
838 }
839
840 return rc;
841}
842
Harsh Shahbbe33742017-03-14 18:09:54 -0700843int cam_soc_util_get_dt_properties(struct cam_hw_soc_info *soc_info)
844{
845 struct device_node *of_node = NULL;
846 int count = 0, i = 0, rc = 0;
Harsh Shahbbe33742017-03-14 18:09:54 -0700847
Jigarkumar Zalab7b49f12017-08-21 16:45:38 -0700848 if (!soc_info || !soc_info->dev)
Harsh Shahbbe33742017-03-14 18:09:54 -0700849 return -EINVAL;
850
Jigarkumar Zalaae152332017-07-18 17:21:48 -0700851 of_node = soc_info->dev->of_node;
Harsh Shahbbe33742017-03-14 18:09:54 -0700852
Pavan Kumar Chilamkurthi1d3ed352017-05-12 14:54:04 -0700853 rc = of_property_read_u32(of_node, "cell-index", &soc_info->index);
Harsh Shahbbe33742017-03-14 18:09:54 -0700854 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700855 CAM_ERR(CAM_UTIL, "device %s failed to read cell-index",
Jigarkumar Zalaae152332017-07-18 17:21:48 -0700856 soc_info->dev_name);
Harsh Shahbbe33742017-03-14 18:09:54 -0700857 return rc;
858 }
Jigarkumar Zalaae152332017-07-18 17:21:48 -0700859
Harsh Shahbbe33742017-03-14 18:09:54 -0700860 count = of_property_count_strings(of_node, "reg-names");
861 if (count <= 0) {
Abhilash Kumar9f3f5122018-01-23 11:15:11 +0530862 CAM_DBG(CAM_UTIL, "no reg-names found for: %s",
Jigarkumar Zala0a740242017-10-19 17:23:55 -0700863 soc_info->dev_name);
Harsh Shahbbe33742017-03-14 18:09:54 -0700864 count = 0;
865 }
866 soc_info->num_mem_block = count;
867
868 for (i = 0; i < soc_info->num_mem_block; i++) {
869 rc = of_property_read_string_index(of_node, "reg-names", i,
870 &soc_info->mem_block_name[i]);
871 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700872 CAM_ERR(CAM_UTIL, "failed to read reg-names at %d", i);
Harsh Shahbbe33742017-03-14 18:09:54 -0700873 return rc;
874 }
875 soc_info->mem_block[i] =
Jigarkumar Zalab7b49f12017-08-21 16:45:38 -0700876 platform_get_resource_byname(soc_info->pdev,
877 IORESOURCE_MEM, soc_info->mem_block_name[i]);
Harsh Shahbbe33742017-03-14 18:09:54 -0700878
879 if (!soc_info->mem_block[i]) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700880 CAM_ERR(CAM_UTIL, "no mem resource by name %s",
Harsh Shahbbe33742017-03-14 18:09:54 -0700881 soc_info->mem_block_name[i]);
882 rc = -ENODEV;
883 return rc;
884 }
885 }
886
Pavan Kumar Chilamkurthi1d3ed352017-05-12 14:54:04 -0700887 if (soc_info->num_mem_block > 0) {
888 rc = of_property_read_u32_array(of_node, "reg-cam-base",
889 soc_info->mem_block_cam_base, soc_info->num_mem_block);
890 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700891 CAM_ERR(CAM_UTIL, "Error reading register offsets");
Pavan Kumar Chilamkurthi1d3ed352017-05-12 14:54:04 -0700892 return rc;
893 }
Harsh Shahbbe33742017-03-14 18:09:54 -0700894 }
895
896 rc = of_property_read_string_index(of_node, "interrupt-names", 0,
897 &soc_info->irq_name);
898 if (rc) {
Abhilash Kumar9f3f5122018-01-23 11:15:11 +0530899 CAM_DBG(CAM_UTIL, "No interrupt line preset for: %s",
Jigarkumar Zala0a740242017-10-19 17:23:55 -0700900 soc_info->dev_name);
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700901 rc = 0;
Harsh Shahbbe33742017-03-14 18:09:54 -0700902 } else {
Jigarkumar Zalab7b49f12017-08-21 16:45:38 -0700903 soc_info->irq_line =
904 platform_get_resource_byname(soc_info->pdev,
Harsh Shahbbe33742017-03-14 18:09:54 -0700905 IORESOURCE_IRQ, soc_info->irq_name);
906 if (!soc_info->irq_line) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700907 CAM_ERR(CAM_UTIL, "no irq resource");
Harsh Shahbbe33742017-03-14 18:09:54 -0700908 rc = -ENODEV;
909 return rc;
910 }
911 }
912
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700913 rc = cam_soc_util_get_dt_regulator_info(soc_info);
914 if (rc)
915 return rc;
916
Harsh Shahbbe33742017-03-14 18:09:54 -0700917 rc = cam_soc_util_get_dt_clk_info(soc_info);
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700918 if (rc)
919 return rc;
920
921 rc = cam_soc_util_get_gpio_info(soc_info);
922 if (rc)
923 return rc;
Harsh Shahbbe33742017-03-14 18:09:54 -0700924
925 return rc;
926}
927
928/**
929 * cam_soc_util_get_regulator()
930 *
931 * @brief: Get regulator resource named vdd
932 *
Jigarkumar Zalab7b49f12017-08-21 16:45:38 -0700933 * @dev: Device associated with regulator
Harsh Shahbbe33742017-03-14 18:09:54 -0700934 * @reg: Return pointer to be filled with regulator on success
935 * @rgltr_name: Name of regulator to get
936 *
937 * @return: 0 for Success, negative value for failure
938 */
Jigarkumar Zalaae152332017-07-18 17:21:48 -0700939static int cam_soc_util_get_regulator(struct device *dev,
Harsh Shahbbe33742017-03-14 18:09:54 -0700940 struct regulator **reg, const char *rgltr_name)
941{
942 int rc = 0;
Jigarkumar Zalaae152332017-07-18 17:21:48 -0700943 *reg = regulator_get(dev, rgltr_name);
Harsh Shahbbe33742017-03-14 18:09:54 -0700944 if (IS_ERR_OR_NULL(*reg)) {
945 rc = PTR_ERR(*reg);
946 rc = rc ? rc : -EINVAL;
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700947 CAM_ERR(CAM_UTIL, "Regulator %s get failed %d", rgltr_name, rc);
Harsh Shahbbe33742017-03-14 18:09:54 -0700948 *reg = NULL;
949 }
950 return rc;
951}
952
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700953int cam_soc_util_regulator_disable(struct regulator *rgltr,
954 const char *rgltr_name, uint32_t rgltr_min_volt,
955 uint32_t rgltr_max_volt, uint32_t rgltr_op_mode,
956 uint32_t rgltr_delay_ms)
957{
958 int32_t rc = 0;
959
960 if (!rgltr) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700961 CAM_ERR(CAM_UTIL, "Invalid NULL parameter");
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700962 return -EINVAL;
963 }
964
965 rc = regulator_disable(rgltr);
966 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700967 CAM_ERR(CAM_UTIL, "%s regulator disable failed", rgltr_name);
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700968 return rc;
969 }
970
971 if (rgltr_delay_ms > 20)
972 msleep(rgltr_delay_ms);
973 else if (rgltr_delay_ms)
974 usleep_range(rgltr_delay_ms * 1000,
975 (rgltr_delay_ms * 1000) + 1000);
976
977 if (regulator_count_voltages(rgltr) > 0) {
978 regulator_set_load(rgltr, 0);
979 regulator_set_voltage(rgltr, 0, rgltr_max_volt);
980 }
981
982 return rc;
983}
984
985
986int cam_soc_util_regulator_enable(struct regulator *rgltr,
987 const char *rgltr_name,
988 uint32_t rgltr_min_volt, uint32_t rgltr_max_volt,
989 uint32_t rgltr_op_mode, uint32_t rgltr_delay)
990{
991 int32_t rc = 0;
992
993 if (!rgltr) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700994 CAM_ERR(CAM_UTIL, "Invalid NULL parameter");
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -0700995 return -EINVAL;
996 }
997
998 if (regulator_count_voltages(rgltr) > 0) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -0700999 CAM_DBG(CAM_UTIL, "voltage min=%d, max=%d",
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001000 rgltr_min_volt, rgltr_max_volt);
1001
1002 rc = regulator_set_voltage(
1003 rgltr, rgltr_min_volt, rgltr_max_volt);
1004 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -07001005 CAM_ERR(CAM_UTIL, "%s set voltage failed", rgltr_name);
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001006 return rc;
1007 }
1008
1009 rc = regulator_set_load(rgltr, rgltr_op_mode);
1010 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -07001011 CAM_ERR(CAM_UTIL, "%s set optimum mode failed",
1012 rgltr_name);
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001013 return rc;
1014 }
1015 }
1016
1017 rc = regulator_enable(rgltr);
1018 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -07001019 CAM_ERR(CAM_UTIL, "%s regulator_enable failed", rgltr_name);
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001020 return rc;
1021 }
1022
1023 if (rgltr_delay > 20)
1024 msleep(rgltr_delay);
1025 else if (rgltr_delay)
1026 usleep_range(rgltr_delay * 1000,
1027 (rgltr_delay * 1000) + 1000);
1028
1029 return rc;
1030}
1031
1032static int cam_soc_util_request_pinctrl(
1033 struct cam_hw_soc_info *soc_info) {
1034
1035 struct cam_soc_pinctrl_info *device_pctrl = &soc_info->pinctrl_info;
Jigarkumar Zalaae152332017-07-18 17:21:48 -07001036 struct device *dev = soc_info->dev;
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001037
1038 device_pctrl->pinctrl = devm_pinctrl_get(dev);
1039 if (IS_ERR_OR_NULL(device_pctrl->pinctrl)) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -07001040 CAM_DBG(CAM_UTIL, "Pinctrl not available");
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001041 device_pctrl->pinctrl = NULL;
1042 return 0;
1043 }
1044 device_pctrl->gpio_state_active =
1045 pinctrl_lookup_state(device_pctrl->pinctrl,
1046 CAM_SOC_PINCTRL_STATE_DEFAULT);
1047 if (IS_ERR_OR_NULL(device_pctrl->gpio_state_active)) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -07001048 CAM_ERR(CAM_UTIL,
1049 "Failed to get the active state pinctrl handle");
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001050 device_pctrl->gpio_state_active = NULL;
1051 return -EINVAL;
1052 }
1053 device_pctrl->gpio_state_suspend
1054 = pinctrl_lookup_state(device_pctrl->pinctrl,
1055 CAM_SOC_PINCTRL_STATE_SLEEP);
1056 if (IS_ERR_OR_NULL(device_pctrl->gpio_state_suspend)) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -07001057 CAM_ERR(CAM_UTIL,
1058 "Failed to get the suspend state pinctrl handle");
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001059 device_pctrl->gpio_state_suspend = NULL;
1060 return -EINVAL;
1061 }
1062 return 0;
1063}
1064
1065static void cam_soc_util_regulator_disable_default(
1066 struct cam_hw_soc_info *soc_info)
1067{
1068 int j = 0;
1069 uint32_t num_rgltr = soc_info->num_rgltr;
1070
1071 for (j = num_rgltr-1; j >= 0; j--) {
1072 if (soc_info->rgltr_ctrl_support == true) {
1073 cam_soc_util_regulator_disable(soc_info->rgltr[j],
1074 soc_info->rgltr_name[j],
1075 soc_info->rgltr_min_volt[j],
1076 soc_info->rgltr_max_volt[j],
1077 soc_info->rgltr_op_mode[j],
1078 soc_info->rgltr_delay[j]);
1079 } else {
1080 if (soc_info->rgltr[j])
1081 regulator_disable(soc_info->rgltr[j]);
1082 }
1083 }
1084}
1085
1086static int cam_soc_util_regulator_enable_default(
1087 struct cam_hw_soc_info *soc_info)
1088{
1089 int j = 0, rc = 0;
1090 uint32_t num_rgltr = soc_info->num_rgltr;
1091
1092 for (j = 0; j < num_rgltr; j++) {
1093 if (soc_info->rgltr_ctrl_support == true) {
1094 rc = cam_soc_util_regulator_enable(soc_info->rgltr[j],
1095 soc_info->rgltr_name[j],
1096 soc_info->rgltr_min_volt[j],
1097 soc_info->rgltr_max_volt[j],
1098 soc_info->rgltr_op_mode[j],
1099 soc_info->rgltr_delay[j]);
1100 } else {
1101 if (soc_info->rgltr[j])
1102 rc = regulator_enable(soc_info->rgltr[j]);
1103 }
1104
1105 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -07001106 CAM_ERR(CAM_UTIL, "%s enable failed",
1107 soc_info->rgltr_name[j]);
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001108 goto disable_rgltr;
1109 }
1110 }
1111
1112 return rc;
1113disable_rgltr:
1114
1115 for (j--; j >= 0; j--) {
1116 if (soc_info->rgltr_ctrl_support == true) {
1117 cam_soc_util_regulator_disable(soc_info->rgltr[j],
1118 soc_info->rgltr_name[j],
1119 soc_info->rgltr_min_volt[j],
1120 soc_info->rgltr_max_volt[j],
1121 soc_info->rgltr_op_mode[j],
1122 soc_info->rgltr_delay[j]);
1123 } else {
1124 if (soc_info->rgltr[j])
1125 regulator_disable(soc_info->rgltr[j]);
1126 }
1127 }
1128
1129 return rc;
1130}
1131
1132int cam_soc_util_request_platform_resource(
1133 struct cam_hw_soc_info *soc_info,
Harsh Shahbbe33742017-03-14 18:09:54 -07001134 irq_handler_t handler, void *irq_data)
1135{
1136 int i = 0, rc = 0;
Harsh Shahbbe33742017-03-14 18:09:54 -07001137
Jigarkumar Zalaae152332017-07-18 17:21:48 -07001138 if (!soc_info || !soc_info->dev) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -07001139 CAM_ERR(CAM_UTIL, "Invalid parameters");
Harsh Shahbbe33742017-03-14 18:09:54 -07001140 return -EINVAL;
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001141 }
Harsh Shahbbe33742017-03-14 18:09:54 -07001142
Harsh Shahbbe33742017-03-14 18:09:54 -07001143 for (i = 0; i < soc_info->num_mem_block; i++) {
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001144 if (soc_info->reserve_mem) {
1145 if (!request_mem_region(soc_info->mem_block[i]->start,
1146 resource_size(soc_info->mem_block[i]),
1147 soc_info->mem_block_name[i])){
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -07001148 CAM_ERR(CAM_UTIL,
Jigarkumar Zalaae152332017-07-18 17:21:48 -07001149 "Error Mem region request Failed:%s",
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001150 soc_info->mem_block_name[i]);
1151 rc = -ENOMEM;
1152 goto unmap_base;
1153 }
1154 }
Harsh Shahbbe33742017-03-14 18:09:54 -07001155 soc_info->reg_map[i].mem_base = ioremap(
1156 soc_info->mem_block[i]->start,
1157 resource_size(soc_info->mem_block[i]));
1158 if (!soc_info->reg_map[i].mem_base) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -07001159 CAM_ERR(CAM_UTIL, "i= %d base NULL", i);
Harsh Shahbbe33742017-03-14 18:09:54 -07001160 rc = -ENOMEM;
1161 goto unmap_base;
1162 }
1163 soc_info->reg_map[i].mem_cam_base =
1164 soc_info->mem_block_cam_base[i];
1165 soc_info->reg_map[i].size =
1166 resource_size(soc_info->mem_block[i]);
1167 soc_info->num_reg_map++;
1168 }
1169
1170 for (i = 0; i < soc_info->num_rgltr; i++) {
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001171 if (soc_info->rgltr_name[i] == NULL) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -07001172 CAM_ERR(CAM_UTIL, "can't find regulator name");
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001173 goto put_regulator;
1174 }
1175
Jigarkumar Zalaae152332017-07-18 17:21:48 -07001176 rc = cam_soc_util_get_regulator(soc_info->dev,
1177 &soc_info->rgltr[i],
Harsh Shahbbe33742017-03-14 18:09:54 -07001178 soc_info->rgltr_name[i]);
1179 if (rc)
1180 goto put_regulator;
1181 }
1182
1183 if (soc_info->irq_line) {
Jigarkumar Zalaae152332017-07-18 17:21:48 -07001184 rc = devm_request_irq(soc_info->dev, soc_info->irq_line->start,
Harsh Shahbbe33742017-03-14 18:09:54 -07001185 handler, IRQF_TRIGGER_RISING,
1186 soc_info->irq_name, irq_data);
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001187 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -07001188 CAM_ERR(CAM_UTIL, "irq request fail");
Harsh Shahbbe33742017-03-14 18:09:54 -07001189 rc = -EBUSY;
1190 goto put_regulator;
1191 }
1192 disable_irq(soc_info->irq_line->start);
Pavan Kumar Chilamkurthi84614012017-04-17 22:37:41 -07001193 soc_info->irq_data = irq_data;
Harsh Shahbbe33742017-03-14 18:09:54 -07001194 }
1195
1196 /* Get Clock */
1197 for (i = 0; i < soc_info->num_clk; i++) {
Jigarkumar Zalaae152332017-07-18 17:21:48 -07001198 soc_info->clk[i] = clk_get(soc_info->dev,
Harsh Shahbbe33742017-03-14 18:09:54 -07001199 soc_info->clk_name[i]);
1200 if (!soc_info->clk[i]) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -07001201 CAM_ERR(CAM_UTIL, "get failed for %s",
1202 soc_info->clk_name[i]);
Harsh Shahbbe33742017-03-14 18:09:54 -07001203 rc = -ENOENT;
1204 goto put_clk;
1205 }
1206 }
1207
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001208 rc = cam_soc_util_request_pinctrl(soc_info);
1209 if (rc)
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -07001210 CAM_DBG(CAM_UTIL, "Failed in request pinctrl, rc=%d", rc);
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001211
1212 rc = cam_soc_util_request_gpio_table(soc_info, true);
1213 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -07001214 CAM_ERR(CAM_UTIL, "Failed in request gpio table, rc=%d", rc);
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001215 goto put_clk;
1216 }
1217
Harsh Shahbbe33742017-03-14 18:09:54 -07001218 return rc;
1219
1220put_clk:
1221 if (i == -1)
1222 i = soc_info->num_clk;
1223 for (i = i - 1; i >= 0; i--) {
1224 if (soc_info->clk[i]) {
1225 clk_put(soc_info->clk[i]);
1226 soc_info->clk[i] = NULL;
1227 }
1228 }
1229
1230 if (soc_info->irq_line) {
1231 disable_irq(soc_info->irq_line->start);
Jigarkumar Zalaae152332017-07-18 17:21:48 -07001232 devm_free_irq(soc_info->dev,
Pavan Kumar Chilamkurthi84614012017-04-17 22:37:41 -07001233 soc_info->irq_line->start, irq_data);
Harsh Shahbbe33742017-03-14 18:09:54 -07001234 }
1235
1236put_regulator:
1237 if (i == -1)
1238 i = soc_info->num_rgltr;
1239 for (i = i - 1; i >= 0; i--) {
1240 if (soc_info->rgltr[i]) {
1241 regulator_disable(soc_info->rgltr[i]);
1242 regulator_put(soc_info->rgltr[i]);
1243 soc_info->rgltr[i] = NULL;
1244 }
1245 }
1246
1247unmap_base:
1248 if (i == -1)
1249 i = soc_info->num_reg_map;
1250 for (i = i - 1; i >= 0; i--) {
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001251 if (soc_info->reserve_mem)
1252 release_mem_region(soc_info->mem_block[i]->start,
1253 resource_size(soc_info->mem_block[i]));
Harsh Shahbbe33742017-03-14 18:09:54 -07001254 iounmap(soc_info->reg_map[i].mem_base);
1255 soc_info->reg_map[i].mem_base = NULL;
1256 soc_info->reg_map[i].size = 0;
1257 }
1258
1259 return rc;
1260}
1261
1262int cam_soc_util_release_platform_resource(struct cam_hw_soc_info *soc_info)
1263{
1264 int i;
Harsh Shahbbe33742017-03-14 18:09:54 -07001265
Jigarkumar Zalaae152332017-07-18 17:21:48 -07001266 if (!soc_info || !soc_info->dev) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -07001267 CAM_ERR(CAM_UTIL, "Invalid parameter");
Harsh Shahbbe33742017-03-14 18:09:54 -07001268 return -EINVAL;
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001269 }
1270
Harsh Shahbbe33742017-03-14 18:09:54 -07001271 for (i = soc_info->num_clk - 1; i >= 0; i--) {
1272 clk_put(soc_info->clk[i]);
1273 soc_info->clk[i] = NULL;
1274 }
1275
1276 for (i = soc_info->num_rgltr - 1; i >= 0; i--) {
1277 if (soc_info->rgltr[i]) {
1278 regulator_put(soc_info->rgltr[i]);
1279 soc_info->rgltr[i] = NULL;
1280 }
1281 }
1282
1283 for (i = soc_info->num_reg_map - 1; i >= 0; i--) {
1284 iounmap(soc_info->reg_map[i].mem_base);
1285 soc_info->reg_map[i].mem_base = NULL;
1286 soc_info->reg_map[i].size = 0;
1287 }
1288
1289 if (soc_info->irq_line) {
1290 disable_irq(soc_info->irq_line->start);
Jigarkumar Zalaae152332017-07-18 17:21:48 -07001291 devm_free_irq(soc_info->dev,
Pavan Kumar Chilamkurthi84614012017-04-17 22:37:41 -07001292 soc_info->irq_line->start, soc_info->irq_data);
Harsh Shahbbe33742017-03-14 18:09:54 -07001293 }
1294
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001295 if (soc_info->pinctrl_info.pinctrl)
1296 devm_pinctrl_put(soc_info->pinctrl_info.pinctrl);
1297
1298
1299 /* release for gpio */
1300 cam_soc_util_request_gpio_table(soc_info, false);
1301
Harsh Shahbbe33742017-03-14 18:09:54 -07001302 return 0;
1303}
1304
1305int cam_soc_util_enable_platform_resource(struct cam_hw_soc_info *soc_info,
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -07001306 bool enable_clocks, enum cam_vote_level clk_level, bool enable_irq)
Harsh Shahbbe33742017-03-14 18:09:54 -07001307{
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001308 int rc = 0;
Harsh Shahbbe33742017-03-14 18:09:54 -07001309
1310 if (!soc_info)
1311 return -EINVAL;
1312
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001313 rc = cam_soc_util_regulator_enable_default(soc_info);
1314 if (rc) {
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -07001315 CAM_ERR(CAM_UTIL, "Regulators enable failed");
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001316 return rc;
Harsh Shahbbe33742017-03-14 18:09:54 -07001317 }
1318
1319 if (enable_clocks) {
Pavan Kumar Chilamkurthi7e7607b2017-06-22 20:02:50 -07001320 rc = cam_soc_util_clk_enable_default(soc_info, clk_level);
Harsh Shahbbe33742017-03-14 18:09:54 -07001321 if (rc)
1322 goto disable_regulator;
1323 }
1324
1325 if (enable_irq) {
1326 rc = cam_soc_util_irq_enable(soc_info);
1327 if (rc)
1328 goto disable_clk;
1329 }
1330
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001331 if (soc_info->pinctrl_info.pinctrl &&
1332 soc_info->pinctrl_info.gpio_state_active) {
1333 rc = pinctrl_select_state(soc_info->pinctrl_info.pinctrl,
1334 soc_info->pinctrl_info.gpio_state_active);
1335
1336 if (rc)
1337 goto disable_irq;
1338 }
1339
Harsh Shahbbe33742017-03-14 18:09:54 -07001340 return rc;
1341
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001342disable_irq:
1343 if (enable_irq)
1344 cam_soc_util_irq_disable(soc_info);
1345
Harsh Shahbbe33742017-03-14 18:09:54 -07001346disable_clk:
1347 if (enable_clocks)
1348 cam_soc_util_clk_disable_default(soc_info);
1349
1350disable_regulator:
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001351 cam_soc_util_regulator_disable_default(soc_info);
1352
Harsh Shahbbe33742017-03-14 18:09:54 -07001353
1354 return rc;
1355}
1356
1357int cam_soc_util_disable_platform_resource(struct cam_hw_soc_info *soc_info,
1358 bool disable_clocks, bool disble_irq)
1359{
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001360 int rc = 0;
Harsh Shahbbe33742017-03-14 18:09:54 -07001361
1362 if (!soc_info)
1363 return -EINVAL;
1364
Harsh Shahb6f61372017-10-23 16:30:02 -07001365 if (disble_irq)
1366 rc |= cam_soc_util_irq_disable(soc_info);
1367
Harsh Shahbbe33742017-03-14 18:09:54 -07001368 if (disable_clocks)
1369 cam_soc_util_clk_disable_default(soc_info);
1370
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001371 cam_soc_util_regulator_disable_default(soc_info);
Harsh Shahbbe33742017-03-14 18:09:54 -07001372
Pavan Kumar Chilamkurthi5852cbf2017-06-23 18:49:37 -07001373 if (soc_info->pinctrl_info.pinctrl &&
1374 soc_info->pinctrl_info.gpio_state_suspend)
1375 rc = pinctrl_select_state(soc_info->pinctrl_info.pinctrl,
1376 soc_info->pinctrl_info.gpio_state_suspend);
1377
Harsh Shahbbe33742017-03-14 18:09:54 -07001378 return rc;
1379}
1380
1381int cam_soc_util_reg_dump(struct cam_hw_soc_info *soc_info,
1382 uint32_t base_index, uint32_t offset, int size)
1383{
1384 void __iomem *base_addr = NULL;
1385
Jigarkumar Zalaea7e56a2017-07-27 10:13:06 -07001386 CAM_DBG(CAM_UTIL, "base_idx %u size=%d", base_index, size);
Harsh Shahbbe33742017-03-14 18:09:54 -07001387
1388 if (!soc_info || base_index >= soc_info->num_reg_map ||
1389 size <= 0 || (offset + size) >=
1390 CAM_SOC_GET_REG_MAP_SIZE(soc_info, base_index))
1391 return -EINVAL;
1392
1393 base_addr = CAM_SOC_GET_REG_MAP_START(soc_info, base_index);
1394
1395 /*
1396 * All error checking already done above,
1397 * hence ignoring the return value below.
1398 */
1399 cam_io_dump(base_addr, offset, size);
1400
1401 return 0;
1402}
1403