Pārlūkot izejas kodu

qcacmn: use distinct I/O remap to access CE register for ipq5018

In ipq5018 CE registers(0x08400000)  kept outside WCSS(0x0C000000) block.
As both regions are more than 60MB apart, not feasible to allocate
single resource which include both.
So, using a separate I/O region to access CE registers.

Change-Id: I67bb6d5ac82a1c0ed1d3e13f7776f9d69ee19956
Basamma Yakkanahalli 5 gadi atpakaļ
vecāks
revīzija
c0b1d0ebf0

+ 6 - 0
hal/wifi3.0/hal_api.h

@@ -727,6 +727,12 @@ struct hal_mem_info {
 	void *dev_base_addr;
 	/* dev base physical addr */
 	void *dev_base_paddr;
+	/* dev base ce virutal addr - applicable only for qca5018  */
+	/* In qca5018 CE register are outside wcss block */
+	/* using a separate address space to access CE registers */
+	void *dev_base_addr_ce;
+	/* dev base ce physical addr */
+	void *dev_base_paddr_ce;
 	/* Remote virtual pointer memory for HW/FW updates */
 	void *shadow_rdptr_mem_vaddr;
 	/* Remote physical pointer memory for HW/FW updates */

+ 2 - 0
hal/wifi3.0/hal_internal.h

@@ -665,6 +665,8 @@ struct hal_soc {
 
 	/* Device base address */
 	void *dev_base_addr;
+	/* Device base address for ce - qca5018 target */
+	void *dev_base_addr_ce;
 
 	/* HAL internal state for all SRNG rings.
 	 * TODO: See if this is required

+ 4 - 1
hal/wifi3.0/hal_srng.c

@@ -337,6 +337,8 @@ static void hal_target_based_configure(struct hal_soc *hal)
 #endif
 #ifdef QCA_WIFI_QCA5018
 	case TARGET_TYPE_QCA5018:
+		hal->use_register_windowing = true;
+		hal->static_window_map = true;
 		hal_qca5018_attach(hal);
 	break;
 #endif
@@ -739,7 +741,8 @@ void *hal_attach(struct hif_opaque_softc *hif_handle, qdf_device_t qdf_dev)
 		goto fail0;
 	}
 	hal->hif_handle = hif_handle;
-	hal->dev_base_addr = hif_get_dev_ba(hif_handle);
+	hal->dev_base_addr = hif_get_dev_ba(hif_handle); /* UMAC */
+	hal->dev_base_addr_ce = hif_get_dev_ba_ce(hif_handle); /* CE */
 	hal->qdf_dev = qdf_dev;
 	hal->shadow_rdptr_mem_vaddr = (uint32_t *)qdf_mem_alloc_consistent(
 		qdf_dev, qdf_dev->dev, sizeof(*(hal->shadow_rdptr_mem_vaddr)) *

+ 15 - 18
hal/wifi3.0/qca5018/hal_5018.c

@@ -111,6 +111,8 @@
 		 (UMAC_WINDOW_ADDRESS_5018 << 12) | \
 		 WINDOW_ENABLE_BIT)
 
+#define HOST_CE_MASK_VALUE 0xFF000000
+
 #include <hal_5018_tx.h>
 #include <hal_5018_rx.h>
 #include <hal_generic_api.h>
@@ -1336,26 +1338,23 @@ static inline qdf_iomem_t hal_get_window_address_5018(struct hal_soc *hal_soc,
 	qdf_iomem_t new_offset;
 
 	/*
-	 * If offset lies within DP register range, use 3rd window to write
-	 * into DP region.
-	 */
-	if ((offset ^ SEQ_WCSS_UMAC_OFFSET) < WINDOW_RANGE_MASK) {
-		new_offset = (hal_soc->dev_base_addr + (3 * WINDOW_START) +
-			  (offset & WINDOW_RANGE_MASK));
-	/*
-	 * If offset lies within CE register range, use 2nd window to write
+	 * Check if offset lies within CE register range(0x08400000)
+	 * or UMAC/DP register range (0x00A00000).
+	 * If offset  lies within CE register range, map it
 	 * into CE region.
 	 */
-	} else if ((offset ^ WFSS_CE_REG_BASE) < WINDOW_RANGE_MASK) {
-		new_offset = (hal_soc->dev_base_addr + (2 * WINDOW_START) +
-			  (offset & WINDOW_RANGE_MASK));
+	if (offset & HOST_CE_MASK_VALUE) {
+		offset = offset - WFSS_CE_REG_BASE;
+		new_offset = (hal_soc->dev_base_addr_ce + offset);
+
+		return new_offset;
 	} else {
-		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
-			  "%s: ERROR: Accessing Wrong register\n", __func__);
-		qdf_assert_always(0);
-		return 0;
+	/*
+	 * If offset lies within DP register range,
+	 * return the address as such
+	 */
+		return addr;
 	}
-	return new_offset;
 }
 
 static inline void hal_write_window_register(struct hal_soc *hal_soc)
@@ -1955,6 +1954,4 @@ void hal_qca5018_attach(struct hal_soc *hal_soc)
 	hal_soc->hw_srng_table = hw_srng_table_5018;
 	hal_soc->hal_hw_reg_offset = hal_hw_reg_offset_qca5018;
 	hal_soc->ops = &qca5018_hal_hw_txrx_ops;
-	if (hal_soc->static_window_map)
-		hal_write_window_register(hal_soc);
 }

+ 1 - 0
hif/inc/hif.h

@@ -1309,6 +1309,7 @@ void hif_allow_link_low_power_states(struct hif_opaque_softc *hif)
 #endif
 
 void *hif_get_dev_ba(struct hif_opaque_softc *hif_handle);
+void *hif_get_dev_ba_ce(struct hif_opaque_softc *hif_handle);
 
 /**
  * hif_set_initial_wakeup_cb() - set the initial wakeup event handler function

+ 2 - 1
hif/inc/reg_struct.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2020 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -660,6 +660,7 @@ struct ce_reg_def {
 	uint32_t d_HOST_IE_REG1_CE_LSB;
 	uint32_t d_HOST_IE_REG2_CE_LSB;
 	uint32_t d_HOST_IE_REG3_CE_LSB;
+	uint32_t d_HOST_CE_ADDRESS;
 };
 
 #endif

+ 6 - 2
hif/inc/target_reg_init.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2020 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -375,6 +375,9 @@ struct targetdef_s *MY_TARGET_DEF = &my_target_def;
 #if !defined(HOST_IE_REG3_CE_LSB)
 #define HOST_IE_REG3_CE_LSB 0
 #endif
+#if !defined(HOST_CE_ADDRESS)
+#define HOST_CE_ADDRESS ATH_UNSUPPORTED_REG_OFFSET
+#endif
 
 static struct ce_reg_def my_ce_reg_def = {
 	/* copy_engine.c */
@@ -460,7 +463,8 @@ static struct ce_reg_def my_ce_reg_def = {
 	.d_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES
 		= A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_ENABLES,
 	.d_A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_STATUS
-		= A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_STATUS
+		= A_WIFI_APB_3_A_WCMN_APPS_CE_INTR_STATUS,
+	.d_HOST_CE_ADDRESS = HOST_CE_ADDRESS
 };
 
 struct ce_reg_def *MY_CEREG_DEF = &my_ce_reg_def;

+ 2 - 1
hif/src/ce/ce_reg.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2019 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2020 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -210,6 +210,7 @@
 #define HOST_IE_ADDRESS_3         (scn->target_ce_def->d_HOST_IE_ADDRESS_3)
 #define HOST_IE_REG3_CE_LSB       (scn->target_ce_def->d_HOST_IE_REG3_CE_LSB)
 #define HOST_IS_ADDRESS           (scn->target_ce_def->d_HOST_IS_ADDRESS)
+#define HOST_CE_ADDRESS           (scn->target_ce_def->d_HOST_CE_ADDRESS)
 
 #define SRC_WATERMARK_LOW_SET(x) \
 	(((x) << SRC_WATERMARK_LOW_LSB) & SRC_WATERMARK_LOW_MASK)

+ 15 - 0
hif/src/hif_main.c

@@ -414,6 +414,21 @@ void *hif_get_dev_ba(struct hif_opaque_softc *hif_handle)
 }
 qdf_export_symbol(hif_get_dev_ba);
 
