diff --git a/drivers/cam_icp/fw_inc/hfi_intf.h b/drivers/cam_icp/fw_inc/hfi_intf.h index 6a5ec84824..0627623064 100644 --- a/drivers/cam_icp/fw_inc/hfi_intf.h +++ b/drivers/cam_icp/fw_inc/hfi_intf.h @@ -73,12 +73,11 @@ int hfi_read_message(uint32_t *pmsg, uint8_t q_id, uint32_t *words_read); * @event_driven_mode: event mode * @hfi_mem: hfi memory info * @icp_base: icp base address - * @debug: debug flag * * Returns success(zero)/failure(non zero) */ int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem, - void *__iomem icp_base, bool debug); + void *__iomem icp_base); /** * hfi_get_hw_caps() - hardware capabilities from firmware @@ -96,18 +95,6 @@ int hfi_get_hw_caps(void *query_caps); */ void hfi_send_system_cmd(uint32_t type, uint64_t data, uint32_t size); -/** - * cam_hfi_enable_cpu() - enable A5 CPU - * @icp_base: icp base address - */ -void cam_hfi_enable_cpu(void __iomem *icp_base); - -/** - * cam_hfi_disable_cpu() - disable A5 CPU - * @icp_base: icp base address - */ -void cam_hfi_disable_cpu(void __iomem *icp_base); - /** * cam_hfi_deinit() - cleanup HFI */ @@ -154,12 +141,10 @@ int hfi_cmd_ubwc_config(uint32_t *ubwc_cfg); * cam_hfi_resume() - function to resume * @hfi_mem: hfi memory info * @icp_base: icp base address - * @debug: debug flag * * Returns success(zero)/failure(non zero) */ -int cam_hfi_resume(struct hfi_mem_info *hfi_mem, - void __iomem *icp_base, bool debug); +int cam_hfi_resume(struct hfi_mem_info *hfi_mem, void __iomem *icp_base); /** * cam_hfi_queue_dump() - utility function to dump hfi queues diff --git a/drivers/cam_icp/fw_inc/hfi_reg.h b/drivers/cam_icp/fw_inc/hfi_reg.h index 200bfe6bc2..cf928ed1db 100644 --- a/drivers/cam_icp/fw_inc/hfi_reg.h +++ b/drivers/cam_icp/fw_inc/hfi_reg.h @@ -9,21 +9,10 @@ #include #include "hfi_intf.h" - /* start of ICP CSR registers */ #define HFI_REG_A5_HW_VERSION 0x0 -#define HFI_REG_A5_CSR_NSEC_RESET 0x4 -#define HFI_REG_A5_CSR_A5_CONTROL 0x8 -#define HFI_REG_A5_CSR_ETM 0xC #define HFI_REG_A5_CSR_A2HOSTINTEN 0x10 -#define HFI_REG_A5_CSR_A2HOSTINT 0x14 -#define HFI_REG_A5_CSR_A2HOSTINTCLR 0x18 -#define HFI_REG_A5_CSR_A2HOSTINTSTATUS 0x1C -#define HFI_REG_A5_CSR_A2HOSTINTSET 0x20 #define HFI_REG_A5_CSR_HOST2ICPINT 0x30 -#define HFI_REG_A5_CSR_A5_STATUS 0x200 -#define HFI_REG_A5_QGIC2_LM_ID 0x204 -#define HFI_REG_A5_SPARE 0x400 /* general purpose registers from */ #define HFI_REG_FW_VERSION 0x44 @@ -44,23 +33,6 @@ /* end of ICP CSR registers */ -/* flags for ICP CSR registers */ -#define ICP_FLAG_CSR_WAKE_UP_EN (1 << 4) -#define ICP_FLAG_CSR_A5_EN (1 << 9) -#define ICP_CSR_EN_CLKGATE_WFI (1 << 12) -#define ICP_CSR_EDBGRQ (1 << 14) -#define ICP_CSR_DBGSWENABLE (1 << 22) -#define ICP_CSR_A5_STATUS_WFI (1 << 7) - -#define ICP_FLAG_A5_CTRL_DBG_EN (ICP_FLAG_CSR_WAKE_UP_EN|\ - ICP_FLAG_CSR_A5_EN|\ - ICP_CSR_EDBGRQ|\ - ICP_CSR_DBGSWENABLE) - -#define ICP_FLAG_A5_CTRL_EN (ICP_FLAG_CSR_WAKE_UP_EN|\ - ICP_FLAG_CSR_A5_EN|\ - ICP_CSR_EN_CLKGATE_WFI) - /* start of Queue table and queues */ #define MAX_ICP_HFI_QUEUES 4 #define ICP_QHDR_TX_TYPE_MASK 0xFF000000 diff --git a/drivers/cam_icp/hfi.c b/drivers/cam_icp/hfi.c index b62cdf1fa9..f88450aad1 100644 --- a/drivers/cam_icp/hfi.c +++ b/drivers/cam_icp/hfi.c @@ -34,9 +34,6 @@ #define HFI_POLL_DELAY_US 100 #define HFI_POLL_TIMEOUT_US 10000 -#define HFI_MAX_PC_POLL_TRY 150 -#define HFI_POLL_TRY_SLEEP 1 - static struct hfi_info *g_hfi; unsigned int g_icp_mmu_hdl; static DEFINE_MUTEX(hfi_cmd_q_mutex); @@ -542,75 +539,13 @@ int hfi_get_hw_caps(void *query_buf) return 0; } -void cam_hfi_disable_cpu(void __iomem *icp_base) -{ - uint32_t data; - uint32_t val; - uint32_t try = 0; - - while (try < HFI_MAX_PC_POLL_TRY) { - data = cam_io_r_mb(icp_base + HFI_REG_A5_CSR_A5_STATUS); - CAM_DBG(CAM_HFI, "wfi status = %x\n", (int)data); - - if (data & ICP_CSR_A5_STATUS_WFI) - break; - /* Need to poll here to confirm that FW is going trigger wfi - * and Host can the proceed. No interrupt is expected from FW - * at this time. - */ - usleep_range(HFI_POLL_TRY_SLEEP * 1000, - (HFI_POLL_TRY_SLEEP * 1000) + 1000); - try++; - } - - val = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_CONTROL); - val &= ~(ICP_FLAG_CSR_A5_EN | ICP_FLAG_CSR_WAKE_UP_EN); - cam_io_w_mb(val, icp_base + HFI_REG_A5_CSR_A5_CONTROL); - - val = cam_io_r(icp_base + HFI_REG_A5_CSR_NSEC_RESET); - cam_io_w_mb(val, icp_base + HFI_REG_A5_CSR_NSEC_RESET); - - cam_io_w_mb((uint32_t)ICP_INIT_REQUEST_RESET, - icp_base + HFI_REG_HOST_ICP_INIT_REQUEST); - cam_io_w_mb((uint32_t)INTR_DISABLE, - icp_base + HFI_REG_A5_CSR_A2HOSTINTEN); -} - -void cam_hfi_enable_cpu(void __iomem *icp_base) -{ - cam_io_w_mb((uint32_t)ICP_FLAG_CSR_A5_EN, - icp_base + HFI_REG_A5_CSR_A5_CONTROL); - cam_io_w_mb((uint32_t)0x10, icp_base + HFI_REG_A5_CSR_NSEC_RESET); -} - -int cam_hfi_resume(struct hfi_mem_info *hfi_mem, - void __iomem *icp_base, bool debug) +int cam_hfi_resume(struct hfi_mem_info *hfi_mem, void __iomem *icp_base) { int rc = 0; - uint32_t data; uint32_t fw_version, status = 0; - cam_hfi_enable_cpu(icp_base); g_hfi->csr_base = icp_base; - if (debug) { - cam_io_w_mb(ICP_FLAG_A5_CTRL_DBG_EN, - (icp_base + HFI_REG_A5_CSR_A5_CONTROL)); - - /* Barrier needed as next write should be done after - * sucessful previous write. Next write enable clock - * gating - */ - wmb(); - - cam_io_w_mb((uint32_t)ICP_FLAG_A5_CTRL_EN, - icp_base + HFI_REG_A5_CSR_A5_CONTROL); - - } else { - cam_io_w_mb((uint32_t)ICP_FLAG_A5_CTRL_EN, - icp_base + HFI_REG_A5_CSR_A5_CONTROL); - } - if (readl_poll_timeout(icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE, status, status == ICP_INIT_RESP_SUCCESS, HFI_POLL_DELAY_US, HFI_POLL_TIMEOUT_US)) { @@ -625,9 +560,6 @@ int cam_hfi_resume(struct hfi_mem_info *hfi_mem, fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION); CAM_DBG(CAM_HFI, "fw version : [%x]", fw_version); - data = cam_io_r(icp_base + HFI_REG_A5_CSR_A5_STATUS); - CAM_DBG(CAM_HFI, "wfi status = %x", (int)data); - cam_io_w_mb((uint32_t)hfi_mem->qtbl.iova, icp_base + HFI_REG_QTBL_PTR); cam_io_w_mb((uint32_t)hfi_mem->sfr_buf.iova, icp_base + HFI_REG_SFR_PTR); @@ -661,7 +593,7 @@ int cam_hfi_resume(struct hfi_mem_info *hfi_mem, } int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem, - void __iomem *icp_base, bool debug) + void __iomem *icp_base) { int rc = 0; struct hfi_qtbl *qtbl; @@ -688,27 +620,6 @@ int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem, memcpy(&g_hfi->map, hfi_mem, sizeof(g_hfi->map)); g_hfi->hfi_state = HFI_DEINIT; - if (debug) { - cam_io_w_mb( - (uint32_t)(ICP_FLAG_CSR_A5_EN | ICP_FLAG_CSR_WAKE_UP_EN | - ICP_CSR_EDBGRQ | ICP_CSR_DBGSWENABLE), - icp_base + HFI_REG_A5_CSR_A5_CONTROL); - msleep(100); - cam_io_w_mb((uint32_t)(ICP_FLAG_CSR_A5_EN | - ICP_FLAG_CSR_WAKE_UP_EN | ICP_CSR_EN_CLKGATE_WFI), - icp_base + HFI_REG_A5_CSR_A5_CONTROL); - } else { - /* Due to hardware bug in V1 ICP clock gating has to be - * disabled, this is supposed to be fixed in V-2. But enabling - * the clock gating is causing the firmware hang, hence - * disabling the clock gating on both V1 and V2 until the - * hardware team root causes this - */ - cam_io_w_mb((uint32_t)ICP_FLAG_CSR_A5_EN | - ICP_FLAG_CSR_WAKE_UP_EN | - ICP_CSR_EN_CLKGATE_WFI, - icp_base + HFI_REG_A5_CSR_A5_CONTROL); - } qtbl = (struct hfi_qtbl *)hfi_mem->qtbl.kva; qtbl_hdr = &qtbl->q_tbl_hdr; diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c index 1ac27511f7..6b257392a3 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c @@ -13,12 +13,14 @@ #include #include #include +#include #include #include "cam_io_util.h" #include "cam_a5_hw_intf.h" #include "cam_hw.h" #include "cam_hw_intf.h" #include "a5_core.h" +#include "a5_reg.h" #include "a5_soc.h" #include "cam_soc_util.h" #include "cam_io_util.h" @@ -28,6 +30,9 @@ #include "cam_cpas_api.h" #include "cam_debug_util.h" +#define PC_POLL_DELAY_US 100 +#define PC_POLL_TIMEOUT_US 10000 + static int cam_a5_cpas_vote(struct cam_a5_device_core_info *core_info, struct cam_icp_cpas_vote *cpas_vote) { @@ -388,6 +393,60 @@ int cam_a5_deinit_hw(void *device_priv, return rc; } +static int cam_a5_power_resume(struct cam_hw_info *a5_info, bool debug_enabled) +{ + uint32_t val = A5_CSR_FULL_CPU_EN; + void __iomem *base; + + if (!a5_info) { + CAM_ERR(CAM_ICP, "invalid A5 device info"); + return -EINVAL; + } + + base = a5_info->soc_info.reg_map[A5_SIERRA_BASE].mem_base; + + cam_io_w_mb(A5_CSR_A5_CPU_EN, base + ICP_SIERRA_A5_CSR_A5_CONTROL); + cam_io_w_mb(A5_CSR_FUNC_RESET, base + ICP_SIERRA_A5_CSR_NSEC_RESET); + + if (debug_enabled) + val |= A5_CSR_FULL_DBG_EN; + + cam_io_w_mb(val, base + ICP_SIERRA_A5_CSR_A5_CONTROL); + + return 0; +} + +static int cam_a5_power_collapse(struct cam_hw_info *a5_info) +{ + uint32_t val, status = 0; + void __iomem *base; + + if (!a5_info) { + CAM_ERR(CAM_ICP, "invalid A5 device info"); + return -EINVAL; + } + + base = a5_info->soc_info.reg_map[A5_SIERRA_BASE].mem_base; + + /** + * Need to poll here to confirm that FW has triggered WFI + * and Host can then proceed. No interrupt is expected + * from FW at this time. + */ + if (readl_poll_timeout(base + ICP_SIERRA_A5_CSR_A5_STATUS, + status, status & A5_CSR_A5_STANDBYWFI, + PC_POLL_DELAY_US, PC_POLL_TIMEOUT_US)) { + CAM_ERR(CAM_ICP, "WFI poll timed out: status=0x%08x", status); + return -ETIMEDOUT; + } + + val = cam_io_r(base + ICP_SIERRA_A5_CSR_A5_CONTROL); + val &= ~(A5_CSR_A5_CPU_EN | A5_CSR_WAKE_UP_EN); + cam_io_w_mb(val, base + ICP_SIERRA_A5_CSR_A5_CONTROL); + + return 0; +} + irqreturn_t cam_a5_irq(int irq_num, void *data) { struct cam_hw_info *a5_dev = data; @@ -458,6 +517,12 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, case CAM_ICP_A5_CMD_FW_DOWNLOAD: rc = cam_a5_download_fw(device_priv); break; + case CAM_ICP_A5_CMD_POWER_COLLAPSE: + rc = cam_a5_power_collapse(a5_dev); + break; + case CAM_ICP_A5_CMD_POWER_RESUME: + rc = cam_a5_power_resume(a5_dev, *((bool *)cmd_args)); + break; case CAM_ICP_A5_CMD_SET_FW_BUF: { struct cam_icp_a5_set_fw_buf_info *fw_buf_info = cmd_args; diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_reg.h b/drivers/cam_icp/icp_hw/a5_hw/a5_reg.h new file mode 100644 index 0000000000..049748adbe --- /dev/null +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_reg.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + */ + +#ifndef _CAM_A5_REG_H_ +#define _CAM_A5_REG_H_ + +#define ICP_SIERRA_A5_CSR_NSEC_RESET 0x4 +#define A5_CSR_FUNC_RESET (1 << 4) +#define A5_CSR_DBG_RESET (1 << 3) +#define A5_CSR_CPU_RESET (1 << 2) + +#define ICP_SIERRA_A5_CSR_A5_CONTROL 0x8 +#define A5_CSR_DBGSWENABLE (1 << 22) +#define A5_CSR_EDBGRQ (1 << 14) +#define A5_CSR_EN_CLKGATE_WFI (1 << 12) +#define A5_CSR_A5_CPU_EN (1 << 9) +#define A5_CSR_WAKE_UP_EN (1 << 4) + +#define A5_CSR_FULL_DBG_EN (A5_CSR_DBGSWENABLE | A5_CSR_EDBGRQ) +#define A5_CSR_FULL_CPU_EN (A5_CSR_A5_CPU_EN | \ + A5_CSR_WAKE_UP_EN | \ + A5_CSR_EN_CLKGATE_WFI) + +#define ICP_SIERRA_A5_CSR_A5_STATUS 0x200 +#define A5_CSR_A5_STANDBYWFI (1 << 7) + +#endif /* _CAM_A5_REG_H_ */ diff --git a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c index 3ba1732810..9be1a940fe 100644 --- a/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c +++ b/drivers/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c @@ -3054,32 +3054,63 @@ static int cam_icp_mgr_hw_close_k(void *hw_priv, void *hw_close_args) } -static int cam_icp_mgr_icp_power_collapse(struct cam_icp_hw_mgr *hw_mgr) +static int cam_icp_mgr_proc_resume(struct cam_icp_hw_mgr *hw_mgr) { - int rc; - struct cam_hw_intf *a5_dev_intf = NULL; - struct cam_hw_info *a5_dev = NULL; + struct cam_hw_intf *icp_dev_intf = hw_mgr->a5_dev_intf; - CAM_DBG(CAM_PERF, "ENTER"); - - a5_dev_intf = hw_mgr->a5_dev_intf; - if (!a5_dev_intf) { - CAM_ERR(CAM_ICP, "a5_dev_intf is invalid\n"); + if (!icp_dev_intf) return -EINVAL; - } - a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv; + + return icp_dev_intf->hw_ops.process_cmd(icp_dev_intf->hw_priv, + CAM_ICP_A5_CMD_POWER_RESUME, + &hw_mgr->a5_jtag_debug, + sizeof(hw_mgr->a5_jtag_debug)); +} + +static void cam_icp_mgr_proc_suspend(struct cam_icp_hw_mgr *hw_mgr) +{ + struct cam_hw_intf *icp_dev_intf = hw_mgr->a5_dev_intf; + + if (!icp_dev_intf) + return; + + icp_dev_intf->hw_ops.process_cmd(icp_dev_intf->hw_priv, + CAM_ICP_A5_CMD_POWER_COLLAPSE, + NULL, 0); +} + +static int __power_collapse(struct cam_icp_hw_mgr *hw_mgr) +{ + int rc = 0; if (!hw_mgr->icp_pc_flag || atomic_read(&hw_mgr->recovery)) { - cam_hfi_disable_cpu( - a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); + cam_icp_mgr_proc_suspend(hw_mgr); rc = cam_icp_mgr_hw_close_k(hw_mgr, NULL); } else { CAM_DBG(CAM_PERF, "Sending PC prep ICP PC enabled"); rc = cam_icp_mgr_send_pc_prep(hw_mgr); - cam_hfi_disable_cpu( - a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); + cam_icp_mgr_proc_suspend(hw_mgr); } + + return rc; +} + +static int cam_icp_mgr_icp_power_collapse(struct cam_icp_hw_mgr *hw_mgr) +{ + struct cam_hw_intf *a5_dev_intf = hw_mgr->a5_dev_intf; + int rc; + + CAM_DBG(CAM_PERF, "ENTER"); + + if (!a5_dev_intf) { + CAM_ERR(CAM_ICP, "A5 device interface is NULL"); + return -EINVAL; + } + + rc = __power_collapse(hw_mgr); + a5_dev_intf->hw_ops.deinit(a5_dev_intf->hw_priv, NULL, 0); + CAM_DBG(CAM_PERF, "EXIT"); return rc; @@ -3173,8 +3204,7 @@ static int cam_icp_mgr_hfi_resume(struct cam_icp_hw_mgr *hw_mgr) hfi_mem.io_mem2.len); return cam_hfi_resume(&hfi_mem, - a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base, - hw_mgr->a5_jtag_debug); + a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); } static int cam_icp_retry_wait_for_abort( @@ -3550,7 +3580,6 @@ static int cam_icp_mgr_fw_download(struct cam_icp_hw_mgr *hw_mgr) { int rc; struct cam_hw_intf *a5_dev_intf = NULL; - struct cam_hw_info *a5_dev = NULL; struct cam_icp_a5_set_irq_cb irq_cb; struct cam_icp_a5_set_fw_buf_info fw_buf_info; @@ -3559,7 +3588,6 @@ static int cam_icp_mgr_fw_download(struct cam_icp_hw_mgr *hw_mgr) CAM_ERR(CAM_ICP, "a5_dev_intf is invalid"); return -EINVAL; } - a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv; irq_cb.icp_hw_mgr_cb = cam_icp_hw_mgr_cb; irq_cb.data = hw_mgr; @@ -3568,7 +3596,7 @@ static int cam_icp_mgr_fw_download(struct cam_icp_hw_mgr *hw_mgr) CAM_ICP_A5_SET_IRQ_CB, &irq_cb, sizeof(irq_cb)); if (rc) - goto set_irq_failed; + return rc; fw_buf_info.kva = icp_hw_mgr.hfi_mem.fw_buf.kva; fw_buf_info.iova = icp_hw_mgr.hfi_mem.fw_buf.iova; @@ -3579,22 +3607,16 @@ static int cam_icp_mgr_fw_download(struct cam_icp_hw_mgr *hw_mgr) CAM_ICP_A5_CMD_SET_FW_BUF, &fw_buf_info, sizeof(fw_buf_info)); if (rc) - goto set_irq_failed; - - cam_hfi_enable_cpu(a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); + return rc; rc = a5_dev_intf->hw_ops.process_cmd( a5_dev_intf->hw_priv, CAM_ICP_A5_CMD_FW_DOWNLOAD, NULL, 0); if (rc) - goto fw_download_failed; + return rc; - return rc; -fw_download_failed: - cam_hfi_disable_cpu(a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); -set_irq_failed: - return rc; + return cam_icp_mgr_proc_resume(hw_mgr); } static int cam_icp_mgr_hfi_init(struct cam_icp_hw_mgr *hw_mgr) @@ -3667,8 +3689,7 @@ static int cam_icp_mgr_hfi_init(struct cam_icp_hw_mgr *hw_mgr) } return cam_hfi_init(0, &hfi_mem, - a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base, - hw_mgr->a5_jtag_debug); + a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); } static int cam_icp_mgr_send_fw_init(struct cam_icp_hw_mgr *hw_mgr) @@ -3760,14 +3781,22 @@ static int cam_icp_mgr_icp_resume(struct cam_icp_hw_mgr *hw_mgr) if (rc) return -EINVAL; + rc = cam_icp_mgr_proc_resume(hw_mgr); + if (rc) + goto hw_deinit; + rc = cam_icp_mgr_hfi_resume(hw_mgr); if (rc) - goto hfi_resume_failed; + goto power_collapse; CAM_DBG(CAM_ICP, "Exit"); return rc; -hfi_resume_failed: - cam_icp_mgr_icp_power_collapse(hw_mgr); + +power_collapse: + __power_collapse(hw_mgr); +hw_deinit: + a5_dev_intf->hw_ops.deinit(a5_dev_intf->hw_priv, NULL, 0); + return rc; } @@ -3843,8 +3872,7 @@ fw_init_failed: cam_hfi_deinit( a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); hfi_init_failed: - cam_hfi_disable_cpu( - a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); + cam_icp_mgr_proc_suspend(hw_mgr); fw_download_failed: cam_icp_mgr_device_deinit(hw_mgr); dev_init_fail: