summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/cnss2/pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/cnss2/pci.c')
-rw-r--r--drivers/net/wireless/cnss2/pci.c82
1 files changed, 81 insertions, 1 deletions
diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c
index 2356caa3af78..3f2aef84662c 100644
--- a/drivers/net/wireless/cnss2/pci.c
+++ b/drivers/net/wireless/cnss2/pci.c
@@ -16,8 +16,10 @@
#include <linux/msi.h>
#include <linux/of.h>
#include <linux/pm_runtime.h>
+#include <linux/memblock.h>
#include "main.h"
+#include "bus.h"
#include "debug.h"
#include "pci.h"
@@ -40,10 +42,15 @@
#endif
#define MHI_NODE_NAME "qcom,mhi"
+#define MHI_MSI_NAME "MHI"
#define MAX_M3_FILE_NAME_LENGTH 13
#define DEFAULT_M3_FILE_NAME "m3.bin"
+#define WAKE_MSI_NAME "WAKE"
+
+#define FW_ASSERT_TIMEOUT 5000
+
#ifdef CONFIG_PCI_MSM
static DEFINE_SPINLOCK(pci_link_down_lock);
#endif
@@ -178,7 +185,6 @@ int cnss_resume_pci_link(struct cnss_pci_data *pci_priv)
goto out;
}
-
pci_set_master(pci_priv->pci_dev);
if (pci_priv->pci_link_down_ind)
@@ -841,6 +847,63 @@ static void cnss_pci_free_m3_mem(struct cnss_pci_data *pci_priv)
m3_mem->size = 0;
}
+int cnss_pci_force_fw_assert_hdlr(struct cnss_pci_data *pci_priv)
+{
+ struct cnss_plat_data *plat_priv;
+ int ret;
+
+ if (!pci_priv)
+ return -ENODEV;
+
+ plat_priv = pci_priv->plat_priv;
+ if (!plat_priv)
+ return -ENODEV;
+
+ ret = cnss_pci_set_mhi_state(pci_priv,
+ CNSS_MHI_TRIGGER_RDDM);
+ if (ret) {
+ cnss_pr_err("Failed to trigger RDDM, err = %d\n", ret);
+ cnss_schedule_recovery(&pci_priv->pci_dev->dev,
+ CNSS_REASON_DEFAULT);
+ return 0;
+ }
+
+ if (!test_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state)) {
+ mod_timer(&plat_priv->fw_boot_timer,
+ jiffies + msecs_to_jiffies(FW_ASSERT_TIMEOUT));
+ }
+
+ return 0;
+}
+
+void cnss_pci_fw_boot_timeout_hdlr(struct cnss_pci_data *pci_priv)
+{
+ if (!pci_priv)
+ return;
+
+ cnss_pr_err("Timeout waiting for FW ready indication\n");
+
+ cnss_schedule_recovery(&pci_priv->pci_dev->dev,
+ CNSS_REASON_TIMEOUT);
+}
+
+int cnss_get_soc_info(struct device *dev, struct cnss_soc_info *info)
+{
+ int ret = 0;
+ struct cnss_plat_data *plat_priv = cnss_bus_dev_to_plat_priv(dev);
+ void *bus_priv = cnss_bus_dev_to_bus_priv(dev);
+
+ if (!plat_priv)
+ return -ENODEV;
+
+ ret = cnss_pci_get_bar_info(bus_priv, &info->va, &info->pa);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+EXPORT_SYMBOL(cnss_get_soc_info);
+
int cnss_pci_get_bar_info(struct cnss_pci_data *pci_priv, void __iomem **va,
phys_addr_t *pa)
{
@@ -991,6 +1054,23 @@ void cnss_get_msi_address(struct device *dev, u32 *msi_addr_low,
}
EXPORT_SYMBOL(cnss_get_msi_address);
+u32 cnss_pci_get_wake_msi(struct cnss_pci_data *pci_priv)
+{
+ int ret, num_vectors;
+ u32 user_base_data, base_vector;
+
+ ret = cnss_get_user_msi_assignment(&pci_priv->pci_dev->dev,
+ WAKE_MSI_NAME, &num_vectors,
+ &user_base_data, &base_vector);
+
+ if (ret) {
+ cnss_pr_err("WAKE MSI is not valid\n");
+ return 0;
+ }
+
+ return user_base_data;
+}
+
#ifdef CONFIG_PCI_MSM
static inline int cnss_pci_set_dma_mask(struct pci_dev *pci_dev)
{