+/**
+ * hif_get_dev_ba_ce(): API to get device ce base address.
+ * @scn: scn
+ *
+ * Return: dev mem base address for CE
+ */
+void *hif_get_dev_ba_ce(struct hif_opaque_softc *hif_handle)
+{
+	struct hif_softc *scn = (struct hif_softc *)hif_handle;
+
+	return scn->mem_ce;
+}
+
+qdf_export_symbol(hif_get_dev_ba_ce);
+
 #ifdef WLAN_CE_INTERRUPT_THRESHOLD_CONFIG
 /**
  * hif_get_cfg_from_psoc() - Retrieve ini cfg from psoc

+ 1 - 0
hif/src/hif_main.h

@@ -173,6 +173,7 @@ struct hif_softc {
 	struct hif_config_info hif_config;
 	struct hif_target_info target_info;
 	void __iomem *mem;
+	void __iomem *mem_ce;
 	enum qdf_bus_type bus_type;
 	struct hif_bus_ops bus_ops;
 	void *ce_id_to_state[CE_COUNT_MAX];

+ 1 - 0
hif/src/pcie/if_pci.h

@@ -151,6 +151,7 @@ struct hif_pci_stats {
 struct hif_pci_softc {
 	struct HIF_CE_state ce_sc;
 	void __iomem *mem;      /* PCI address. */
