diff --git a/drivers/cam_icp/fw_inc/hfi_intf.h b/drivers/cam_icp/fw_inc/hfi_intf.h index 01777b831fab..e3af27e0f820 100644 --- a/drivers/cam_icp/fw_inc/hfi_intf.h +++ b/drivers/cam_icp/fw_inc/hfi_intf.h @@ -33,7 +33,6 @@ struct hfi_mem { * @qdss: qdss mapped memory for fw * @io_mem: io memory info * @io_mem2: 2nd io memory info - * @icp_base: icp base address */ struct hfi_mem_info { struct hfi_mem qtbl; @@ -46,17 +45,18 @@ struct hfi_mem_info { struct hfi_mem qdss; struct hfi_mem io_mem; struct hfi_mem io_mem2; - void __iomem *icp_base; }; /** * struct hfi_ops * @irq_raise: called to raise H2ICP interrupt * @irq_enable: called to enable interrupts from ICP + * @iface_addr: called to get interface registers base address */ struct hfi_ops { void (*irq_raise)(void *data); void (*irq_enable)(void *data); + void __iomem *(*iface_addr)(void *data); }; /** @@ -84,12 +84,11 @@ int hfi_read_message(uint32_t *pmsg, uint8_t q_id, uint32_t *words_read); * @hfi_ops: processor-specific hfi ops * @priv: device private data * @event_driven_mode: event mode - * @icp_base: icp base address * * Returns success(zero)/failure(non zero) */ -int cam_hfi_init(struct hfi_mem_info *hfi_mem, struct hfi_ops *hfi_ops, - void *priv, uint8_t event_driven_mode, void *__iomem icp_base); +int cam_hfi_init(struct hfi_mem_info *hfi_mem, const struct hfi_ops *hfi_ops, + void *priv, uint8_t event_driven_mode); /** * hfi_get_hw_caps() - hardware capabilities from firmware @@ -110,7 +109,7 @@ void hfi_send_system_cmd(uint32_t type, uint64_t data, uint32_t size); /** * cam_hfi_deinit() - cleanup HFI */ -void cam_hfi_deinit(void __iomem *icp_base); +void cam_hfi_deinit(void); /** * hfi_set_debug_level() - set debug level * @a5_dbg_type: 1 for debug_q & 2 for qdss @@ -152,11 +151,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 * * Returns success(zero)/failure(non zero) */ -int cam_hfi_resume(struct hfi_mem_info *hfi_mem, void __iomem *icp_base); +int cam_hfi_resume(struct hfi_mem_info *hfi_mem); /** * 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 c96080bd67fb..cfb459d27bb8 100644 --- a/drivers/cam_icp/fw_inc/hfi_reg.h +++ b/drivers/cam_icp/fw_inc/hfi_reg.h @@ -9,27 +9,24 @@ #include #include "hfi_intf.h" -/* start of ICP CSR registers */ -#define HFI_REG_A5_HW_VERSION 0x0 +/* general purpose registers */ +#define GEN_PURPOSE_REG(n) (n * 4) -/* general purpose registers from */ -#define HFI_REG_FW_VERSION 0x44 -#define HFI_REG_HOST_ICP_INIT_REQUEST 0x48 -#define HFI_REG_ICP_HOST_INIT_RESPONSE 0x4C -#define HFI_REG_SHARED_MEM_PTR 0x50 -#define HFI_REG_SHARED_MEM_SIZE 0x54 -#define HFI_REG_QTBL_PTR 0x58 -#define HFI_REG_UNCACHED_HEAP_PTR 0x5C -#define HFI_REG_UNCACHED_HEAP_SIZE 0x60 -#define HFI_REG_QDSS_IOVA 0x6C -#define HFI_REG_SFR_PTR 0x68 -#define HFI_REG_QDSS_IOVA_SIZE 0x70 -#define HFI_REG_IO_REGION_IOVA 0x74 -#define HFI_REG_IO_REGION_SIZE 0x78 -#define HFI_REG_IO2_REGION_IOVA 0x7C -#define HFI_REG_IO2_REGION_SIZE 0x80 - -/* end of ICP CSR registers */ +#define HFI_REG_FW_VERSION GEN_PURPOSE_REG(1) +#define HFI_REG_HOST_ICP_INIT_REQUEST GEN_PURPOSE_REG(2) +#define HFI_REG_ICP_HOST_INIT_RESPONSE GEN_PURPOSE_REG(3) +#define HFI_REG_SHARED_MEM_PTR GEN_PURPOSE_REG(4) +#define HFI_REG_SHARED_MEM_SIZE GEN_PURPOSE_REG(5) +#define HFI_REG_QTBL_PTR GEN_PURPOSE_REG(6) +#define HFI_REG_UNCACHED_HEAP_PTR GEN_PURPOSE_REG(7) +#define HFI_REG_UNCACHED_HEAP_SIZE GEN_PURPOSE_REG(8) +#define HFI_REG_SFR_PTR GEN_PURPOSE_REG(10) +#define HFI_REG_QDSS_IOVA GEN_PURPOSE_REG(11) +#define HFI_REG_QDSS_IOVA_SIZE GEN_PURPOSE_REG(12) +#define HFI_REG_IO_REGION_IOVA GEN_PURPOSE_REG(13) +#define HFI_REG_IO_REGION_SIZE GEN_PURPOSE_REG(14) +#define HFI_REG_IO2_REGION_IOVA GEN_PURPOSE_REG(15) +#define HFI_REG_IO2_REGION_SIZE GEN_PURPOSE_REG(16) /* start of Queue table and queues */ #define MAX_ICP_HFI_QUEUES 4 @@ -278,7 +275,6 @@ struct hfi_qtbl { * @cmd_q_state: State of command queue * @mutex msg_q_lock: Lock for message queue * @msg_q_state: State of message queue - * @csr_base: CSR base address * @priv: device private data */ struct hfi_info { @@ -292,7 +288,6 @@ struct hfi_info { bool cmd_q_state; struct mutex msg_q_lock; bool msg_q_state; - void __iomem *csr_base; void *priv; }; diff --git a/drivers/cam_icp/hfi.c b/drivers/cam_icp/hfi.c index 32f0fe0f7810..f94301f4275b 100644 --- a/drivers/cam_icp/hfi.c +++ b/drivers/cam_icp/hfi.c @@ -51,6 +51,16 @@ static void hfi_irq_enable(struct hfi_info *hfi) hfi->ops.irq_enable(hfi->priv); } +static void __iomem *hfi_iface_addr(struct hfi_info *hfi) +{ + void __iomem *ret = NULL; + + if (hfi->ops.iface_addr) + ret = hfi->ops.iface_addr(hfi->priv); + + return IS_ERR_OR_NULL(ret) ? NULL : ret; +} + void cam_hfi_queue_dump(void) { struct hfi_qtbl *qtbl; @@ -550,12 +560,16 @@ int hfi_get_hw_caps(void *query_buf) return 0; } -int cam_hfi_resume(struct hfi_mem_info *hfi_mem, void __iomem *icp_base) +int cam_hfi_resume(struct hfi_mem_info *hfi_mem) { int rc = 0; uint32_t fw_version, status = 0; + void __iomem *icp_base = hfi_iface_addr(g_hfi); - g_hfi->csr_base = icp_base; + if (!icp_base) { + CAM_ERR(CAM_HFI, "invalid HFI interface address"); + return -EINVAL; + } if (readl_poll_timeout(icp_base + HFI_REG_ICP_HOST_INIT_RESPONSE, status, status == ICP_INIT_RESP_SUCCESS, @@ -602,15 +616,16 @@ int cam_hfi_resume(struct hfi_mem_info *hfi_mem, void __iomem *icp_base) return rc; } -int cam_hfi_init(struct hfi_mem_info *hfi_mem, struct hfi_ops *hfi_ops, - void *priv, uint8_t event_driven_mode, void __iomem *icp_base) +int cam_hfi_init(struct hfi_mem_info *hfi_mem, const struct hfi_ops *hfi_ops, + void *priv, uint8_t event_driven_mode) { int rc = 0; + uint32_t status = 0; struct hfi_qtbl *qtbl; struct hfi_qtbl_hdr *qtbl_hdr; struct hfi_q_hdr *cmd_q_hdr, *msg_q_hdr, *dbg_q_hdr; - uint32_t hw_version, fw_version, status = 0; struct sfr_buf *sfr_buffer; + void __iomem *icp_base; if (!hfi_mem || !hfi_ops || !priv) { CAM_ERR(CAM_HFI, @@ -752,6 +767,16 @@ int cam_hfi_init(struct hfi_mem_info *hfi_mem, struct hfi_ops *hfi_ops, break; } + g_hfi->ops = *hfi_ops; + g_hfi->priv = priv; + + icp_base = hfi_iface_addr(g_hfi); + if (!icp_base) { + CAM_ERR(CAM_HFI, "invalid HFI interface address"); + rc = -EINVAL; + goto regions_fail; + } + 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, @@ -792,17 +817,12 @@ int cam_hfi_init(struct hfi_mem_info *hfi_mem, struct hfi_ops *hfi_ops, goto regions_fail; } - hw_version = cam_io_r(icp_base + HFI_REG_A5_HW_VERSION); - fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION); - CAM_DBG(CAM_HFI, "hw version : : [%x], fw version : [%x]", - hw_version, fw_version); + CAM_DBG(CAM_HFI, "ICP fw version: 0x%x", + cam_io_r(icp_base + HFI_REG_FW_VERSION)); - g_hfi->csr_base = icp_base; g_hfi->hfi_state = HFI_READY; g_hfi->cmd_q_state = true; g_hfi->msg_q_state = true; - g_hfi->ops = *hfi_ops; - g_hfi->priv = priv; hfi_irq_enable(g_hfi); @@ -819,7 +839,7 @@ alloc_fail: return rc; } -void cam_hfi_deinit(void __iomem *icp_base) +void cam_hfi_deinit(void) { mutex_lock(&hfi_cmd_q_mutex); mutex_lock(&hfi_msg_q_mutex); 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 8b6b068a64cd..646fc6cef0ef 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c @@ -33,6 +33,8 @@ #define PC_POLL_DELAY_US 100 #define PC_POLL_TIMEOUT_US 10000 +#define A5_GEN_PURPOSE_REG_OFFSET 0x40 + static int cam_a5_cpas_vote(struct cam_a5_device_core_info *core_info, struct cam_icp_cpas_vote *cpas_vote) { @@ -513,6 +515,21 @@ void cam_a5_irq_enable(void *priv) ICP_SIERRA_A5_CSR_A2HOSTINTEN); } +void __iomem *cam_a5_iface_addr(void *priv) +{ + struct cam_hw_info *a5_info = priv; + void __iomem *base; + + if (!a5_info) { + CAM_ERR(CAM_ICP, "invalid A5 device info"); + return ERR_PTR(-EINVAL); + } + + base = a5_info->soc_info.reg_map[A5_SIERRA_BASE].mem_base; + + return base + A5_GEN_PURPOSE_REG_OFFSET; +} + int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, void *cmd_args, uint32_t arg_size) { diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_core.h b/drivers/cam_icp/icp_hw/a5_hw/a5_core.h index 98a18165dd0d..49ab5ab2488f 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_core.h +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.h @@ -83,6 +83,7 @@ irqreturn_t cam_a5_irq(int irq_num, void *data); void cam_a5_irq_raise(void *priv); void cam_a5_irq_enable(void *priv); +void __iomem *cam_a5_iface_addr(void *priv); /** * @brief : API to register a5 hw to platform framework. 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 ed8e9cb0b61e..f299f6bf258c 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 @@ -53,6 +53,12 @@ #define ICP_DEVICE_IDLE_TIMEOUT 400 +static const struct hfi_ops hfi_a5_ops = { + .irq_raise = cam_a5_irq_raise, + .irq_enable = cam_a5_irq_enable, + .iface_addr = cam_a5_iface_addr, +}; + static struct cam_icp_hw_mgr icp_hw_mgr; static void cam_icp_mgr_process_dbg_buf(unsigned int debug_lvl); @@ -3118,17 +3124,8 @@ static int cam_icp_mgr_icp_power_collapse(struct cam_icp_hw_mgr *hw_mgr) static int cam_icp_mgr_hfi_resume(struct cam_icp_hw_mgr *hw_mgr) { - struct cam_hw_intf *a5_dev_intf = NULL; - struct cam_hw_info *a5_dev = NULL; struct hfi_mem_info hfi_mem; - a5_dev_intf = hw_mgr->a5_dev_intf; - if (!a5_dev_intf) { - CAM_ERR(CAM_ICP, "a5_dev_intf is invalid\n"); - return -EINVAL; - } - a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv; - hfi_mem.qtbl.kva = icp_hw_mgr.hfi_mem.qtbl.kva; hfi_mem.qtbl.iova = icp_hw_mgr.hfi_mem.qtbl.iova; hfi_mem.qtbl.len = icp_hw_mgr.hfi_mem.qtbl.len; @@ -3203,8 +3200,7 @@ static int cam_icp_mgr_hfi_resume(struct cam_icp_hw_mgr *hw_mgr) hfi_mem.io_mem2.iova, hfi_mem.io_mem2.len); - return cam_hfi_resume(&hfi_mem, - a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); + return cam_hfi_resume(&hfi_mem); } static int cam_icp_retry_wait_for_abort( @@ -3479,7 +3475,6 @@ static int cam_icp_mgr_hw_close(void *hw_priv, void *hw_close_args) { struct cam_icp_hw_mgr *hw_mgr = hw_priv; 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; int rc = 0; @@ -3494,7 +3489,7 @@ static int cam_icp_mgr_hw_close(void *hw_priv, void *hw_close_args) CAM_DBG(CAM_ICP, "a5_dev_intf is NULL"); return -EINVAL; } - a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv; + fw_buf_info.kva = 0; fw_buf_info.iova = 0; fw_buf_info.len = 0; @@ -3505,8 +3500,9 @@ static int cam_icp_mgr_hw_close(void *hw_priv, void *hw_close_args) sizeof(fw_buf_info)); if (rc) CAM_ERR(CAM_ICP, "nullify the fw buf failed"); - cam_hfi_deinit( - a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); + + cam_hfi_deinit(); + irq_cb.icp_hw_mgr_cb = NULL; irq_cb.data = NULL; rc = a5_dev_intf->hw_ops.process_cmd( @@ -3624,7 +3620,7 @@ static int cam_icp_mgr_hfi_init(struct cam_icp_hw_mgr *hw_mgr) struct cam_hw_intf *a5_dev_intf = NULL; struct cam_hw_info *a5_dev = NULL; struct hfi_mem_info hfi_mem; - struct hfi_ops hfi_ops; + const struct hfi_ops *hfi_ops; a5_dev_intf = hw_mgr->a5_dev_intf; if (!a5_dev_intf) { @@ -3689,11 +3685,9 @@ static int cam_icp_mgr_hfi_init(struct cam_icp_hw_mgr *hw_mgr) hfi_mem.io_mem2.len = 0x0; } - hfi_ops.irq_raise = cam_a5_irq_raise; - hfi_ops.irq_enable = cam_a5_irq_enable; + hfi_ops = &hfi_a5_ops; - return cam_hfi_init(&hfi_mem, &hfi_ops, a5_dev, 0, - a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); + return cam_hfi_init(&hfi_mem, hfi_ops, a5_dev, 0); } static int cam_icp_mgr_send_fw_init(struct cam_icp_hw_mgr *hw_mgr) @@ -3807,7 +3801,6 @@ hw_deinit: static int cam_icp_mgr_hw_open(void *hw_mgr_priv, void *download_fw_args) { struct cam_hw_intf *a5_dev_intf = NULL; - struct cam_hw_info *a5_dev = NULL; struct cam_icp_hw_mgr *hw_mgr = hw_mgr_priv; bool icp_pc = false; int rc = 0; @@ -3827,7 +3820,7 @@ static int cam_icp_mgr_hw_open(void *hw_mgr_priv, void *download_fw_args) CAM_ERR(CAM_ICP, "a5_dev_intf is invalid"); return -EINVAL; } - a5_dev = (struct cam_hw_info *)a5_dev_intf->hw_priv; + rc = cam_icp_allocate_hfi_mem(); if (rc) goto alloc_hfi_mem_failed; @@ -3873,8 +3866,7 @@ static int cam_icp_mgr_hw_open(void *hw_mgr_priv, void *download_fw_args) return rc; fw_init_failed: - cam_hfi_deinit( - a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); + cam_hfi_deinit(); hfi_init_failed: cam_icp_mgr_proc_suspend(hw_mgr); fw_download_failed: