aboutsummaryrefslogtreecommitdiff
path: root/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c')
-rw-r--r--drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c212
1 files changed, 176 insertions, 36 deletions
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
index 2e9aa6cbb1db..03c7d7b6c007 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -14,6 +14,7 @@
#include "cam_csiphy_core.h"
#include "cam_csiphy_dev.h"
#include "cam_csiphy_soc.h"
+#include "cam_common_util.h"
#include <soc/qcom/scm.h>
#include <cam_mem_mgr.h>
@@ -21,20 +22,36 @@
#define SCM_SVC_CAMERASS 0x18
#define SECURE_SYSCALL_ID 0x6
+#define SECURE_SYSCALL_ID_2 0x7
+
static int csiphy_dump;
module_param(csiphy_dump, int, 0644);
-static int cam_csiphy_notify_secure_mode(int phy, bool protect)
+static int cam_csiphy_notify_secure_mode(struct csiphy_device *csiphy_dev,
+ bool protect, int32_t offset)
{
struct scm_desc desc = {0};
+ int result = -1;
+ if (offset >= CSIPHY_MAX_INSTANCES)
+ return -EINVAL;
desc.arginfo = SCM_ARGS(2, SCM_VAL, SCM_VAL);
desc.args[0] = protect;
- desc.args[1] = phy;
-
- CAM_DBG(CAM_CSIPHY, "phy : %d, protect : %d", phy, protect);
- if (scm_call2(SCM_SIP_FNID(SCM_SVC_CAMERASS, SECURE_SYSCALL_ID),
- &desc)) {
+ desc.args[1] = csiphy_dev->csiphy_cpas_cp_reg_mask[offset];
+
+ /*
+ * If SECURE_SYSCALL_ID_2 is not supported
+ * then fallback to SECURE_SYSCALL_ID
+ */
+ result = scm_call2(SCM_SIP_FNID(SCM_SVC_CAMERASS, SECURE_SYSCALL_ID_2),
+ &desc);
+ if (result == -EOPNOTSUPP) {
+ desc.args[1] = csiphy_dev->soc_info.index;
+ CAM_ERR(CAM_CSIPHY, "SCM CALL 7 not supported fallback to 6");
+ result = scm_call2(SCM_SIP_FNID(SCM_SVC_CAMERASS,
+ SECURE_SYSCALL_ID), &desc);
+ }
+ if (result) {
CAM_ERR(CAM_CSIPHY, "scm call to hypervisor failed");
return -EINVAL;
}
@@ -42,6 +59,27 @@ static int cam_csiphy_notify_secure_mode(int phy, bool protect)
return 0;
}
+static int32_t cam_csiphy_get_instance_offset(
+ struct csiphy_device *csiphy_dev,
+ int32_t dev_handle)
+{
+ int32_t i;
+
+ if (csiphy_dev->acquire_count >
+ CSIPHY_MAX_INSTANCES) {
+ CAM_ERR(CAM_CSIPHY, "Invalid acquire count");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < csiphy_dev->acquire_count; i++) {
+ if (dev_handle ==
+ csiphy_dev->bridge_intf.device_hdl[i])
+ break;
+ }
+
+ return i;
+}
+
void cam_csiphy_query_cap(struct csiphy_device *csiphy_dev,
struct cam_csiphy_query_cap *csiphy_cap)
{
@@ -75,11 +113,56 @@ void cam_csiphy_reset(struct csiphy_device *csiphy_dev)
}
}
+static int32_t cam_csiphy_update_secure_info(
+ struct csiphy_device *csiphy_dev,
+ struct cam_csiphy_info *cam_cmd_csiphy_info,
+ struct cam_config_dev_cmd *cfg_dev)
+{
+ uint32_t clock_lane, adj_lane_mask, temp;
+ int32_t offset;
+
+ if (csiphy_dev->acquire_count >=
+ CSIPHY_MAX_INSTANCES) {
+ CAM_ERR(CAM_CSIPHY, "Invalid acquire count");
+ return -EINVAL;
+ }
+
+ offset = cam_csiphy_get_instance_offset(csiphy_dev,
+ cfg_dev->dev_handle);
+ if (offset < 0 || offset >= CSIPHY_MAX_INSTANCES) {
+ CAM_ERR(CAM_CSIPHY, "Invalid offset");
+ return -EINVAL;
+ }
+
+ if (cam_cmd_csiphy_info->combo_mode)
+ clock_lane =
+ csiphy_dev->ctrl_reg->csiphy_reg.csiphy_combo_clk_lane;
+ else
+ clock_lane =
+ csiphy_dev->ctrl_reg->csiphy_reg.csiphy_clock_lane;
+
+ adj_lane_mask = cam_cmd_csiphy_info->lane_mask & 0x1F &
+ ~clock_lane;
+ temp = adj_lane_mask & (clock_lane - 1);
+ adj_lane_mask =
+ ((adj_lane_mask & (~((clock_lane - 1)))) >> 1) | temp;
+
+ csiphy_dev->csiphy_info.secure_mode[offset] = 1;
+
+ csiphy_dev->csiphy_cpas_cp_reg_mask[offset] =
+ adj_lane_mask << (csiphy_dev->soc_info.index *
+ (CAM_CSIPHY_MAX_DPHY_LANES + CAM_CSIPHY_MAX_CPHY_LANES) +
+ (!cam_cmd_csiphy_info->csiphy_3phase) *
+ (CAM_CSIPHY_MAX_CPHY_LANES));
+
+ return 0;
+}
+
int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev,
struct cam_config_dev_cmd *cfg_dev)
{
int32_t rc = 0;
- uint64_t generic_ptr;
+ uintptr_t generic_ptr;
struct cam_packet *csl_packet = NULL;
struct cam_cmd_buf_desc *cmd_desc = NULL;
uint32_t *cmd_buf = NULL;
@@ -92,7 +175,7 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev,
}
rc = cam_mem_get_cpu_buf((int32_t) cfg_dev->packet_handle,
- (uint64_t *)&generic_ptr, &len);
+ &generic_ptr, &len);
if (rc < 0) {
CAM_ERR(CAM_CSIPHY, "Failed to get packet Mem address: %d", rc);
return rc;
@@ -105,14 +188,15 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev,
return -EINVAL;
}
- csl_packet = (struct cam_packet *)(generic_ptr + cfg_dev->offset);
+ csl_packet = (struct cam_packet *)
+ (generic_ptr + (uint32_t)cfg_dev->offset);
cmd_desc = (struct cam_cmd_buf_desc *)
((uint32_t *)&csl_packet->payload +
csl_packet->cmd_buf_offset / 4);
rc = cam_mem_get_cpu_buf(cmd_desc->mem_handle,
- (uint64_t *)&generic_ptr, &len);
+ &generic_ptr, &len);
if (rc < 0) {
CAM_ERR(CAM_CSIPHY,
"Failed to get cmd buf Mem address : %d", rc);
@@ -136,7 +220,10 @@ int32_t cam_cmd_buf_parser(struct csiphy_device *csiphy_dev,
csiphy_dev->csiphy_info.settle_time =
cam_cmd_csiphy_info->settle_time;
csiphy_dev->csiphy_info.data_rate = cam_cmd_csiphy_info->data_rate;
- csiphy_dev->csiphy_info.secure_mode = cam_cmd_csiphy_info->secure_mode;
+
+ if (cam_cmd_csiphy_info->secure_mode == 1)
+ cam_csiphy_update_secure_info(csiphy_dev,
+ cam_cmd_csiphy_info, cfg_dev);
return rc;
}
@@ -330,8 +417,10 @@ int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev)
CAM_DBG(CAM_CSIPHY, "Do Nothing");
break;
}
- usleep_range(reg_array[lane_pos][i].delay*1000,
- reg_array[lane_pos][i].delay*1000 + 1000);
+ if (reg_array[lane_pos][i].delay > 0) {
+ usleep_range(reg_array[lane_pos][i].delay*1000,
+ reg_array[lane_pos][i].delay*1000 + 10);
+ }
}
lane_mask >>= 1;
lane_pos++;
@@ -345,6 +434,7 @@ int32_t cam_csiphy_config_dev(struct csiphy_device *csiphy_dev)
void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev)
{
struct cam_hw_soc_info *soc_info;
+ int32_t i = 0;
if (csiphy_dev->csiphy_state == CAM_CSIPHY_INIT)
return;
@@ -352,13 +442,17 @@ void cam_csiphy_shutdown(struct csiphy_device *csiphy_dev)
if (csiphy_dev->csiphy_state == CAM_CSIPHY_START) {
soc_info = &csiphy_dev->soc_info;
- if (csiphy_dev->csiphy_info.secure_mode)
- cam_csiphy_notify_secure_mode(
- csiphy_dev->soc_info.index,
- CAM_SECURE_MODE_NON_SECURE);
+ for (i = 0; i < csiphy_dev->acquire_count; i++) {
+ if (csiphy_dev->csiphy_info.secure_mode[i])
+ cam_csiphy_notify_secure_mode(
+ csiphy_dev,
+ CAM_SECURE_MODE_NON_SECURE, i);
- csiphy_dev->csiphy_info.secure_mode =
- CAM_SECURE_MODE_NON_SECURE;
+ csiphy_dev->csiphy_info.secure_mode[i] =
+ CAM_SECURE_MODE_NON_SECURE;
+
+ csiphy_dev->csiphy_cpas_cp_reg_mask[i] = 0;
+ }
cam_csiphy_reset(csiphy_dev);
cam_soc_util_disable_platform_resource(soc_info, true, true);
@@ -396,7 +490,7 @@ static int32_t cam_csiphy_external_cmd(struct csiphy_device *csiphy_dev,
int32_t rc = 0;
if (copy_from_user(&cam_cmd_csiphy_info,
- (void __user *)p_submit_cmd->packet_handle,
+ u64_to_user_ptr(p_submit_cmd->packet_handle),
sizeof(struct cam_csiphy_info))) {
CAM_ERR(CAM_CSIPHY, "failed to copy cam_csiphy_info\n");
rc = -EFAULT;
@@ -456,7 +550,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
struct cam_create_dev_hdl bridge_params;
rc = copy_from_user(&csiphy_acq_dev,
- (void __user *)cmd->handle,
+ u64_to_user_ptr(cmd->handle),
sizeof(csiphy_acq_dev));
if (rc < 0) {
CAM_ERR(CAM_CSIPHY, "Failed copying from User");
@@ -466,7 +560,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
csiphy_acq_params.combo_mode = 0;
if (copy_from_user(&csiphy_acq_params,
- (void __user *)csiphy_acq_dev.info_handle,
+ u64_to_user_ptr(csiphy_acq_dev.info_handle),
sizeof(csiphy_acq_params))) {
CAM_ERR(CAM_CSIPHY,
"Failed copying from User");
@@ -522,7 +616,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
bridge_intf->session_hdl[csiphy_acq_params.combo_mode] =
csiphy_acq_dev.session_handle;
- if (copy_to_user((void __user *)cmd->handle,
+ if (copy_to_user(u64_to_user_ptr(cmd->handle),
&csiphy_acq_dev,
sizeof(struct cam_sensor_acquire_dev))) {
CAM_ERR(CAM_CSIPHY, "Failed copying from User");
@@ -540,7 +634,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
struct cam_csiphy_query_cap csiphy_cap = {0};
cam_csiphy_query_cap(csiphy_dev, &csiphy_cap);
- if (copy_to_user((void __user *)cmd->handle,
+ if (copy_to_user(u64_to_user_ptr(cmd->handle),
&csiphy_cap, sizeof(struct cam_csiphy_query_cap))) {
CAM_ERR(CAM_CSIPHY, "Failed copying from User");
rc = -EINVAL;
@@ -549,6 +643,16 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
}
break;
case CAM_STOP_DEV: {
+ int32_t offset, rc = 0;
+ struct cam_start_stop_dev_cmd config;
+
+ rc = copy_from_user(&config, u64_to_user_ptr(cmd->handle),
+ sizeof(config));
+ if (rc < 0) {
+ CAM_ERR(CAM_CSIPHY, "Failed copying from User");
+ goto release_mutex;
+ }
+
if ((csiphy_dev->csiphy_state != CAM_CSIPHY_START) ||
!csiphy_dev->start_dev_count) {
CAM_ERR(CAM_CSIPHY, "Not in right state to stop : %d",
@@ -556,20 +660,38 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
goto release_mutex;
}
+ offset = cam_csiphy_get_instance_offset(csiphy_dev,
+ config.dev_handle);
+ if (offset < 0 || offset >= CSIPHY_MAX_INSTANCES) {
+ CAM_ERR(CAM_CSIPHY, "Invalid offset");
+ goto release_mutex;
+ }
+
if (--csiphy_dev->start_dev_count) {
CAM_DBG(CAM_CSIPHY, "Stop Dev ref Cnt: %d",
csiphy_dev->start_dev_count);
+ if (csiphy_dev->csiphy_info.secure_mode[offset])
+ cam_csiphy_notify_secure_mode(
+ csiphy_dev,
+ CAM_SECURE_MODE_NON_SECURE, offset);
+
+ csiphy_dev->csiphy_info.secure_mode[offset] =
+ CAM_SECURE_MODE_NON_SECURE;
+ csiphy_dev->csiphy_cpas_cp_reg_mask[offset] = 0;
+
goto release_mutex;
}
- if (csiphy_dev->csiphy_info.secure_mode)
+ if (csiphy_dev->csiphy_info.secure_mode[offset])
cam_csiphy_notify_secure_mode(
- csiphy_dev->soc_info.index,
- CAM_SECURE_MODE_NON_SECURE);
+ csiphy_dev,
+ CAM_SECURE_MODE_NON_SECURE, offset);
- csiphy_dev->csiphy_info.secure_mode =
+ csiphy_dev->csiphy_info.secure_mode[offset] =
CAM_SECURE_MODE_NON_SECURE;
+ csiphy_dev->csiphy_cpas_cp_reg_mask[offset] = 0x0;
+
rc = cam_csiphy_disable_hw(csiphy_dev);
if (rc < 0)
CAM_ERR(CAM_CSIPHY, "Failed in csiphy release");
@@ -590,7 +712,8 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
goto release_mutex;
}
- if (copy_from_user(&release, (void __user *) cmd->handle,
+ if (copy_from_user(&release,
+ u64_to_user_ptr(cmd->handle),
sizeof(release))) {
rc = -EFAULT;
goto release_mutex;
@@ -628,7 +751,8 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
case CAM_CONFIG_DEV: {
struct cam_config_dev_cmd config;
- if (copy_from_user(&config, (void __user *)cmd->handle,
+ if (copy_from_user(&config,
+ u64_to_user_ptr(cmd->handle),
sizeof(config))) {
rc = -EFAULT;
} else {
@@ -643,12 +767,28 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
case CAM_START_DEV: {
struct cam_ahb_vote ahb_vote;
struct cam_axi_vote axi_vote;
+ struct cam_start_stop_dev_cmd config;
+ int32_t offset;
+
+ rc = copy_from_user(&config, u64_to_user_ptr(cmd->handle),
+ sizeof(config));
+ if (rc < 0) {
+ CAM_ERR(CAM_CSIPHY, "Failed copying from User");
+ goto release_mutex;
+ }
if (csiphy_dev->csiphy_state == CAM_CSIPHY_START) {
csiphy_dev->start_dev_count++;
goto release_mutex;
}
+ offset = cam_csiphy_get_instance_offset(csiphy_dev,
+ config.dev_handle);
+ if (offset < 0 || offset >= CSIPHY_MAX_INSTANCES) {
+ CAM_ERR(CAM_CSIPHY, "Invalid offset");
+ goto release_mutex;
+ }
+
ahb_vote.type = CAM_VOTE_ABSOLUTE;
ahb_vote.vote.level = CAM_SVS_VOTE;
axi_vote.compressed_bw = CAM_CPAS_DEFAULT_AXI_BW;
@@ -661,12 +801,12 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
goto release_mutex;
}
- if (csiphy_dev->csiphy_info.secure_mode) {
+ if (csiphy_dev->csiphy_info.secure_mode[offset] == 1) {
rc = cam_csiphy_notify_secure_mode(
- csiphy_dev->soc_info.index,
- CAM_SECURE_MODE_SECURE);
+ csiphy_dev,
+ CAM_SECURE_MODE_SECURE, offset);
if (rc < 0)
- csiphy_dev->csiphy_info.secure_mode =
+ csiphy_dev->csiphy_info.secure_mode[offset] =
CAM_SECURE_MODE_NON_SECURE;
}
@@ -694,7 +834,7 @@ int32_t cam_csiphy_core_cfg(void *phy_dev,
struct cam_config_dev_cmd submit_cmd;
if (copy_from_user(&submit_cmd,
- (void __user *)cmd->handle,
+ u64_to_user_ptr(cmd->handle),
sizeof(struct cam_config_dev_cmd))) {
CAM_ERR(CAM_CSIPHY, "failed copy config ext\n");
rc = -EFAULT;