+	void __iomem *mem_ce;   /* PCI address for CE. */
 	size_t mem_len;
 
 	struct device *dev;	/* For efficiency, should be first in struct */

+ 5 - 3
hif/src/qca5018def.c

@@ -157,17 +157,19 @@
 
 #define HOST_IE_ADDRESS \
 	HWIO_WFSS_CE_COMMON_R0_CE_HOST_IE_0_ADDR(\
-		WFSS_CE_COMMON_REG_REG_BASE)
+		WFSS_CE_COMMON_REG_REG_BASE_OFFS)
 #define HOST_IE_REG1_CE_LSB HWIO_WFSS_CE_COMMON_R0_CE_HOST_IE_0_SRC_RING_IE_SHFT
 #define HOST_IE_ADDRESS_2 \
 	HWIO_WFSS_CE_COMMON_R0_CE_HOST_IE_1_ADDR(\
-		WFSS_CE_COMMON_REG_REG_BASE)
+		WFSS_CE_COMMON_REG_REG_BASE_OFFS)
 #define HOST_IE_REG2_CE_LSB HWIO_WFSS_CE_COMMON_R0_CE_HOST_IE_1_STS_RING_IE_SHFT
 #define HOST_IE_ADDRESS_3 \
 	HWIO_WFSS_CE_COMMON_R0_CE_HOST_IE_0_ADDR(\
-		WFSS_CE_COMMON_REG_REG_BASE)
+		WFSS_CE_COMMON_REG_REG_BASE_OFFS)
 #define HOST_IE_REG3_CE_LSB HWIO_WFSS_CE_COMMON_R0_CE_HOST_IE_0_DST_RING_IE_SHFT
 
+#define HOST_CE_ADDRESS WFSS_CE_REG_BASE
+
 #define HOST_IE_COPY_COMPLETE_MASK MISSING
 #define SR_BA_ADDRESS MISSING
 #define SR_BA_ADDRESS_HIGH MISSING

+ 36 - 15
hif/src/snoc/if_ahb.c

@@ -495,6 +495,11 @@ void hif_ahb_disable_bus(struct hif_softc *scn)
 
 			hif_ahb_device_reset(scn);
 		}
