diff options
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.c | 212 |
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; |