Merge "msm: camera: utils: Add camera clk wrapper infrastructure" into camera-kernel.lnx.5.0
This commit is contained in:
committato da
Gerrit - the friendly Code Review server
commit
f144ee8473
@@ -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;
|
||||
}
|
||||
|
@@ -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);
|
||||
|
@@ -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];
|
||||
};
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
|
@@ -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);
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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()
|
||||
|
Fai riferimento in un nuovo problema
Block a user