Loading drivers/cam_cpas/cam_cpas_hw.c +26 −0 Original line number Diff line number Diff line Loading @@ -1544,6 +1544,7 @@ static int cam_cpas_hw_stop(void *hw_priv, void *stop_args, struct cam_cpas_private_soc *soc_private = NULL; int rc = 0; long result; int retry_camnoc_idle = 0; if (!hw_priv || !stop_args) { CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK", Loading Loading @@ -1597,6 +1598,18 @@ static int cam_cpas_hw_stop(void *hw_priv, void *stop_args, } } if (cpas_core->internal_ops.qchannel_handshake) { rc = cpas_core->internal_ops.qchannel_handshake( cpas_hw, false); if (rc) { CAM_ERR(CAM_CPAS, "failed in qchannel_handshake rc=%d", rc); retry_camnoc_idle = 1; /* Do not return error, passthrough */ } } rc = cam_cpas_soc_disable_irq(&cpas_hw->soc_info); if (rc) { CAM_ERR(CAM_CPAS, "disable_irq failed, rc=%d", rc); Loading @@ -1612,6 +1625,19 @@ static int cam_cpas_hw_stop(void *hw_priv, void *stop_args, atomic_read(&cpas_core->irq_count)); } /* try again incase camnoc is still not idle */ if (cpas_core->internal_ops.qchannel_handshake && retry_camnoc_idle) { rc = cpas_core->internal_ops.qchannel_handshake( cpas_hw, false); if (rc) { CAM_ERR(CAM_CPAS, "failed in qchannel_handshake rc=%d", rc); /* Do not return error, passthrough */ } } rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info, true, false); if (rc) { Loading drivers/cam_cpas/cam_cpas_hw.h +3 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,8 @@ enum cam_cpas_access_type { * @power_off: Function pointer for hw core specific power off settings * @setup_qos_settings: Function pointer for hw to select a specific qos header * @print_poweron_settings: Function pointer for hw to print poweron settings * @qchannel_handshake: Function pointer for hw core specific qchannel * handshake settings * */ struct cam_cpas_internal_ops { Loading @@ -85,6 +87,7 @@ struct cam_cpas_internal_ops { int (*setup_qos_settings)(struct cam_hw_info *cpas_hw, uint32_t selection_mask); int (*print_poweron_settings)(struct cam_hw_info *cpas_hw); int (*qchannel_handshake)(struct cam_hw_info *cpas_hw, bool power_on); }; /** Loading drivers/cam_cpas/cam_cpas_hw_intf.h +2 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ #define CAM_CPAS_POLL_MIN_USECS 200 /* Maximum usecs to sleep while polling */ #define CAM_CPAS_POLL_MAX_USECS 250 /* Number of times to retry while polling */ #define CAM_CPAS_POLL_QH_RETRY_CNT 50 /** * enum cam_cpas_hw_type - Enum for CPAS HW type Loading drivers/cam_cpas/camss_top/cam_camsstop_hw.c +1 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,7 @@ int cam_camsstop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops) internal_ops->power_off = NULL; internal_ops->setup_qos_settings = NULL; internal_ops->print_poweron_settings = NULL; internal_ops->qchannel_handshake = NULL; return 0; } drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +62 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,8 @@ #include "cam_req_mgr_workq.h" struct cam_camnoc_info *camnoc_info; struct cam_cpas_camnoc_qchannel *qchannel_info; #define CAMNOC_SLAVE_MAX_ERR_CODE 7 static const char * const camnoc_salve_err_code[] = { Loading Loading @@ -818,11 +820,65 @@ static int cam_cpastop_poweroff(struct cam_hw_info *cpas_hw) return rc; } static int cam_cpastop_qchannel_handshake(struct cam_hw_info *cpas_hw, bool power_on) { struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info; int32_t reg_indx = cpas_core->regbase_index[CAM_CPAS_REG_CPASTOP]; uint32_t mask = 0; uint32_t wait_data, qchannel_status, qdeny; int rc = 0; if (reg_indx == -1) return -EINVAL; if (!qchannel_info) return 0; if (power_on) { /* wait for QACCEPTN in QCHANNEL status*/ mask = BIT(0); wait_data = 1; } else { /* Clear the quiecience request in QCHANNEL ctrl*/ cam_io_w_mb(0, soc_info->reg_map[reg_indx].mem_base + qchannel_info->qchannel_ctrl); /* wait for QACCEPTN and QDENY in QCHANNEL status*/ mask = BIT(1) | BIT(0); wait_data = 0; } rc = cam_io_poll_value_wmask( soc_info->reg_map[reg_indx].mem_base + qchannel_info->qchannel_status, wait_data, mask, CAM_CPAS_POLL_QH_RETRY_CNT, CAM_CPAS_POLL_MIN_USECS, CAM_CPAS_POLL_MAX_USECS); if (rc) { CAM_ERR(CAM_CPAS, "camnoc idle sequence failed, qstat 0x%x", cam_io_r(soc_info->reg_map[reg_indx].mem_base + qchannel_info->qchannel_status)); /* Do not return error, passthrough */ rc = 0; } /* check if deny bit is set */ qchannel_status = cam_io_r_mb(soc_info->reg_map[reg_indx].mem_base + qchannel_info->qchannel_status); qdeny = (qchannel_status & BIT(1)); if (!power_on && qdeny) rc = -EBUSY; return rc; } static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw, struct cam_cpas_hw_caps *hw_caps) { int rc = 0; struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info; qchannel_info = NULL; CAM_DBG(CAM_CPAS, "hw_version=0x%x Camera Version %d.%d.%d, cpas version %d.%d.%d", Loading Loading @@ -864,18 +920,23 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw, break; case CAM_CPAS_TITAN_580_V100: camnoc_info = &cam580_cpas100_camnoc_info; qchannel_info = &cam580_cpas100_qchannel_info; break; case CAM_CPAS_TITAN_540_V100: camnoc_info = &cam540_cpas100_camnoc_info; qchannel_info = &cam540_cpas100_qchannel_info; break; case CAM_CPAS_TITAN_520_V100: camnoc_info = &cam520_cpas100_camnoc_info; qchannel_info = &cam520_cpas100_qchannel_info; break; case CAM_CPAS_TITAN_545_V100: camnoc_info = &cam545_cpas100_camnoc_info; qchannel_info = &cam545_cpas100_qchannel_info; break; case CAM_CPAS_TITAN_570_V200: camnoc_info = &cam570_cpas200_camnoc_info; qchannel_info = &cam570_cpas200_qchannel_info; break; case CAM_CPAS_TITAN_680_V100: camnoc_info = &cam680_cpas100_camnoc_info; Loading Loading @@ -961,6 +1022,7 @@ int cam_cpastop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops) internal_ops->setup_qos_settings = cam_cpastop_setup_qos_settings; internal_ops->print_poweron_settings = cam_cpastop_print_poweron_settings; internal_ops->qchannel_handshake = cam_cpastop_qchannel_handshake; return 0; } Loading
drivers/cam_cpas/cam_cpas_hw.c +26 −0 Original line number Diff line number Diff line Loading @@ -1544,6 +1544,7 @@ static int cam_cpas_hw_stop(void *hw_priv, void *stop_args, struct cam_cpas_private_soc *soc_private = NULL; int rc = 0; long result; int retry_camnoc_idle = 0; if (!hw_priv || !stop_args) { CAM_ERR(CAM_CPAS, "Invalid arguments %pK %pK", Loading Loading @@ -1597,6 +1598,18 @@ static int cam_cpas_hw_stop(void *hw_priv, void *stop_args, } } if (cpas_core->internal_ops.qchannel_handshake) { rc = cpas_core->internal_ops.qchannel_handshake( cpas_hw, false); if (rc) { CAM_ERR(CAM_CPAS, "failed in qchannel_handshake rc=%d", rc); retry_camnoc_idle = 1; /* Do not return error, passthrough */ } } rc = cam_cpas_soc_disable_irq(&cpas_hw->soc_info); if (rc) { CAM_ERR(CAM_CPAS, "disable_irq failed, rc=%d", rc); Loading @@ -1612,6 +1625,19 @@ static int cam_cpas_hw_stop(void *hw_priv, void *stop_args, atomic_read(&cpas_core->irq_count)); } /* try again incase camnoc is still not idle */ if (cpas_core->internal_ops.qchannel_handshake && retry_camnoc_idle) { rc = cpas_core->internal_ops.qchannel_handshake( cpas_hw, false); if (rc) { CAM_ERR(CAM_CPAS, "failed in qchannel_handshake rc=%d", rc); /* Do not return error, passthrough */ } } rc = cam_cpas_soc_disable_resources(&cpas_hw->soc_info, true, false); if (rc) { Loading
drivers/cam_cpas/cam_cpas_hw.h +3 −0 Original line number Diff line number Diff line Loading @@ -70,6 +70,8 @@ enum cam_cpas_access_type { * @power_off: Function pointer for hw core specific power off settings * @setup_qos_settings: Function pointer for hw to select a specific qos header * @print_poweron_settings: Function pointer for hw to print poweron settings * @qchannel_handshake: Function pointer for hw core specific qchannel * handshake settings * */ struct cam_cpas_internal_ops { Loading @@ -85,6 +87,7 @@ struct cam_cpas_internal_ops { int (*setup_qos_settings)(struct cam_hw_info *cpas_hw, uint32_t selection_mask); int (*print_poweron_settings)(struct cam_hw_info *cpas_hw); int (*qchannel_handshake)(struct cam_hw_info *cpas_hw, bool power_on); }; /** Loading
drivers/cam_cpas/cam_cpas_hw_intf.h +2 −0 Original line number Diff line number Diff line Loading @@ -19,6 +19,8 @@ #define CAM_CPAS_POLL_MIN_USECS 200 /* Maximum usecs to sleep while polling */ #define CAM_CPAS_POLL_MAX_USECS 250 /* Number of times to retry while polling */ #define CAM_CPAS_POLL_QH_RETRY_CNT 50 /** * enum cam_cpas_hw_type - Enum for CPAS HW type Loading
drivers/cam_cpas/camss_top/cam_camsstop_hw.c +1 −0 Original line number Diff line number Diff line Loading @@ -79,6 +79,7 @@ int cam_camsstop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops) internal_ops->power_off = NULL; internal_ops->setup_qos_settings = NULL; internal_ops->print_poweron_settings = NULL; internal_ops->qchannel_handshake = NULL; return 0; }
drivers/cam_cpas/cpas_top/cam_cpastop_hw.c +62 −0 Original line number Diff line number Diff line Loading @@ -34,6 +34,8 @@ #include "cam_req_mgr_workq.h" struct cam_camnoc_info *camnoc_info; struct cam_cpas_camnoc_qchannel *qchannel_info; #define CAMNOC_SLAVE_MAX_ERR_CODE 7 static const char * const camnoc_salve_err_code[] = { Loading Loading @@ -818,11 +820,65 @@ static int cam_cpastop_poweroff(struct cam_hw_info *cpas_hw) return rc; } static int cam_cpastop_qchannel_handshake(struct cam_hw_info *cpas_hw, bool power_on) { struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info; struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info; int32_t reg_indx = cpas_core->regbase_index[CAM_CPAS_REG_CPASTOP]; uint32_t mask = 0; uint32_t wait_data, qchannel_status, qdeny; int rc = 0; if (reg_indx == -1) return -EINVAL; if (!qchannel_info) return 0; if (power_on) { /* wait for QACCEPTN in QCHANNEL status*/ mask = BIT(0); wait_data = 1; } else { /* Clear the quiecience request in QCHANNEL ctrl*/ cam_io_w_mb(0, soc_info->reg_map[reg_indx].mem_base + qchannel_info->qchannel_ctrl); /* wait for QACCEPTN and QDENY in QCHANNEL status*/ mask = BIT(1) | BIT(0); wait_data = 0; } rc = cam_io_poll_value_wmask( soc_info->reg_map[reg_indx].mem_base + qchannel_info->qchannel_status, wait_data, mask, CAM_CPAS_POLL_QH_RETRY_CNT, CAM_CPAS_POLL_MIN_USECS, CAM_CPAS_POLL_MAX_USECS); if (rc) { CAM_ERR(CAM_CPAS, "camnoc idle sequence failed, qstat 0x%x", cam_io_r(soc_info->reg_map[reg_indx].mem_base + qchannel_info->qchannel_status)); /* Do not return error, passthrough */ rc = 0; } /* check if deny bit is set */ qchannel_status = cam_io_r_mb(soc_info->reg_map[reg_indx].mem_base + qchannel_info->qchannel_status); qdeny = (qchannel_status & BIT(1)); if (!power_on && qdeny) rc = -EBUSY; return rc; } static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw, struct cam_cpas_hw_caps *hw_caps) { int rc = 0; struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info; qchannel_info = NULL; CAM_DBG(CAM_CPAS, "hw_version=0x%x Camera Version %d.%d.%d, cpas version %d.%d.%d", Loading Loading @@ -864,18 +920,23 @@ static int cam_cpastop_init_hw_version(struct cam_hw_info *cpas_hw, break; case CAM_CPAS_TITAN_580_V100: camnoc_info = &cam580_cpas100_camnoc_info; qchannel_info = &cam580_cpas100_qchannel_info; break; case CAM_CPAS_TITAN_540_V100: camnoc_info = &cam540_cpas100_camnoc_info; qchannel_info = &cam540_cpas100_qchannel_info; break; case CAM_CPAS_TITAN_520_V100: camnoc_info = &cam520_cpas100_camnoc_info; qchannel_info = &cam520_cpas100_qchannel_info; break; case CAM_CPAS_TITAN_545_V100: camnoc_info = &cam545_cpas100_camnoc_info; qchannel_info = &cam545_cpas100_qchannel_info; break; case CAM_CPAS_TITAN_570_V200: camnoc_info = &cam570_cpas200_camnoc_info; qchannel_info = &cam570_cpas200_qchannel_info; break; case CAM_CPAS_TITAN_680_V100: camnoc_info = &cam680_cpas100_camnoc_info; Loading Loading @@ -961,6 +1022,7 @@ int cam_cpastop_get_internal_ops(struct cam_cpas_internal_ops *internal_ops) internal_ops->setup_qos_settings = cam_cpastop_setup_qos_settings; internal_ops->print_poweron_settings = cam_cpastop_print_poweron_settings; internal_ops->qchannel_handshake = cam_cpastop_qchannel_handshake; return 0; }