+		if (tgt_info->target_type == TARGET_TYPE_QCA5018) {
+			iounmap(sc->mem_ce);
+			sc->mem_ce = NULL;
+			scn->mem_ce = NULL;
+		}
 		mem = (void __iomem *)sc->mem;
 		if (mem) {
 			pfrm_devm_iounmap(&pdev->dev, mem);
@@ -605,11 +610,25 @@ QDF_STATUS hif_ahb_enable_bus(struct hif_softc *ol_sc,
 	tgt_info->target_type = target_type;
 	hif_register_tbl_attach(ol_sc, hif_type);
 	hif_target_register_tbl_attach(ol_sc, target_type);
+	/*
+	 * In QCA5018 CE region moved to SOC outside WCSS block.
+	 * Allocate separate I/O remap to access CE registers.
+	 */
+	if (tgt_info->target_type == TARGET_TYPE_QCA5018) {
+		struct hif_softc *scn = HIF_GET_SOFTC(sc);
+
+		sc->mem_ce = ioremap_nocache(HOST_CE_ADDRESS, HOST_CE_SIZE);
+		if (IS_ERR(sc->mem_ce)) {
+			HIF_INFO("CE: ioremap failed\n");
+			return PTR_ERR(sc->mem_ce);
+		}
+		ol_sc->mem_ce = sc->mem_ce;
+	}
 
 	if ((tgt_info->target_type != TARGET_TYPE_QCA8074) &&
-	    (tgt_info->target_type != TARGET_TYPE_QCA8074V2) &&
-	    (tgt_info->target_type != TARGET_TYPE_QCA5018) &&
-	    (tgt_info->target_type != TARGET_TYPE_QCA6018)) {
+			(tgt_info->target_type != TARGET_TYPE_QCA8074V2) &&
+			(tgt_info->target_type != TARGET_TYPE_QCA5018) &&
+			(tgt_info->target_type != TARGET_TYPE_QCA6018)) {
 		if (hif_ahb_enable_radio(sc, pdev, id) != 0) {
 			HIF_INFO("error in enabling soc\n");
 			return -EIO;
@@ -718,22 +737,23 @@ void hif_ahb_irq_enable(struct hif_softc *scn, int ce_id)
 	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
 	struct CE_pipe_config *target_ce_conf = &hif_state->target_ce_config[ce_id];
 	struct hif_target_info *tgt_info = &scn->target_info;
+	void *mem = scn->mem_ce ? scn->mem_ce : scn->mem;
 
 	if (scn->per_ce_irq) {
 		if (target_ce_conf->pipedir & PIPEDIR_OUT) {
 			reg_offset = HOST_IE_ADDRESS;
 			qdf_spin_lock_irqsave(&hif_state->irq_reg_lock);
-			regval = hif_read32_mb(scn, scn->mem + reg_offset);
+			regval = hif_read32_mb(scn, mem + reg_offset);
 			regval |= HOST_IE_REG1_CE_BIT(ce_id);
-			hif_write32_mb(scn, scn->mem + reg_offset, regval);
+			hif_write32_mb(scn, mem + reg_offset, regval);
 			qdf_spin_unlock_irqrestore(&hif_state->irq_reg_lock);
 		}
 		if (target_ce_conf->pipedir & PIPEDIR_IN) {
 			reg_offset = HOST_IE_ADDRESS_2;
 			qdf_spin_lock_irqsave(&hif_state->irq_reg_lock);
-			regval = hif_read32_mb(scn, scn->mem + reg_offset);
+			regval = hif_read32_mb(scn, mem + reg_offset);
 			regval |= HOST_IE_REG2_CE_BIT(ce_id);
-			hif_write32_mb(scn, scn->mem + reg_offset, regval);
+			hif_write32_mb(scn, mem + reg_offset, regval);
 			if (tgt_info->target_type == TARGET_TYPE_QCA8074 ||
 			    tgt_info->target_type == TARGET_TYPE_QCA8074V2 ||
 			    tgt_info->target_type == TARGET_TYPE_QCA5018 ||
@@ -741,11 +761,11 @@ void hif_ahb_irq_enable(struct hif_softc *scn, int ce_id)
 				/* Enable destination ring interrupts for
 				 * 8074, 8074V2, 6018 and 50xx
 				 */
-				regval = hif_read32_mb(scn, scn->mem +
+				regval = hif_read32_mb(scn, mem +
 					HOST_IE_ADDRESS_3);
 				regval |= HOST_IE_REG3_CE_BIT(ce_id);
 
-				hif_write32_mb(scn, scn->mem +
+				hif_write32_mb(scn, mem +
 					       HOST_IE_ADDRESS_3, regval);
 			}
 			qdf_spin_unlock_irqrestore(&hif_state->irq_reg_lock);
@@ -769,22 +789,23 @@ void hif_ahb_irq_disable(struct hif_softc *scn, int ce_id)
 	struct HIF_CE_state *hif_state = HIF_GET_CE_STATE(scn);
 	struct CE_pipe_config *target_ce_conf = &hif_state->target_ce_config[ce_id];
 	struct hif_target_info *tgt_info = &scn->target_info;
+	void *mem = scn->mem_ce ? scn->mem_ce : scn->mem;
 
 	if (scn->per_ce_irq) {
 		if (target_ce_conf->pipedir & PIPEDIR_OUT) {
 			reg_offset = HOST_IE_ADDRESS;
 			qdf_spin_lock_irqsave(&hif_state->irq_reg_lock);
-			regval = hif_read32_mb(scn, scn->mem + reg_offset);
+			regval = hif_read32_mb(scn, mem + reg_offset);
 			regval &= ~HOST_IE_REG1_CE_BIT(ce_id);
-			hif_write32_mb(scn, scn->mem + reg_offset, regval);
+			hif_write32_mb(scn, mem + reg_offset, regval);
 			qdf_spin_unlock_irqrestore(&hif_state->irq_reg_lock);
 		}
 		if (target_ce_conf->pipedir & PIPEDIR_IN) {
 			reg_offset = HOST_IE_ADDRESS_2;
 			qdf_spin_lock_irqsave(&hif_state->irq_reg_lock);
-			regval = hif_read32_mb(scn, scn->mem + reg_offset);
+			regval = hif_read32_mb(scn, mem + reg_offset);
 			regval &= ~HOST_IE_REG2_CE_BIT(ce_id);
-			hif_write32_mb(scn, scn->mem + reg_offset, regval);
+			hif_write32_mb(scn, mem + reg_offset, regval);
 			if (tgt_info->target_type == TARGET_TYPE_QCA8074 ||
 			    tgt_info->target_type == TARGET_TYPE_QCA8074V2 ||
 			    tgt_info->target_type == TARGET_TYPE_QCA5018 ||
@@ -792,11 +813,11 @@ void hif_ahb_irq_disable(struct hif_softc *scn, int ce_id)
 				/* Disable destination ring interrupts for
 				 * 8074, 8074V2, 6018 and 50xx
 				 */
-				regval = hif_read32_mb(scn, scn->mem +
+				regval = hif_read32_mb(scn, mem +
 					HOST_IE_ADDRESS_3);
 				regval &= ~HOST_IE_REG3_CE_BIT(ce_id);
 
-				hif_write32_mb(scn, scn->mem +
+				hif_write32_mb(scn, mem +
 					       HOST_IE_ADDRESS_3, regval);
 			}
 			qdf_spin_unlock_irqrestore(&hif_state->irq_reg_lock);

+ 2 - 1
hif/src/snoc/if_ahb.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2020 The Linux Foundation. All rights reserved.
  *
  * Permission to use, copy, modify, and/or distribute this software for
  * any purpose with or without fee is hereby granted, provided that the
@@ -45,6 +45,7 @@
 #define TCSR_WCSS0_HALTACK 0x52010
 #define TCSR_WCSS1_HALTACK 0x52014
 #define ATH_AHB_RESET_WAIT_MAX 10 /* Ms */
+#define HOST_CE_SIZE 0x200000
 
 irqreturn_t hif_ahb_interrupt_handler(int irq, void *context);