浏览代码

Merge "msm: camera: utils: Add camera clk wrapper infrastructure" into camera-kernel.lnx.5.0

Haritha Chintalapati 4 年之前
父节点
当前提交
f144ee8473

+ 3 - 6
drivers/cam_isp/isp_hw_mgr/isp_hw/ppi_hw/cam_csid_ppi_core.c

@@ -76,8 +76,7 @@ static int cam_csid_ppi_enable_hw(struct cam_csid_ppi_hw  *ppi_hw)
 	}
 
 	for (i = 0; i < soc_info->num_clk; i++) {
-		rc = cam_soc_util_clk_enable(soc_info->clk[i],
-			soc_info->clk_name[i], 0, NULL);
+		rc = cam_soc_util_clk_enable(soc_info, false, i, -1, NULL);
 		if (rc)
 			goto clk_disable;
 	}
@@ -107,8 +106,7 @@ static int cam_csid_ppi_enable_hw(struct cam_csid_ppi_hw  *ppi_hw)
 	return 0;
 clk_disable:
 	for (--i; i >= 0; i--)
-		cam_soc_util_clk_disable(soc_info->clk[i],
-			soc_info->clk_name[i]);
+		cam_soc_util_clk_disable(soc_info, false, i);
 	ppi_hw->hw_info->open_count--;
 	return rc;
 }
@@ -154,8 +152,7 @@ static int cam_csid_ppi_disable_hw(struct cam_csid_ppi_hw *ppi_hw)
 	ppi_hw->device_enabled = 0;
 
 	for (i = 0; i < soc_info->num_clk; i++)
-		cam_soc_util_clk_disable(soc_info->clk[i],
-			soc_info->clk_name[i]);
+		cam_soc_util_clk_disable(soc_info, false, i);
 
 	return rc;
 }

+ 13 - 11
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.c

@@ -64,9 +64,8 @@ int cam_tfe_init_soc_resources(struct cam_hw_soc_info *soc_info,
 
 clk_option:
 
-	rc = cam_soc_util_get_option_clk_by_name(soc_info,
-		CAM_TFE_DSP_CLK_NAME, &soc_private->dsp_clk,
-		&soc_private->dsp_clk_index, &soc_private->dsp_clk_rate);
+	rc = cam_soc_util_get_option_clk_by_name(soc_info, CAM_TFE_DSP_CLK_NAME,
+		&soc_private->dsp_clk_index);
 	if (rc)
 		CAM_WARN(CAM_ISP, "Option clk get failed with rc %d", rc);
 
@@ -129,10 +128,13 @@ int cam_tfe_deinit_soc_resources(struct cam_hw_soc_info *soc_info)
 			"Error! Release platform resource failed rc=%d", rc);
 
 
-	rc = cam_soc_util_clk_put(&soc_private->dsp_clk);
-	if (rc < 0)
-		CAM_ERR(CAM_ISP,
-			"Error Put dsp clk failed rc=%d", rc);
+	if (soc_private->dsp_clk_index != -1) {
+		rc = cam_soc_util_put_optional_clk(soc_info,
+			soc_private->dsp_clk_index);
+		if (rc)
+			CAM_ERR(CAM_ISP,
+				"Error Put dsp clk failed rc=%d", rc);
+	}
 
 	kfree(soc_private);
 
