From f42f7b1e9ac0ba8b7a668eb85e298e011a8dea97 Mon Sep 17 00:00:00 2001 From: Fernando Pacheco Date: Fri, 17 Jul 2020 16:18:06 -0700 Subject: [PATCH] msm: camera: icp: Adapt HFI to processor specific irq management The steps to enable and send interrupts will differ between processors. Pull this logic out of the HFI and out to the devices, so that we can adapt to the specific irq management of any processor. CRs-Fixed: 2722486 Change-Id: I2a889b91ec13295aa14bb2b16252332482a1225a Signed-off-by: Fernando Pacheco --- drivers/cam_icp/fw_inc/hfi_intf.h | 18 ++++++++-- drivers/cam_icp/fw_inc/hfi_reg.h | 19 +++------- drivers/cam_icp/hfi.c | 35 ++++++++++++++----- drivers/cam_icp/icp_hw/a5_hw/a5_core.c | 28 +++++++++++++++ drivers/cam_icp/icp_hw/a5_hw/a5_core.h | 5 ++- drivers/cam_icp/icp_hw/a5_hw/a5_reg.h | 8 +++++ .../icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c | 8 +++-- 7 files changed, 92 insertions(+), 29 deletions(-) diff --git a/drivers/cam_icp/fw_inc/hfi_intf.h b/drivers/cam_icp/fw_inc/hfi_intf.h index 062762306454..01777b831fab 100644 --- a/drivers/cam_icp/fw_inc/hfi_intf.h +++ b/drivers/cam_icp/fw_inc/hfi_intf.h @@ -49,6 +49,16 @@ struct hfi_mem_info { void __iomem *icp_base; }; +/** + * struct hfi_ops + * @irq_raise: called to raise H2ICP interrupt + * @irq_enable: called to enable interrupts from ICP + */ +struct hfi_ops { + void (*irq_raise)(void *data); + void (*irq_enable)(void *data); +}; + /** * hfi_write_cmd() - function for hfi write * @cmd_ptr: pointer to command data for hfi write @@ -70,14 +80,16 @@ int hfi_read_message(uint32_t *pmsg, uint8_t q_id, uint32_t *words_read); /** * hfi_init() - function initialize hfi after firmware download - * @event_driven_mode: event mode * @hfi_mem: hfi memory info + * @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(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem, - void *__iomem icp_base); +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); /** * hfi_get_hw_caps() - hardware capabilities from firmware diff --git a/drivers/cam_icp/fw_inc/hfi_reg.h b/drivers/cam_icp/fw_inc/hfi_reg.h index cf928ed1db43..c96080bd67fb 100644 --- a/drivers/cam_icp/fw_inc/hfi_reg.h +++ b/drivers/cam_icp/fw_inc/hfi_reg.h @@ -11,8 +11,6 @@ /* start of ICP CSR registers */ #define HFI_REG_A5_HW_VERSION 0x0 -#define HFI_REG_A5_CSR_A2HOSTINTEN 0x10 -#define HFI_REG_A5_CSR_HOST2ICPINT 0x30 /* general purpose registers from */ #define HFI_REG_FW_VERSION 0x44 @@ -97,19 +95,6 @@ enum reg_settings { SET_WM = 1024 }; -/** - * @INTR_DISABLE: Disable interrupt - * @INTR_ENABLE: Enable interrupt - * @INTR_ENABLE_WD0: Enable WD0 - * @INTR_ENABLE_WD1: Enable WD1 - */ -enum intr_status { - INTR_DISABLE, - INTR_ENABLE, - INTR_ENABLE_WD0, - INTR_ENABLE_WD1 = 0x4 -}; - /** * @ICP_INIT_RESP_RESET: reset init state * @ICP_INIT_RESP_SUCCESS: init success @@ -284,6 +269,7 @@ struct hfi_qtbl { /** * struct hfi_info * @map: Hfi shared memory info + * @ops: processor-specific ops * @smem_size: Shared memory size * @uncachedheap_size: uncached heap size * @msgpacket_buf: message buffer @@ -293,9 +279,11 @@ struct hfi_qtbl { * @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 { struct hfi_mem_info map; + struct hfi_ops ops; uint32_t smem_size; uint32_t uncachedheap_size; uint32_t msgpacket_buf[ICP_HFI_MAX_MSG_SIZE_IN_WORDS]; @@ -305,6 +293,7 @@ struct hfi_info { struct mutex msg_q_lock; bool msg_q_state; void __iomem *csr_base; + void *priv; }; #endif /* _CAM_HFI_REG_H_ */ diff --git a/drivers/cam_icp/hfi.c b/drivers/cam_icp/hfi.c index f88450aad166..32f0fe0f7810 100644 --- a/drivers/cam_icp/hfi.c +++ b/drivers/cam_icp/hfi.c @@ -39,6 +39,18 @@ unsigned int g_icp_mmu_hdl; static DEFINE_MUTEX(hfi_cmd_q_mutex); static DEFINE_MUTEX(hfi_msg_q_mutex); +static void hfi_irq_raise(struct hfi_info *hfi) +{ + if (hfi->ops.irq_raise) + hfi->ops.irq_raise(hfi->priv); +} + +static void hfi_irq_enable(struct hfi_info *hfi) +{ + if (hfi->ops.irq_enable) + hfi->ops.irq_enable(hfi->priv); +} + void cam_hfi_queue_dump(void) { struct hfi_qtbl *qtbl; @@ -160,8 +172,7 @@ int hfi_write_cmd(void *cmd_ptr) * firmware to process */ wmb(); - cam_io_w_mb((uint32_t)INTR_ENABLE, - g_hfi->csr_base + HFI_REG_A5_CSR_HOST2ICPINT); + hfi_irq_raise(g_hfi); err: mutex_unlock(&hfi_cmd_q_mutex); return rc; @@ -554,8 +565,7 @@ int cam_hfi_resume(struct hfi_mem_info *hfi_mem, void __iomem *icp_base) return -ETIMEDOUT; } - cam_io_w_mb((uint32_t)(INTR_ENABLE|INTR_ENABLE_WD0), - icp_base + HFI_REG_A5_CSR_A2HOSTINTEN); + hfi_irq_enable(g_hfi); fw_version = cam_io_r(icp_base + HFI_REG_FW_VERSION); CAM_DBG(CAM_HFI, "fw version : [%x]", fw_version); @@ -592,8 +602,8 @@ int cam_hfi_resume(struct hfi_mem_info *hfi_mem, void __iomem *icp_base) return rc; } -int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem, - void __iomem *icp_base) +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 rc = 0; struct hfi_qtbl *qtbl; @@ -602,6 +612,13 @@ int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem, uint32_t hw_version, fw_version, status = 0; struct sfr_buf *sfr_buffer; + if (!hfi_mem || !hfi_ops || !priv) { + CAM_ERR(CAM_HFI, + "invalid arg: hfi_mem=%pK hfi_ops=%pK priv=%pK", + hfi_mem, hfi_ops, priv); + return -EINVAL; + } + mutex_lock(&hfi_cmd_q_mutex); mutex_lock(&hfi_msg_q_mutex); @@ -784,8 +801,10 @@ int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem, g_hfi->hfi_state = HFI_READY; g_hfi->cmd_q_state = true; g_hfi->msg_q_state = true; - cam_io_w_mb((uint32_t)(INTR_ENABLE|INTR_ENABLE_WD0), - icp_base + HFI_REG_A5_CSR_A2HOSTINTEN); + g_hfi->ops = *hfi_ops; + g_hfi->priv = priv; + + hfi_irq_enable(g_hfi); mutex_unlock(&hfi_cmd_q_mutex); mutex_unlock(&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 6b257392a3ec..8b6b068a64cd 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_core.c +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.c @@ -485,6 +485,34 @@ irqreturn_t cam_a5_irq(int irq_num, void *data) return IRQ_HANDLED; } +void cam_a5_irq_raise(void *priv) +{ + struct cam_hw_info *a5_info = priv; + + if (!a5_info) { + CAM_ERR(CAM_ICP, "invalid A5 device info"); + return; + } + + cam_io_w_mb(A5_HOSTINT, + a5_info->soc_info.reg_map[A5_SIERRA_BASE].mem_base + + ICP_SIERRA_A5_CSR_HOST2ICPINT); +} + +void cam_a5_irq_enable(void *priv) +{ + struct cam_hw_info *a5_info = priv; + + if (!a5_info) { + CAM_ERR(CAM_ICP, "invalid A5 device info"); + return; + } + + cam_io_w_mb(A5_WDT_WS0EN | A5_A2HOSTINTEN, + a5_info->soc_info.reg_map[A5_SIERRA_BASE].mem_base + + ICP_SIERRA_A5_CSR_A2HOSTINTEN); +} + 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 f6edebbc3141..98a18165dd0d 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_core.h +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_core.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef CAM_A5_CORE_H @@ -81,6 +81,9 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type, irqreturn_t cam_a5_irq(int irq_num, void *data); +void cam_a5_irq_raise(void *priv); +void cam_a5_irq_enable(void *priv); + /** * @brief : API to register a5 hw to platform framework. * @return struct platform_device pointer on on success, or ERR_PTR() on error. diff --git a/drivers/cam_icp/icp_hw/a5_hw/a5_reg.h b/drivers/cam_icp/icp_hw/a5_hw/a5_reg.h index 049748adbe1a..0a8e38d9ad52 100644 --- a/drivers/cam_icp/icp_hw/a5_hw/a5_reg.h +++ b/drivers/cam_icp/icp_hw/a5_hw/a5_reg.h @@ -23,6 +23,14 @@ A5_CSR_WAKE_UP_EN | \ A5_CSR_EN_CLKGATE_WFI) +#define ICP_SIERRA_A5_CSR_A2HOSTINTEN 0x10 +#define A5_WDT_WS1EN (1 << 2) +#define A5_WDT_WS0EN (1 << 1) +#define A5_A2HOSTINTEN (1 << 0) + +#define ICP_SIERRA_A5_CSR_HOST2ICPINT 0x30 +#define A5_HOSTINT (1 << 0) + #define ICP_SIERRA_A5_CSR_A5_STATUS 0x200 #define A5_CSR_A5_STANDBYWFI (1 << 7) 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 9be1a940fe6d..ed8e9cb0b61e 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 @@ -3624,6 +3624,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; a5_dev_intf = hw_mgr->a5_dev_intf; if (!a5_dev_intf) { @@ -3688,8 +3689,11 @@ static int cam_icp_mgr_hfi_init(struct cam_icp_hw_mgr *hw_mgr) hfi_mem.io_mem2.len = 0x0; } - return cam_hfi_init(0, &hfi_mem, - a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base); + hfi_ops.irq_raise = cam_a5_irq_raise; + hfi_ops.irq_enable = cam_a5_irq_enable; + + return cam_hfi_init(&hfi_mem, &hfi_ops, a5_dev, 0, + 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)