Эх сурвалжийг харах

qcacmn: Enable device force wake recipe in driver

Enable force wake recipe feature DEVICE_FORCE_WAKE_ENABLE
and disable the generic shadow register write feature
GENERIC_SHADOW_REGISTER_ACCESS_ENABLE.
Force wake recipe will be used to write to the REO remap
control registers by waking up the UMAC instead of using
shadow register writes.
Assert soc wake reg and poll on the scratch reg to check
if UMAC is awake.
Enable HIF_REG_WINDOW_SUPPORT to enable windowed reg
read/write in HIF layer.

Change-Id: Ib696e27e19a07c0084c097b95b7780b56e643c8b
CRs-Fixed: 2850590
Nisha Menon 4 жил өмнө
parent
commit
8d4b739df0

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

@@ -50,18 +50,6 @@
 #define SHADOW_REGISTER(x) 0
 #endif /* QCA_WIFI_QCA6390 || QCA_WIFI_QCA6490 || QCA_WIFI_QCA6750 */
 
-#define MAX_UNWINDOWED_ADDRESS 0x80000
-#if defined(QCA_WIFI_QCA6390) || defined(QCA_WIFI_QCA6490) || \
-    defined(QCA_WIFI_QCN9000) || defined(QCA_WIFI_QCA6750)
-#define WINDOW_ENABLE_BIT 0x40000000
-#else
-#define WINDOW_ENABLE_BIT 0x80000000
-#endif
-#define WINDOW_REG_ADDRESS 0x310C
-#define WINDOW_SHIFT 19
-#define WINDOW_VALUE_MASK 0x3F
-#define WINDOW_START MAX_UNWINDOWED_ADDRESS
-#define WINDOW_RANGE_MASK 0x7FFFF
 /*
  * BAR + 4K is always accessible, any access outside this
  * space requires force wake procedure.

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

@@ -372,7 +372,6 @@ static void hal_target_based_configure(struct hal_soc *hal)
 	case TARGET_TYPE_QCA6490:
 		hal->use_register_windowing = true;
 		hal_qca6490_attach(hal);
-		hal->init_phase = false;
 	break;
 #endif
 #ifdef QCA_WIFI_QCA6750

+ 90 - 21
hif/src/hif_io32.h

@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2020 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2021 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
@@ -23,6 +23,25 @@
 #include "hif.h"
 #include "hif_main.h"
 
+/* Device memory is 32MB but bar size is only 1MB.
+ * Register remapping logic is used to access 32MB device memory.
+ * 0-512KB : Fixed address, 512KB-1MB : remapped address.
+ * Use PCIE_REMAP_1M_BAR_CTRL register to set window
+ * for pcie based wifi chipsets.
+ */
+#define MAX_UNWINDOWED_ADDRESS 0x80000
+#if defined(QCA_WIFI_QCA6390) || defined(QCA_WIFI_QCA6490) || \
+	defined(QCA_WIFI_QCN9000) || defined(QCA_WIFI_QCA6750)
+#define WINDOW_ENABLE_BIT 0x40000000
+#else
+#define WINDOW_ENABLE_BIT 0x80000000
+#endif
+#define WINDOW_REG_ADDRESS 0x310C
+#define WINDOW_SHIFT 19
+#define WINDOW_VALUE_MASK 0x3F
+#define WINDOW_START MAX_UNWINDOWED_ADDRESS
+#define WINDOW_RANGE_MASK 0x7FFFF
+
 #if defined(HIF_REG_WINDOW_SUPPORT) && defined(HIF_PCI)
 
 static inline
@@ -123,23 +142,27 @@ bool hif_target_access_allowed(struct hif_softc *scn)
 #include "qdf_lock.h"
 #include "qdf_util.h"
 
-/* Device memory is 32MB but bar size is only 1MB.
- * Register remapping logic is used to access 32MB device memory.
- * 0-512KB : Fixed address, 512KB-1MB : remapped address.
- * Use PCIE_REMAP_1M_BAR_CTRL register to set window.
- * Offset: 0x310C
- * Bits  : Field Name
- * 31      FUNCTION_ENABLE_V
- * 5:0     ADDR_24_19_V
+#ifdef PCIE_REG_WINDOW_LOCAL_NO_CACHE
+/**
+ * hif_select_window(): Update the register window
+ * @sc: HIF pci handle
+ * @offset: reg offset to read from or write to
+ *
+ * Calculate the window using the offset provided and update
+ * the window reg value accordingly for windowed read/write reg
+ * access.
+ *
+ * Return: None
  */