@@ -198,8 +200,8 @@ int cam_tfe_soc_enable_clk(struct cam_hw_soc_info *soc_info,
 	soc_private = soc_info->soc_private;
 
 	if (strcmp(clk_name, CAM_TFE_DSP_CLK_NAME) == 0) {
-		rc = cam_soc_util_clk_enable(soc_private->dsp_clk,
-			CAM_TFE_DSP_CLK_NAME, soc_private->dsp_clk_rate, NULL);
+		rc = cam_soc_util_clk_enable(soc_info, true,
+			soc_private->dsp_clk_index, 0, NULL);
 		if (rc)
 			CAM_ERR(CAM_ISP,
 			"Error enable dsp clk failed rc=%d", rc);
@@ -222,8 +224,8 @@ int cam_tfe_soc_disable_clk(struct cam_hw_soc_info *soc_info,
 	soc_private = soc_info->soc_private;
 
 	if (strcmp(clk_name, CAM_TFE_DSP_CLK_NAME) == 0) {
-		rc = cam_soc_util_clk_disable(soc_private->dsp_clk,
-			CAM_TFE_DSP_CLK_NAME);
+		rc = cam_soc_util_clk_disable(soc_info, true,
+			soc_private->dsp_clk_index);
 		if (rc)
 			CAM_ERR(CAM_ISP,
 			"Error enable dsp clk failed rc=%d", rc);

+ 2 - 3
drivers/cam_isp/isp_hw_mgr/isp_hw/tfe_hw/cam_tfe_soc.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2019-2021, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _CAM_TFE_SOC_H_
@@ -26,15 +26,14 @@ enum cam_cpas_handle_id {
  *                           This handle is used for all further interface
  *                           with CPAS.
  * @cpas_version:            Has cpas version read from Hardware
+ * @dsp_clk_index:           DSP clk index in optional clocks
  * @num_pid:                 number of pids of tfe
  * @pid:                     TFE pid value list
  */
 struct cam_tfe_soc_private {
 	uint32_t    cpas_handle;
 	uint32_t    cpas_version;
-	struct clk *dsp_clk;
 	int32_t     dsp_clk_index;
-	int32_t     dsp_clk_rate;
 	uint32_t    num_pid;
 	uint32_t    pid[CAM_ISP_HW_MAX_PID_VAL];
 };

+ 9 - 9
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.c

@@ -158,9 +158,8 @@ int cam_vfe_init_soc_resources(struct cam_hw_soc_info *soc_info,
 		goto free_soc_private;
 	}
 
-	rc = cam_soc_util_get_option_clk_by_name(soc_info,
-		CAM_VFE_DSP_CLK_NAME, &soc_private->dsp_clk,
-		&soc_private->dsp_clk_index, &soc_private->dsp_clk_rate);
+	rc = cam_soc_util_get_option_clk_by_name(soc_info, CAM_VFE_DSP_CLK_NAME,
+		&soc_private->dsp_clk_index);
 	if (rc)
 		CAM_DBG(CAM_ISP, "Option clk get failed with rc %d", rc);
 
@@ -222,8 +221,9 @@ int cam_vfe_deinit_soc_resources(struct cam_hw_soc_info *soc_info)
 			"Error! Release platform resources failed rc=%d", rc);
 
 	if (soc_private->dsp_clk_index != -1) {
-		rc = cam_soc_util_clk_put(&soc_private->dsp_clk);
-		if (rc < 0)
+		rc = cam_soc_util_put_optional_clk(soc_info,
+			soc_private->dsp_clk_index);
+		if (rc)
 			CAM_ERR(CAM_ISP,
 				"Error Put dsp clk failed rc=%d", rc);
 	}
@@ -306,8 +306,8 @@ int cam_vfe_soc_enable_clk(struct cam_hw_soc_info *soc_info,
 			goto end;
 		}
 
-		rc = cam_soc_util_clk_enable(soc_private->dsp_clk,
-			CAM_VFE_DSP_CLK_NAME, soc_private->dsp_clk_rate, NULL);
+		rc = cam_soc_util_clk_enable(soc_info, true,
+			soc_private->dsp_clk_index, 0, NULL);
 		if (rc)
 			CAM_ERR(CAM_ISP,
 			"Error enable dsp clk failed rc=%d", rc);
@@ -338,8 +338,8 @@ int cam_vfe_soc_disable_clk(struct cam_hw_soc_info *soc_info,
 			goto end;
 		}
 
-		rc = cam_soc_util_clk_disable(soc_private->dsp_clk,
-			CAM_VFE_DSP_CLK_NAME);
+		rc = cam_soc_util_clk_disable(soc_info, true,
+			soc_private->dsp_clk_index);
 		if (rc)
 			CAM_ERR(CAM_ISP,
 			"Error disable dsp clk failed rc=%d", rc);

+ 2 - 3
drivers/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/cam_vfe_soc.h

@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0-only */
 /*
- * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
  */
 
 #ifndef _CAM_VFE_SOC_H_
@@ -22,6 +22,7 @@
  *                           This handle is used for all further interface
  *                           with CPAS.
  * @cpas_version:            Has cpas version read from Hardware
+ * @dsp_clk_index:           DSP clk index in optional clocks
  * @ubwc_static_ctrl:        UBWC static control configuration
  * @is_ife_lite:             Flag to indicate full vs lite IFE
  * @ife_clk_src:             IFE source clock
@@ -31,9 +32,7 @@
 struct cam_vfe_soc_private {
 	uint32_t    cpas_handle;
 	uint32_t    cpas_version;
-	struct clk *dsp_clk;
 	int32_t     dsp_clk_index;
-	int32_t     dsp_clk_rate;
 	uint32_t    ubwc_static_ctrl[UBWC_STATIC_CONFIG_MAX];
 	bool        is_ife_lite;
 	uint64_t    ife_clk_src;

+ 8 - 9
drivers/cam_sensor_module/cam_sensor_utils/cam_sensor_util.c

@@ -2087,12 +2087,13 @@ int cam_sensor_core_power_up(struct cam_sensor_power_ctrl_t *ctrl,
 					power_setting->config_val;
 
 			for (j = 0; j < soc_info->num_clk; j++) {
-				rc = cam_soc_util_clk_enable(soc_info->clk[j],
-					soc_info->clk_name[j],
-					soc_info->clk_rate[0][j],
-					NULL);
-				if (rc)
+				rc = cam_soc_util_clk_enable(soc_info, false,
+					i, 0, NULL);
+				if (rc) {
+					CAM_ERR(CAM_UTIL,
+						"Failed in clk enable %d", i);
 					break;
+				}
 			}
 
 			if (rc < 0) {
@@ -2212,8 +2213,7 @@ power_up_failed:
 		switch (power_setting->seq_type) {
 		case SENSOR_MCLK:
 			for (i = soc_info->num_clk - 1; i >= 0; i--) {
-				cam_soc_util_clk_disable(soc_info->clk[i],
-					soc_info->clk_name[i]);
+				cam_soc_util_clk_disable(soc_info, false, i);
 			}
 			ret = cam_config_mclk_reg(ctrl, soc_info, index);
 			if (ret < 0) {
@@ -2370,8 +2370,7 @@ int cam_sensor_util_power_down(struct cam_sensor_power_ctrl_t *ctrl,
 		switch (pd->seq_type) {
 		case SENSOR_MCLK:
 			for (i = soc_info->num_clk - 1; i >= 0; i--) {
-				cam_soc_util_clk_disable(soc_info->clk[i],
-					soc_info->clk_name[i]);
+				cam_soc_util_clk_disable(soc_info, false, i);
 			}
 
 			ret = cam_config_mclk_reg(ctrl, soc_info, index);

+ 523 - 50
drivers/cam_utils/cam_soc_util.c

@@ -13,8 +13,274 @@
 #include "cam_cx_ipeak.h"
 #include "cam_mem_mgr.h"
 
+#define CAM_TO_MASK(bitn)          (1 << (int)(bitn))
+#define CAM_IS_BIT_SET(mask, bit)  ((mask) & CAM_TO_MASK(bit))
+#define CAM_SET_BIT(mask, bit)     ((mask) |= CAM_TO_MASK(bit))
+#define CAM_CLEAR_BIT(mask, bit)   ((mask) &= ~CAM_TO_MASK(bit))
+
+/**
+ * struct cam_clk_wrapper_clk: This represents an entry corresponding to a
+ *                             shared clock in Clk wrapper. Clients that share
+ *                             the same clock are registered to this clk entry
+ *                             and set rate from them is consolidated before
+ *                             setting it to clk driver.
+ *
+ * @list:           List pointer to point to next shared clk entry
+ * @clk_id:         Clk Id of this clock
+ * @curr_clk_rate:  Current clock rate set for this clock
+ * @client_list:    List of clients registered to this shared clock entry
+ * @num_clients:    Number of clients
+ **/
+struct cam_clk_wrapper_clk {
+	struct list_head list;
+	uint32_t clk_id;
+	int64_t curr_clk_rate;
+	struct list_head client_list;
+	uint32_t num_clients;
+};
+
+/**
+ * struct cam_clk_wrapper_client: This represents a client (device) that wants
+ *                                to share the clock with some other client.
+ *
+ * @list:           List pointer to point to next client that share the
+ *                  same clock
+ * @soc_info:       soc_info of client. This is used as unique identifier
+ *                  for a client
+ * @clk:            Clk handle
+ * @curr_clk_rate:  Current clock rate set for this client
+ **/
+struct cam_clk_wrapper_client {
+	struct list_head list;
+	struct cam_hw_soc_info *soc_info;
+	struct clk *clk;
+	int64_t curr_clk_rate;
+};
+
 static char supported_clk_info[256];
 
+static DEFINE_MUTEX(wrapper_lock);
+static LIST_HEAD(wrapper_clk_list);
+
+static int cam_soc_util_clk_wrapper_register_entry(
+	uint32_t clk_id, struct clk *clk, struct cam_hw_soc_info *soc_info,
+	const char *clk_name)
+{
+	struct cam_clk_wrapper_clk *wrapper_clk;
+	struct cam_clk_wrapper_client *wrapper_client;
+	bool clock_found = false;
+	int rc = 0;
+
+	mutex_lock(&wrapper_lock);
+
+	list_for_each_entry(wrapper_clk, &wrapper_clk_list, list) {
+		CAM_DBG(CAM_UTIL, "Clk list id %d num clients %d",
+			wrapper_clk->clk_id, wrapper_clk->num_clients);
+
+		if (wrapper_clk->clk_id == clk_id) {
+			clock_found = true;
+			list_for_each_entry(wrapper_client,
+				&wrapper_clk->client_list, list) {
+				CAM_DBG(CAM_UTIL,
+					"Clk id %d entry client %s",
+					wrapper_clk->clk_id,
+					wrapper_client->soc_info->dev_name);
+				if (wrapper_client->soc_info == soc_info) {
+					CAM_ERR(CAM_UTIL,
+						"Register with same soc info, clk id %d, client %s",
+						clk_id, soc_info->dev_name);
+					rc = -EINVAL;
+					goto end;
+				}
+			}
+			break;
+		}
+	}
+
+	if (!clock_found) {
+		CAM_DBG(CAM_UTIL, "Adding new entry for clk id %d", clk_id);
+		wrapper_clk = kzalloc(sizeof(struct cam_clk_wrapper_clk),
+			GFP_KERNEL);
+		if (!wrapper_clk) {
+			CAM_ERR(CAM_UTIL,
+				"Failed in allocating new clk entry %d",
+				clk_id);
+			rc = -ENOMEM;
+			goto end;
+		}
+
+		wrapper_clk->clk_id = clk_id;
+		INIT_LIST_HEAD(&wrapper_clk->list);
+		INIT_LIST_HEAD(&wrapper_clk->client_list);
+		list_add_tail(&wrapper_clk->list, &wrapper_clk_list);
+	}
+	wrapper_client = kzalloc(sizeof(struct cam_clk_wrapper_client),
+		GFP_KERNEL);
+	if (!wrapper_client) {
+		CAM_ERR(CAM_UTIL, "Failed in allocating new client entry %d",
+			clk_id);
+		rc = -ENOMEM;
+		goto end;
+	}
+
+	wrapper_client->soc_info = soc_info;
+	wrapper_client->clk = clk;
+
+	INIT_LIST_HEAD(&wrapper_client->list);
+	list_add_tail(&wrapper_client->list, &wrapper_clk->client_list);
+	wrapper_clk->num_clients++;
+
+	CAM_DBG(CAM_UTIL,
+		"Adding new client %s for clk[%s] id %d, num clients %d",
+		soc_info->dev_name, clk_name, clk_id, wrapper_clk->num_clients);
+end:
+	mutex_unlock(&wrapper_lock);
+	return rc;
+}
+
+static int cam_soc_util_clk_wrapper_unregister_entry(
+	uint32_t clk_id, struct cam_hw_soc_info *soc_info)
+{
+	struct cam_clk_wrapper_clk *wrapper_clk;
+	struct cam_clk_wrapper_client *wrapper_client;
+	bool clock_found = false;
+	bool client_found = false;
+	int rc = 0;
+
+	mutex_lock(&wrapper_lock);
+
+	list_for_each_entry(wrapper_clk, &wrapper_clk_list, list) {
+		CAM_DBG(CAM_UTIL, "Clk list id %d num clients %d",
+			wrapper_clk->clk_id, wrapper_clk->num_clients);
+
+		if (wrapper_clk->clk_id == clk_id) {
+			clock_found = true;
+			list_for_each_entry(wrapper_client,
+				&wrapper_clk->client_list, list) {
+				CAM_DBG(CAM_UTIL, "Clk id %d entry client %s",
+					wrapper_clk->clk_id,
+					wrapper_client->soc_info->dev_name);
+				if (wrapper_client->soc_info == soc_info) {
+					client_found = true;
+					wrapper_clk->num_clients--;
+					list_del_init(&wrapper_client->list);
+					kfree(wrapper_client);
+					break;
+				}
+			}
+			break;
+		}
+	}
+
+	if (!clock_found) {
+		CAM_ERR(CAM_UTIL, "Shared clk id %d entry not found", clk_id);
+		rc = -EINVAL;
+		goto end;
+	}
+
+	if (!client_found) {
+		CAM_ERR(CAM_UTIL,
+			"Client %pK for Shared clk id %d entry not found",
+			soc_info, clk_id);
+		rc = -EINVAL;
+		goto end;
+	}
+
+	CAM_DBG(CAM_UTIL, "Unregister client %s for clk id %d, num clients %d",
+		soc_info->dev_name, clk_id, wrapper_clk->num_clients);
+
+	if (!wrapper_clk->num_clients) {
+		list_del_init(&wrapper_clk->list);
+		kfree(wrapper_clk);
+	}
+end:
+	mutex_unlock(&wrapper_lock);
+	return rc;
+}
+
+static int cam_soc_util_clk_wrapper_set_clk_rate(
+	uint32_t clk_id, struct cam_hw_soc_info *soc_info,
+	struct clk *clk, int64_t clk_rate)
+{
+	struct cam_clk_wrapper_clk *wrapper_clk;
+	struct cam_clk_wrapper_client *wrapper_client;
+	bool clk_found = false;
+	bool client_found = false;
+	int rc = 0;
+	int64_t final_clk_rate = 0;
+
+	if (!soc_info || !clk) {
+		CAM_ERR(CAM_UTIL, "Invalid param soc_info %pK clk %pK",
+			soc_info, clk);
+		return -EINVAL;
+	}
+
+	mutex_lock(&wrapper_lock);
+
+	list_for_each_entry(wrapper_clk, &wrapper_clk_list, list) {
+		CAM_DBG(CAM_UTIL, "Clk list id %d num clients %d",
+			wrapper_clk->clk_id, wrapper_clk->num_clients);
+		if (wrapper_clk->clk_id == clk_id) {
+			clk_found = true;
+			break;
+		}
+	}
+
+	if (!clk_found) {
+		CAM_ERR(CAM_UTIL, "Clk entry not found id %d client %s",
+			clk_id, soc_info->dev_name);
+		rc = -EINVAL;
+		goto end;
+	}
+
+	list_for_each_entry(wrapper_client, &wrapper_clk->client_list, list) {
+		CAM_DBG(CAM_UTIL, "Clk id %d client %s, clk rate %lld",
+			wrapper_clk->clk_id, wrapper_client->soc_info->dev_name,
+			wrapper_client->curr_clk_rate);
+		if (wrapper_client->soc_info == soc_info) {
+			client_found = true;
+			CAM_DBG(CAM_UTIL,
+				"Clk enable clk id %d, client %s curr %ld new %ld",
+				clk_id, wrapper_client->soc_info->dev_name,
+				wrapper_client->curr_clk_rate, clk_rate);
+
+			wrapper_client->curr_clk_rate = clk_rate;
+		}
+
+		if (final_clk_rate < wrapper_client->curr_clk_rate)
+			final_clk_rate = wrapper_client->curr_clk_rate;
+	}
+
+	if (!client_found) {
+		CAM_ERR(CAM_UTIL,
+			"Wrapper clk enable without client entry clk id %d client %s",
+			clk_id, soc_info->dev_name);
+		rc = -EINVAL;
+		goto end;
+	}
+
+	CAM_DBG(CAM_UTIL,
+		"Clk id %d, client %s, clients rate %ld, curr %ld final %ld",
+		wrapper_clk->clk_id, soc_info->dev_name, clk_rate,
+		wrapper_clk->curr_clk_rate, final_clk_rate);
+
+	if (final_clk_rate != wrapper_clk->curr_clk_rate) {
+		if (final_clk_rate) {
+			rc = clk_set_rate(clk, final_clk_rate);
+			if (rc) {
+				CAM_ERR(CAM_UTIL, "set_rate failed on clk %d",
+					wrapper_clk->clk_id);
+				goto end;
+			}
+		}
+		wrapper_clk->curr_clk_rate = final_clk_rate;
+	}
+
+end:
+	mutex_unlock(&wrapper_lock);
+	return rc;
+}
+
 int cam_soc_util_get_clk_level(struct cam_hw_soc_info *soc_info,
 	int64_t clk_rate, int clk_idx, int32_t *clk_lvl)
 {
@@ -367,18 +633,26 @@ long cam_soc_util_get_clk_round_rate(struct cam_hw_soc_info *soc_info,
  * @clk:              Clock structure information for which rate is to be set
  * @clk_name:         Name of the clock for which rate is being set
  * @clk_rate:         Clock rate to be set
+ * @shared_clk:       Whether this is a shared clk
+ * @clk_id:           Clock ID
  * @applied_clk_rate: Final clock rate set to the clk
  *
  * @return:         Success or failure
  */
-static int cam_soc_util_set_clk_rate(struct clk *clk, const char *clk_name,
-	int64_t clk_rate, unsigned long *applied_clk_rate)
+static int cam_soc_util_set_clk_rate(struct cam_hw_soc_info *soc_info,
+	struct clk *clk, const char *clk_name,
+	int64_t clk_rate, bool shared_clk, uint32_t clk_id,
+	unsigned long *applied_clk_rate)
 {
 	int rc = 0;
 	long clk_rate_round = -1;
+	bool set_rate = false;
 
-	if (!clk || !clk_name)
+	if (!clk || !clk_name) {
+		CAM_ERR(CAM_UTIL, "Invalid input clk %pK clk_name %pK",
+			clk, clk_name);
 		return -EINVAL;
+	}
 
 	CAM_DBG(CAM_UTIL, "set %s, rate %lld", clk_name, clk_rate);
 	if (clk_rate > 0) {
@@ -389,11 +663,7 @@ static int cam_soc_util_set_clk_rate(struct clk *clk, const char *clk_name,
 				clk_name, clk_rate_round);
 			return clk_rate_round;
 		}
-		rc = clk_set_rate(clk, clk_rate_round);
-		if (rc) {
-			CAM_ERR(CAM_UTIL, "set_rate failed on %s", clk_name);
-			return rc;
-		}
+		set_rate = true;
 	} else if (clk_rate == INIT_RATE) {
 		clk_rate_round = clk_get_rate(clk);
 		CAM_DBG(CAM_UTIL, "init new_rate %ld", clk_rate_round);
@@ -405,10 +675,23 @@ static int cam_soc_util_set_clk_rate(struct clk *clk, const char *clk_name,
 				return clk_rate_round;
 			}
 		}
-		rc = clk_set_rate(clk, clk_rate_round);
-		if (rc) {
-			CAM_ERR(CAM_UTIL, "set_rate failed on %s", clk_name);
-			return rc;
+		set_rate = true;
+	}
+
+	if (set_rate) {
+		if (shared_clk) {
+			CAM_DBG(CAM_UTIL,
+				"Dev %s clk %s id %d Set Shared clk %ld",
+				soc_info->dev_name, clk_name, clk_id,
+				clk_rate_round);
+			cam_soc_util_clk_wrapper_set_clk_rate(
+				clk_id, soc_info, clk, clk_rate_round);
+		} else {
+			rc = clk_set_rate(clk, clk_rate_round);
+			if (rc) {
+				CAM_ERR(CAM_UTIL, "set_rate failed on %s", clk_name);
+				return rc;
+			}
 		}
 	}
 
@@ -462,8 +745,10 @@ int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info,
 			apply_level);
 	}
 
-	rc = cam_soc_util_set_clk_rate(clk,
+	rc = cam_soc_util_set_clk_rate(soc_info, clk,
 		soc_info->clk_name[src_clk_idx], clk_rate,
+		CAM_IS_BIT_SET(soc_info->shared_clk_mask, src_clk_idx),
+		soc_info->clk_id[src_clk_idx],
 		&soc_info->applied_src_clk_rate);
 	if (rc) {
 		CAM_ERR(CAM_UTIL,
@@ -482,9 +767,11 @@ int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info,
 			continue;
 		}
 		clk = soc_info->clk[scl_clk_idx];
-		rc = cam_soc_util_set_clk_rate(clk,
+		rc = cam_soc_util_set_clk_rate(soc_info, clk,
 			soc_info->clk_name[scl_clk_idx],
 			soc_info->clk_rate[apply_level][scl_clk_idx],
+			CAM_IS_BIT_SET(soc_info->shared_clk_mask, scl_clk_idx),
+			soc_info->clk_id[scl_clk_idx],
 			NULL);
 		if (rc) {
 			CAM_WARN(CAM_UTIL,
@@ -498,21 +785,26 @@ int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info,
 	return 0;
 }
 
-int cam_soc_util_clk_put(struct clk **clk)
+int cam_soc_util_put_optional_clk(struct cam_hw_soc_info *soc_info,
+	int32_t clk_indx)
 {
-	if (!(*clk)) {
-		CAM_ERR(CAM_UTIL, "Invalid params clk");
+	if (clk_indx < 0) {
+		CAM_ERR(CAM_UTIL, "Invalid params clk %d", clk_indx);
 		return -EINVAL;
 	}
 
-	clk_put(*clk);
-	*clk = NULL;
+	if (CAM_IS_BIT_SET(soc_info->optional_shared_clk_mask, clk_indx))
+		cam_soc_util_clk_wrapper_unregister_entry(
+			soc_info->optional_clk_id[clk_indx], soc_info);
+
+	clk_put(soc_info->optional_clk[clk_indx]);
+	soc_info->optional_clk[clk_indx] = NULL;
 
 	return 0;
 }
 
 static struct clk *cam_soc_util_option_clk_get(struct device_node *np,
-	int index)
+	int index, uint32_t *clk_id)
 {
 	struct of_phandle_args clkspec;
 	struct clk *clk;
@@ -527,23 +819,25 @@ static struct clk *cam_soc_util_option_clk_get(struct device_node *np,
 		return ERR_PTR(rc);
 
 	clk = of_clk_get_from_provider(&clkspec);
+
+	*clk_id = clkspec.args[0];
 	of_node_put(clkspec.np);
 
 	return clk;
 }
 
 int cam_soc_util_get_option_clk_by_name(struct cam_hw_soc_info *soc_info,
-	const char *clk_name, struct clk **clk, int32_t *clk_index,
-	int32_t *clk_rate)
+	const char *clk_name, int32_t *clk_index)
 {
 	int index = 0;
 	int rc = 0;
 	struct device_node *of_node = NULL;
+	uint32_t shared_clk_val;
 
-	if (!soc_info || !clk_name || !clk) {
+	if (!soc_info || !clk_name || !clk_index) {
 		CAM_ERR(CAM_UTIL,
-			"Invalid params soc_info %pK clk_name %s clk %pK",
-			soc_info, clk_name, clk);
+			"Invalid params soc_info %pK clk_name %s clk_index %pK",
+			soc_info, clk_name, clk_index);
 		return -EINVAL;
 	}
 
@@ -554,52 +848,129 @@ int cam_soc_util_get_option_clk_by_name(struct cam_hw_soc_info *soc_info,
 	if (index < 0) {
 		CAM_DBG(CAM_UTIL, "No clk data for %s", clk_name);
 		*clk_index = -1;
-		*clk = ERR_PTR(-EINVAL);
 		return -EINVAL;
 	}
 
-	*clk = cam_soc_util_option_clk_get(of_node, index);
-	if (IS_ERR(*clk)) {
+	if (index >= CAM_SOC_MAX_OPT_CLK) {
+		CAM_ERR(CAM_UTIL, "Insufficient optional clk entries %d %d",
+			index, CAM_SOC_MAX_OPT_CLK);
+		return -EINVAL;
+	}
+
+	of_property_read_string_index(of_node, "clock-names-option",
+		index, &(soc_info->optional_clk_name[index]));
+
+	soc_info->optional_clk[index] = cam_soc_util_option_clk_get(of_node,
+		index, &soc_info->optional_clk_id[index]);
+	if (IS_ERR(soc_info->optional_clk[index])) {
 		CAM_ERR(CAM_UTIL, "No clk named %s found. Dev %s", clk_name,
 			soc_info->dev_name);
 		*clk_index = -1;
-		*clk = NULL;
 		return -EFAULT;
 	}
 	*clk_index = index;
 
 	rc = of_property_read_u32_index(of_node, "clock-rates-option",
-		index, clk_rate);
+		index, &soc_info->optional_clk_rate[index]);
 	if (rc) {
 		CAM_ERR(CAM_UTIL,
 			"Error reading clock-rates clk_name %s index %d",
 			clk_name, index);
-		cam_soc_util_clk_put(clk);
-		*clk_rate = 0;
-		return rc;
+		goto error;
 	}
 
 	/*
 	 * Option clocks are assumed to be available to single Device here.
 	 * Hence use INIT_RATE instead of NO_SET_RATE.
 	 */
-	*clk_rate = (*clk_rate == 0) ? (int32_t)INIT_RATE : *clk_rate;
+	soc_info->optional_clk_rate[index] =
+		(soc_info->optional_clk_rate[index] == 0) ?
+		(int32_t)INIT_RATE : soc_info->optional_clk_rate[index];
 
 	CAM_DBG(CAM_UTIL, "clk_name %s index %d clk_rate %d",
-		clk_name, *clk_index, *clk_rate);
+		clk_name, *clk_index, soc_info->optional_clk_rate[index]);
+
+	rc = of_property_read_u32_index(of_node, "shared-clks-option",
+		index, &shared_clk_val);
+	if (rc) {
+		CAM_DBG(CAM_UTIL, "Not shared clk  %s index %d",
+			clk_name, index);
+	} else if (shared_clk_val > 1) {
+		CAM_WARN(CAM_UTIL, "Invalid shared clk val %d", shared_clk_val);
+	} else {
+		CAM_DBG(CAM_UTIL,
+			"Dev %s shared clk  %s index %d, clk id %d, shared_clk_val %d",
+			soc_info->dev_name, clk_name, index,
+			soc_info->optional_clk_id[index], shared_clk_val);
+
+		if (shared_clk_val) {
+			CAM_SET_BIT(soc_info->optional_shared_clk_mask, index);
+
+			/* Create a wrapper entry if this is a shared clock */
+			CAM_DBG(CAM_UTIL,
+				"Dev %s, clk %s, id %d register wrapper entry for shared clk",
+				soc_info->dev_name,
+				soc_info->optional_clk_name[index],
+				soc_info->optional_clk_id[index]);
+
+			rc = cam_soc_util_clk_wrapper_register_entry(
+				soc_info->optional_clk_id[index],
+				soc_info->optional_clk[index], soc_info,
+				soc_info->optional_clk_name[index]);
+			if (rc) {
+				CAM_ERR(CAM_UTIL,
+					"Failed in registering shared clk Dev %s id %d",
+					soc_info->dev_name,
+					soc_info->optional_clk_id[index]);
+				goto error;
+			}
+		}
+	}
 
 	return 0;
+error:
+	clk_put(soc_info->optional_clk[index]);
+	soc_info->optional_clk_rate[index] = 0;
+	soc_info->optional_clk[index] = NULL;
+	*clk_index = -1;
+
+	return rc;
 }
 
-int cam_soc_util_clk_enable(struct clk *clk, const char *clk_name,
-	int32_t clk_rate, unsigned long *applied_clock_rate)
+int cam_soc_util_clk_enable(struct cam_hw_soc_info *soc_info,
+	bool optional_clk, int32_t clk_idx, int32_t apply_level,
+	unsigned long *applied_clock_rate)
 {
 	int rc = 0;
+	struct clk *clk;
+	const char *clk_name;
+	int32_t clk_rate;
+	uint32_t shared_clk_mask;
+	uint32_t clk_id;
 
-	if (!clk || !clk_name)
+	if (!soc_info || (clk_idx < 0) || (apply_level >= CAM_MAX_VOTE)) {
+		CAM_ERR(CAM_UTIL, "Invalid param %d %d", clk_idx, apply_level);
 		return -EINVAL;
+	}
 
-	rc = cam_soc_util_set_clk_rate(clk, clk_name, clk_rate,
+	if (optional_clk) {
+		clk = soc_info->optional_clk[clk_idx];
+		clk_name = soc_info->optional_clk_name[clk_idx];
+		clk_rate = (apply_level == -1) ?
+			0 : soc_info->optional_clk_rate[clk_idx];
+		shared_clk_mask = soc_info->optional_shared_clk_mask;
+		clk_id = soc_info->optional_clk_id[clk_idx];
+	} else {
+		clk = soc_info->clk[clk_idx];
+		clk_name = soc_info->clk_name[clk_idx];
+		clk_rate = (apply_level == -1) ?
+			0 : soc_info->clk_rate[apply_level][clk_idx];
+		shared_clk_mask = soc_info->shared_clk_mask;
+		clk_id = soc_info->clk_id[clk_idx];
+	}
+
+	rc = cam_soc_util_set_clk_rate(soc_info, clk, clk_name, clk_rate,
+		CAM_IS_BIT_SET(shared_clk_mask, clk_idx), clk_id,
 		applied_clock_rate);
 	if (rc)
 		return rc;
@@ -613,14 +984,42 @@ int cam_soc_util_clk_enable(struct clk *clk, const char *clk_name,
 	return rc;
 }
 
-int cam_soc_util_clk_disable(struct clk *clk, const char *clk_name)
+int cam_soc_util_clk_disable(struct cam_hw_soc_info *soc_info,
+	bool optional_clk, int32_t clk_idx)
 {
-	if (!clk || !clk_name)
+
+	struct clk *clk;
+	const char *clk_name;
+	uint32_t shared_clk_mask;
+	uint32_t clk_id;
+
+	if (!soc_info || (clk_idx < 0)) {
+		CAM_ERR(CAM_UTIL, "Invalid param %d", clk_idx);
 		return -EINVAL;
+	}
+
+	if (optional_clk) {
+		clk = soc_info->optional_clk[clk_idx];
+		clk_name = soc_info->optional_clk_name[clk_idx];
+		shared_clk_mask = soc_info->optional_shared_clk_mask;
+		clk_id = soc_info->optional_clk_id[clk_idx];
+	} else {
+		clk = soc_info->clk[clk_idx];
+		clk_name = soc_info->clk_name[clk_idx];
+		shared_clk_mask = soc_info->shared_clk_mask;
+		clk_id = soc_info->clk_id[clk_idx];
+	}
 
 	CAM_DBG(CAM_UTIL, "disable %s", clk_name);
 	clk_disable_unprepare(clk);
 
+	if (CAM_IS_BIT_SET(shared_clk_mask, clk_idx)) {
+		CAM_DBG(CAM_UTIL,
+			"Dev %s clk %s Disabling Shared clk, set 0 rate",
+			soc_info->dev_name, clk_name);
+		cam_soc_util_clk_wrapper_set_clk_rate(clk_id, soc_info, clk, 0);
+	}
+
 	return 0;
 }
 
@@ -658,9 +1057,7 @@ int cam_soc_util_clk_enable_default(struct cam_hw_soc_info *soc_info,
 		cam_cx_ipeak_update_vote_cx_ipeak(soc_info, apply_level);
 
 	for (i = 0; i < soc_info->num_clk; i++) {
-		rc = cam_soc_util_clk_enable(soc_info->clk[i],
-			soc_info->clk_name[i],
-			soc_info->clk_rate[apply_level][i],
+		rc = cam_soc_util_clk_enable(soc_info, false, i, apply_level,
 			&applied_clk_rate);
 		if (rc)
 			goto clk_disable;
@@ -684,8 +1081,7 @@ clk_disable:
 	if (soc_info->cam_cx_ipeak_enable)
 		cam_cx_ipeak_update_vote_cx_ipeak(soc_info, 0);
 	for (i--; i >= 0; i--) {
-		cam_soc_util_clk_disable(soc_info->clk[i],
-			soc_info->clk_name[i]);
+		cam_soc_util_clk_disable(soc_info, false, i);
 	}
 
 	return rc;
@@ -711,8 +1107,7 @@ void cam_soc_util_clk_disable_default(struct cam_hw_soc_info *soc_info)
 	if (soc_info->cam_cx_ipeak_enable)
 		cam_cx_ipeak_unvote_cx_ipeak(soc_info);
 	for (i = soc_info->num_clk - 1; i >= 0; i--)
-		cam_soc_util_clk_disable(soc_info->clk[i],
-			soc_info->clk_name[i]);
+		cam_soc_util_clk_disable(soc_info, false, i);
 }
 
 /**
@@ -737,6 +1132,8 @@ static int cam_soc_util_get_dt_clk_info(struct cam_hw_soc_info *soc_info)
 	const char *clk_control_debugfs = NULL;
 	const char *clk_cntl_lvl_string = NULL;
 	enum cam_vote_level level;
+	int shared_clk_cnt;
+	struct of_phandle_args clk_args = {0};
 
 	if (!soc_info || !soc_info->dev)
 		return -EINVAL;
@@ -857,8 +1254,54 @@ static int cam_soc_util_get_dt_clk_info(struct cam_hw_soc_info *soc_info)
 			soc_info->src_clk_idx = i;
 			CAM_DBG(CAM_UTIL, "src clock = %s, index = %d",
 				src_clk_str, i);
-			break;
 		}
+
+		rc = of_parse_phandle_with_args(of_node, "clocks",
+			"#clock-cells", i, &clk_args);
+		if (rc) {
+			CAM_ERR(CAM_CPAS,
+				"failed to clock info rc=%d", rc);
+			rc = -EINVAL;
+			goto end;
+		}
+
+		soc_info->clk_id[i] = clk_args.args[0];
+		of_node_put(clk_args.np);
+
+		CAM_DBG(CAM_UTIL, "Dev %s clk %s id %d",
+			soc_info->dev_name, soc_info->clk_name[i],
+			soc_info->clk_id[i]);
+	}
+
+	soc_info->shared_clk_mask = 0;
+	shared_clk_cnt = of_property_count_u32_elems(of_node, "shared-clks");
+	if (shared_clk_cnt <= 0) {
+		CAM_DBG(CAM_UTIL, "Dev %s, no shared clks", soc_info->dev_name);
+	} else if (shared_clk_cnt != count) {
+		CAM_ERR(CAM_UTIL, "Dev %s, incorrect shared clock count %d %d",
+			soc_info->dev_name, shared_clk_cnt, count);
+		rc = -EINVAL;
+		goto end;
+	} else {
+		uint32_t shared_clk_val;
+
+		for (i = 0; i < shared_clk_cnt; i++) {
+			rc = of_property_read_u32_index(of_node,
+				"shared-clks", i, &shared_clk_val);
+			if (rc || (shared_clk_val > 1)) {
+				CAM_ERR(CAM_UTIL,
+					"Incorrect shared clk info at %d, val=%d, count=%d",
+					i, shared_clk_val, shared_clk_cnt);
+				rc = -EINVAL;
+				goto end;
+			}
+
+			if (shared_clk_val)
+				CAM_SET_BIT(soc_info->shared_clk_mask, i);
+		}
+
+		CAM_DBG(CAM_UTIL, "Dev %s shared clk mask 0x%x",
+			soc_info->dev_name, soc_info->shared_clk_mask);
 	}
 
 	/* scalable clk info parsing */
@@ -953,9 +1396,11 @@ int cam_soc_util_set_clk_rate_level(struct cam_hw_soc_info *soc_info,
 			soc_info->clk_name[i],
 			soc_info->clk_rate[apply_level][i]);
 
-		rc = cam_soc_util_set_clk_rate(soc_info->clk[i],
+		rc = cam_soc_util_set_clk_rate(soc_info, soc_info->clk[i],
 			soc_info->clk_name[i],
 			soc_info->clk_rate[apply_level][i],
+			CAM_IS_BIT_SET(soc_info->shared_clk_mask, i),
+			soc_info->clk_id[i],
 			&applied_clk_rate);
 		if (rc < 0) {
 			CAM_DBG(CAM_UTIL,
@@ -1634,6 +2079,26 @@ int cam_soc_util_request_platform_resource(
 			rc = -ENOENT;
 			goto put_clk;
 		}
+
+		/* Create a wrapper entry if this is a shared clock */
+		if (CAM_IS_BIT_SET(soc_info->shared_clk_mask, i)) {
+			CAM_DBG(CAM_UTIL,
+				"Dev %s, clk %s, id %d register wrapper entry for shared clk",
+				soc_info->dev_name, soc_info->clk_name[i],
+				soc_info->clk_id[i]);
+			rc = cam_soc_util_clk_wrapper_register_entry(
+				soc_info->clk_id[i], soc_info->clk[i], soc_info,
+				soc_info->clk_name[i]);
+			if (rc) {
+				CAM_ERR(CAM_UTIL,
+					"Failed in registering shared clk Dev %s id %d",
+					soc_info->dev_name,
+					soc_info->clk_id[i]);
+				clk_put(soc_info->clk[i]);
+				soc_info->clk[i] = NULL;
+				goto put_clk;
+			}
+		}
 	}
 
 	rc = cam_soc_util_request_pinctrl(soc_info);
@@ -1656,6 +2121,10 @@ put_clk:
 		i = soc_info->num_clk;
 	for (i = i - 1; i >= 0; i--) {
 		if (soc_info->clk[i]) {
+			if (CAM_IS_BIT_SET(soc_info->shared_clk_mask, i))
+				cam_soc_util_clk_wrapper_unregister_entry(
+					soc_info->clk_id[i], soc_info);
+
 			clk_put(soc_info->clk[i]);
 			soc_info->clk[i] = NULL;
 		}
@@ -1703,6 +2172,10 @@ int cam_soc_util_release_platform_resource(struct cam_hw_soc_info *soc_info)
 	}
 
 	for (i = soc_info->num_clk - 1; i >= 0; i--) {
+		if (CAM_IS_BIT_SET(soc_info->shared_clk_mask, i))
+			cam_soc_util_clk_wrapper_unregister_entry(
+				soc_info->clk_id[i], soc_info);
+
 		clk_put(soc_info->clk[i]);
 		soc_info->clk[i] = NULL;
 	}

+ 47 - 17
drivers/cam_utils/cam_soc_util.h

@@ -36,6 +36,9 @@
 /* maximum number of device clock */
 #define CAM_SOC_MAX_CLK             32
 
+/* maximum number of optional device clock */
+#define CAM_SOC_MAX_OPT_CLK    2
+
 /* DDR device types */
 #define DDR_TYPE_LPDDR4        6
 #define DDR_TYPE_LPDDR4X       7
@@ -155,12 +158,23 @@ struct cam_soc_gpio_data {
  * @clk:                    Array of associated clock resources
  * @clk_rate:               2D array of clock rates representing clock rate
  *                          values at different vote levels
+ * @clk_id                  Clock IDs
+ * @shared_clk_mask         Mask indicating which of the clocks are shared with
+ *                          other devices. Set rate on these clocks needs to go
+ *                          through camera clk wrapper for aggregation.
  * @prev_clk_level          Last vote level
  * @src_clk_idx:            Source clock index that is rate-controllable
+ * @applied_src_clk_rate    Current clock rate of the core source clk
  * @clk_level_valid:        Indicates whether corresponding level is valid
  * @scl_clk_count:          Number of scalable clocks present
  * @scl_clk_idx:            Index of scalable clocks
- * @applied_src_clk_rate    Current clock rate of the core source clk
+ * @optional_clk_name:      Array of clock names
+ * @optional_clk:           Array of associated clock resources
+ * @optional_clk_rate:      Optional clock's clk rate
+ * @optional_clk_id         Clock IDs
+ * @optional_shared_clk_mask Mask indicating which of the clocks are shared with
+ *                           other devices. Set rate on these clocks needs to go
+ *                           through camera clk wrapper for aggregation.
  * @gpio_data:              Pointer to gpio info
  * @pinctrl_info:           Pointer to pinctrl info
  * @dentry:                 Debugfs entry
@@ -205,12 +219,19 @@ struct cam_hw_soc_info {
 	const char                     *clk_name[CAM_SOC_MAX_CLK];
 	struct clk                     *clk[CAM_SOC_MAX_CLK];
 	int32_t                         clk_rate[CAM_MAX_VOTE][CAM_SOC_MAX_CLK];
+	uint32_t                        clk_id[CAM_SOC_MAX_CLK];
+	uint32_t                        shared_clk_mask;
 	int32_t                         prev_clk_level;
 	int32_t                         src_clk_idx;
 	unsigned long                   applied_src_clk_rate;
 	bool                            clk_level_valid[CAM_MAX_VOTE];
 	int32_t                         scl_clk_count;
 	int32_t                         scl_clk_idx[CAM_SOC_MAX_CLK];
+	const char                     *optional_clk_name[CAM_SOC_MAX_OPT_CLK];
+	struct clk                     *optional_clk[CAM_SOC_MAX_OPT_CLK];
+	int32_t                         optional_clk_rate[CAM_SOC_MAX_OPT_CLK];
+	uint32_t                        optional_clk_id[CAM_SOC_MAX_OPT_CLK];
+	uint32_t                        optional_shared_clk_mask;
 
 	struct cam_soc_gpio_data       *gpio_data;
 	struct cam_soc_pinctrl_info     pinctrl_info;
@@ -427,42 +448,48 @@ int cam_soc_util_set_src_clk_rate(struct cam_hw_soc_info *soc_info,
  *
  * @soc_info:           Device soc information
  * @clk_name:           Name of clock to find reference for
- * @clk:                Clock reference pointer to be filled if Success
  * @clk_index:          Clk index in the option clk array to be returned
- * @clk_rate:           Clk rate in the option clk array
  *
  * @return:             0: Success
  *                      Negative: Failure
  */
 int cam_soc_util_get_option_clk_by_name(struct cam_hw_soc_info *soc_info,
-	const char *clk_name, struct clk **clk, int32_t *clk_index,
-	int32_t *clk_rate);
+	const char *clk_name, int32_t *clk_index);
 
 /**
- * cam_soc_util_clk_put()
+ * cam_soc_util_put_optional_clk()
  *
- * @brief:              Put clock specified in params
+ * @brief:              Put clock corresponding to index specified in params
  *
- * @clk:                Reference to the Clock that needs to be put
+ * @soc_info:           Device soc information
+ * @clk_idx:            Clock index in optional clocks to put
  *
  * @return:             Success or failure
  */
-int cam_soc_util_clk_put(struct clk **clk);
+int cam_soc_util_put_optional_clk(struct cam_hw_soc_info *soc_info,
+	int32_t clk_idx);
 
 /**
  * cam_soc_util_clk_enable()
  *
  * @brief:              Enable clock specified in params
  *
- * @clk:                Clock that needs to be turned ON
- * @clk_name:           Clocks name associated with clk
- * @clk_rate:           Clocks rate associated with clk
+ * @soc_info:           Device soc information
+ * @optional_clk:       Whether to set optional clk or normal clk with
+ *                      the idx given
+ * @clk_idx:            Clock index to set
+ * @apply_level:        Apply level.
+ *                      -1 for 0 rate
+ *                      any other value indicate level for normal clocks
+ *                      For optional clocks any other value means the rate saved
+ *                      in soc_info
  * @applied_clock_rate  Final Clock rate applied to the clk
  *
  * @return:             Success or failure
  */
-int cam_soc_util_clk_enable(struct clk *clk, const char *clk_name,
-	int32_t clk_rate, unsigned long *applied_clock_rate);
+int cam_soc_util_clk_enable(struct cam_hw_soc_info *soc_info,
+	bool optional_clk, int32_t clk_idx, int32_t apply_level,
+	unsigned long *applied_clock_rate);
 
 /**
  * cam_soc_util_set_clk_rate_level()
@@ -485,12 +512,15 @@ int cam_soc_util_set_clk_rate_level(struct cam_hw_soc_info *soc_info,
  *
  * @brief:              Disable clock specified in params
  *
- * @clk:                Clock that needs to be turned OFF
- * @clk_name:           Clocks name associated with clk
+ * @soc_info:           Device soc information
+ * @optional_clk:       Whether to set optional clk or normal clk with
+ *                      the idx given
+ * @clk_idx:            Clock index to disable
  *
  * @return:             Success or failure
  */
-int cam_soc_util_clk_disable(struct clk *clk, const char *clk_name);
+int cam_soc_util_clk_disable(struct cam_hw_soc_info *soc_info,
+	bool optional_clk, int32_t clk_idx);
 
 /**
  * cam_soc_util_irq_enable()