Browse Source

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 <[email protected]>
Fernando Pacheco 5 years ago
parent
commit
f42f7b1e9a

+ 15 - 3
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

+ 4 - 15
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_ */

+ 27 - 8
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);

+ 28 - 0
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)
 {

+ 4 - 1
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.

+ 8 - 0
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)
 

+ 6 - 2
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)