+static inline void hif_select_window(struct hif_pci_softc *sc, uint32_t offset)
+{
+	uint32_t window = (offset >> WINDOW_SHIFT) & WINDOW_VALUE_MASK;
 
-#define MAX_UNWINDOWED_ADDRESS 0x80000 /* 512KB */
-#define WINDOW_ENABLE_BIT 0x80000000 /* 31st bit to enable window */
-#define WINDOW_REG_ADDRESS 0x310C /* PCIE_REMAP_1M_BAR_CTRL Reg offset */
-#define WINDOW_SHIFT 19
-#define WINDOW_VALUE_MASK 0x3F
-#define WINDOW_START MAX_UNWINDOWED_ADDRESS
-#define WINDOW_RANGE_MASK 0x7FFFF
+	qdf_iowrite32(sc->mem + WINDOW_REG_ADDRESS,
+		      WINDOW_ENABLE_BIT | window);
+	sc->register_window = window;
+}
+#else /* PCIE_REG_WINDOW_LOCAL_NO_CACHE */
 
 static inline void hif_select_window(struct hif_pci_softc *sc, uint32_t offset)
 {
@@ -151,6 +174,51 @@ static inline void hif_select_window(struct hif_pci_softc *sc, uint32_t offset)
 		sc->register_window = window;
 	}
 }
+#endif /* PCIE_REG_WINDOW_LOCAL_NO_CACHE */
+
+#if !defined(QCA_WIFI_QCA6390) && !defined(QCA_WIFI_QCA6490)
+/**
+ * hif_lock_reg_access() - Lock window register access spinlock
+ * @sc: HIF handle
+ * @flags: variable pointer to save CPU states
+ *
+ * Lock register window spinlock
+ *
+ * Return: void
+ */
+static inline void hif_lock_reg_access(struct hif_pci_softc *sc,
+				       unsigned long *flags)
+{
+	qdf_spin_lock_irqsave(&sc->register_access_lock);
+}
+
+/**
+ * hif_unlock_reg_access() - Unlock window register access spinlock
+ * @sc: HIF handle
+ * @flags: variable pointer to save CPU states
+ *
+ * Unlock register window spinlock
+ *
+ * Return: void
+ */
+static inline void hif_unlock_reg_access(struct hif_pci_softc *sc,
+					 unsigned long *flags)
+{
+	qdf_spin_unlock_irqrestore(&sc->register_access_lock);
+}
+#else
+static inline void hif_lock_reg_access(struct hif_pci_softc *sc,
+				       unsigned long *flags)
+{
+	pld_lock_reg_window(sc->dev, flags);
+}
+
+static inline void hif_unlock_reg_access(struct hif_pci_softc *sc,
+					 unsigned long *flags)
+{
+	pld_unlock_reg_window(sc->dev, flags);
+}
+#endif
 
 /**
  * note1: WINDOW_RANGE_MASK = (1 << WINDOW_SHIFT) -1
@@ -163,16 +231,17 @@ static inline void hif_write32_mb_reg_window(void *scn,
 {
 	struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
 	uint32_t offset = addr - sc->mem;
+	unsigned long flags;
 
 	if (!sc->use_register_windowing ||
 	    offset < MAX_UNWINDOWED_ADDRESS) {
 		qdf_iowrite32(addr, value);
 	} else {
-		qdf_spin_lock_irqsave(&sc->register_access_lock);
+		hif_lock_reg_access(sc, &flags);
 		hif_select_window(sc, offset);
 		qdf_iowrite32(sc->mem + WINDOW_START +
 			  (offset & WINDOW_RANGE_MASK), value);
-		qdf_spin_unlock_irqrestore(&sc->register_access_lock);
+		hif_unlock_reg_access(sc, &flags);
 	}
 }
 
@@ -181,17 +250,17 @@ static inline uint32_t hif_read32_mb_reg_window(void *scn, void __iomem *addr)
 	struct hif_pci_softc *sc = HIF_GET_PCI_SOFTC(scn);
 	uint32_t ret;
 	uint32_t offset = addr - sc->mem;
+	unsigned long flags;
 
 	if (!sc->use_register_windowing ||
 	    offset < MAX_UNWINDOWED_ADDRESS) {
 		return qdf_ioread32(addr);
 	}
-
-	qdf_spin_lock_irqsave(&sc->register_access_lock);
+	hif_lock_reg_access(sc, &flags);
 	hif_select_window(sc, offset);
 	ret = qdf_ioread32(sc->mem + WINDOW_START +
 		       (offset & WINDOW_RANGE_MASK));
-	qdf_spin_unlock_irqrestore(&sc->register_access_lock);
+	hif_unlock_reg_access(sc, &flags);
 
 	return ret;
 }

+ 31 - 20
hif/src/pcie/if_pci.c

@@ -3407,6 +3407,8 @@ static void hif_pci_init_reg_windowing_support(struct hif_pci_softc *sc,
 {
 	switch (target_type) {
 	case TARGET_TYPE_QCN7605:
+	case TARGET_TYPE_QCA6490:
+	case TARGET_TYPE_QCA6390:
 		sc->use_register_windowing = true;
 		qdf_spinlock_create(&sc->register_access_lock);
 		sc->register_window = 0;
@@ -3661,6 +3663,24 @@ bool hif_pci_needs_bmi(struct hif_softc *scn)
 
 #ifdef FORCE_WAKE
 #ifdef DEVICE_FORCE_WAKE_ENABLE
+
+/**
+ * HIF_POLL_UMAC_WAKE poll value to indicate if UMAC is powered up
+ * Update the below macro with FW defined one.
+ */
+#define HIF_POLL_UMAC_WAKE 0x2
+
+/**
+ * hif_force_wake_request(): Enable the force wake recipe
+ * @hif_handle: HIF handle
+ *
+ * Bring MHI to M0 state and force wake the UMAC by asserting the
+ * soc wake reg. Poll the scratch reg to check if its set to
+ * HIF_POLL_UMAC_WAKE. The polled value may return 0x1 in case UMAC
+ * is powered down.
+ *
+ * Return: 0 if handshake is successful or ETIMEDOUT in case of failure
+ */
 int hif_force_wake_request(struct hif_opaque_softc *hif_handle)
 {
 	uint32_t timeout, value;
@@ -3688,15 +3708,8 @@ int hif_force_wake_request(struct hif_opaque_softc *hif_handle)
 		hif_info("state-change event races, ignore");
 
 	HIF_STATS_INC(pci_scn, mhi_force_wake_success, 1);
-	hif_write32_mb(scn,
-		       scn->mem +
-		       PCIE_SOC_PCIE_REG_PCIE_SCRATCH_0_SOC_PCIE_REG,
-		       0);
-	hif_write32_mb(scn,
-		       scn->mem +
-		       PCIE_PCIE_LOCAL_REG_PCIE_SOC_WAKE_PCIE_LOCAL_REG,
-		       1);
-
+	hif_write32_mb(scn, scn->mem +
+		       PCIE_PCIE_LOCAL_REG_PCIE_SOC_WAKE_PCIE_LOCAL_REG, 1);
 	HIF_STATS_INC(pci_scn, soc_force_wake_register_write_success, 1);
 	/*
 	 * do not reset the timeout
@@ -3704,18 +3717,18 @@ int hif_force_wake_request(struct hif_opaque_softc *hif_handle)
 	 */
 	timeout = 0;
 	do {
-		value =
-		hif_read32_mb(scn,
-			      scn->mem +
-			      PCIE_SOC_PCIE_REG_PCIE_SCRATCH_0_SOC_PCIE_REG);
-		if (value)
+		value = hif_read32_mb(
+				scn, scn->mem +
+				PCIE_SOC_PCIE_REG_PCIE_SCRATCH_0_SOC_PCIE_REG);
+		hif_info("pcie scratch reg read value = %x", value);
+		if (value == HIF_POLL_UMAC_WAKE)
 			break;
 		qdf_mdelay(FORCE_WAKE_DELAY_MS);
 		timeout += FORCE_WAKE_DELAY_MS;
 	} while (timeout <= FORCE_WAKE_DELAY_TIMEOUT_MS);
 
-	if (!value) {
-		hif_err("failed handshake mechanism");
+	if (value != HIF_POLL_UMAC_WAKE) {
+		hif_err("failed force wake handshake mechanism");
 		HIF_STATS_INC(pci_scn, soc_force_wake_failure, 1);
 		return -ETIMEDOUT;
 	}
@@ -3738,10 +3751,8 @@ int hif_force_wake_release(struct hif_opaque_softc *hif_handle)
 	}
 
 	HIF_STATS_INC(pci_scn, mhi_force_wake_release_success, 1);
-	hif_write32_mb(scn,
-		       scn->mem +
-		       PCIE_PCIE_LOCAL_REG_PCIE_SOC_WAKE_PCIE_LOCAL_REG,
-		       0);
+	hif_write32_mb(scn, scn->mem +
+		       PCIE_PCIE_LOCAL_REG_PCIE_SOC_WAKE_PCIE_LOCAL_REG, 0);
 	HIF_STATS_INC(pci_scn, soc_force_wake_release_success, 1);
 	return 0;
 }