qcacld-3.0: Add PLD layer for WHUNT

WHUNT is host unit testing framework which simulates
firmware. Add a PLD wrapper layer for this virtual device.

Change-Id: I1d09b8a18a25b414b0c1d56723cc5687f2bfe297
diff --git a/Kbuild b/Kbuild
index 7ac440e..151bc58 100644
--- a/Kbuild
+++ b/Kbuild
@@ -1815,12 +1815,17 @@
 
 PLD_OBJS :=	$(PLD_SRC_DIR)/pld_common.o
 
-ifeq ($(CONFIG_HIF_PCI), y)
-PLD_OBJS +=	$(PLD_SRC_DIR)/pld_pcie.o
+ifeq ($(CONFIG_PCIE_FW_SIM), y)
+PLD_OBJS +=     $(PLD_SRC_DIR)/pld_pcie_fw_sim.o
+else ifeq ($(CONFIG_HIF_PCI), y)
+PLD_OBJS +=     $(PLD_SRC_DIR)/pld_pcie.o
 endif
-ifeq ($(CONFIG_ICNSS), y)
-PLD_OBJS +=	$(PLD_SRC_DIR)/pld_snoc.o
+ifeq ($(CONFIG_SNOC_FW_SIM),y)
+PLD_OBJS +=     $(PLD_SRC_DIR)/pld_snoc_fw_sim.o
+else ifeq ($(CONFIG_ICNSS),y)
+PLD_OBJS +=     $(PLD_SRC_DIR)/pld_snoc.o
 endif
+
 ifeq ($(CONFIG_QCA_WIFI_SDIO), y)
 PLD_OBJS +=	$(PLD_SRC_DIR)/pld_sdio.o
 endif
@@ -2134,7 +2139,15 @@
 cppflags-$(CONFIG_WLAN_FEATURE_ELNA) += -DWLAN_FEATURE_ELNA
 
 cppflags-$(CONFIG_PLD_SDIO_CNSS_FLAG) += -DCONFIG_PLD_SDIO_CNSS
-cppflags-$(CONFIG_PLD_PCIE_CNSS_FLAG) += -DCONFIG_PLD_PCIE_CNSS
+
+ifeq ($(CONFIG_PLD_PCIE_CNSS_FLAG), y)
+ifeq ($(CONFIG_PCIE_FW_SIM), y)
+cppflags-y += -DCONFIG_PLD_PCIE_FW_SIM
+else
+cppflags-y += -DCONFIG_PLD_PCIE_CNSS
+endif
+endif
+
 cppflags-$(CONFIG_PLD_PCIE_INIT_FLAG) += -DCONFIG_PLD_PCIE_INIT
 cppflags-$(CONFIG_WLAN_FEATURE_DP_RX_THREADS) += -DFEATURE_WLAN_DP_RX_THREADS
 cppflags-$(CONFIG_WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT) += -DWLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT
@@ -2159,7 +2172,13 @@
 endif
 endif
 
-cppflags-$(CONFIG_ICNSS) += -DCONFIG_PLD_SNOC_ICNSS
+ifeq ($(CONFIG_ICNSS), y)
+ifeq ($(CONFIG_SNOC_FW_SIM), y)
+cppflags-y += -DCONFIG_PLD_SNOC_FW_SIM
+else
+cppflags-y += -DCONFIG_PLD_SNOC_ICNSS
+endif
+endif
 
 cppflags-$(CONFIG_WIFI_3_0_ADRASTEA) += -DQCA_WIFI_3_0_ADRASTEA
 cppflags-$(CONFIG_WIFI_3_0_ADRASTEA) += -DQCA_WIFI_3_0
diff --git a/core/hdd/src/wlan_hdd_driver_ops.c b/core/hdd/src/wlan_hdd_driver_ops.c
index 86158b0..6d2354b 100644
--- a/core/hdd/src/wlan_hdd_driver_ops.c
+++ b/core/hdd/src/wlan_hdd_driver_ops.c
@@ -211,8 +211,10 @@
 static enum qdf_bus_type to_bus_type(enum pld_bus_type bus_type)
 {
 	switch (bus_type) {
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
 	case PLD_BUS_TYPE_PCIE:
 		return QDF_BUS_TYPE_PCI;
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 		return QDF_BUS_TYPE_SNOC;
 	case PLD_BUS_TYPE_SDIO:
diff --git a/core/pld/inc/pld_common.h b/core/pld/inc/pld_common.h
index de22d85..1a2e20a 100644
--- a/core/pld/inc/pld_common.h
+++ b/core/pld/inc/pld_common.h
@@ -47,13 +47,19 @@
  * @PLD_BUS_TYPE_NONE: invalid bus type, only return in error cases
  * @PLD_BUS_TYPE_PCIE: PCIE bus
  * @PLD_BUS_TYPE_SNOC: SNOC bus
+ * @PLD_BUS_TYPE_SDIO: SDIO bus
+ * @PLD_BUS_TYPE_USB : USB bus
+ * @PLD_BUS_TYPE_SNOC_FW_SIM : SNOC FW SIM bus
+ * @PLD_BUS_TYPE_PCIE_FW_SIM : PCIE FW SIM bus
  */
 enum pld_bus_type {
 	PLD_BUS_TYPE_NONE = -1,
 	PLD_BUS_TYPE_PCIE = 0,
 	PLD_BUS_TYPE_SNOC,
 	PLD_BUS_TYPE_SDIO,
-	PLD_BUS_TYPE_USB
+	PLD_BUS_TYPE_USB,
+	PLD_BUS_TYPE_SNOC_FW_SIM,
+	PLD_BUS_TYPE_PCIE_FW_SIM,
 };
 
 #define PLD_MAX_FIRMWARE_SIZE (1 * 1024 * 1024)
@@ -698,7 +704,94 @@
  */
 int pld_idle_restart(struct device *dev,
 		     int (*restart_cb)(struct device *dev));
+/**
+ * pld_srng_request_irq() - Register IRQ for SRNG
+ * @dev: device
+ * @irq: IRQ number
+ * @handler: IRQ callback function
+ * @irqflags: IRQ flags
+ * @name: IRQ name
+ * @ctx: IRQ context
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_srng_request_irq(struct device *dev, int irq, irq_handler_t handler,
+			 unsigned long irqflags,
+			 const char *name,
+			 void *ctx);
+/**
+ * pld_srng_free_irq() - Free IRQ for SRNG
+ * @dev: device
+ * @irq: IRQ number
+ * @ctx: IRQ context
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_srng_free_irq(struct device *dev, int irq, void *ctx);
 
+/**
+ * pld_srng_enable_irq() - Enable IRQ for SRNG
+ * @dev: device
+ * @irq: IRQ number
+ *
+ * Return: void
+ */
+void pld_srng_enable_irq(struct device *dev, int irq);
+
+/**
+ * pld_disable_irq() - Disable IRQ for SRNG
+ * @dev: device
+ * @irq: IRQ number
+ *
+ * Return: void
+ */
+void pld_srng_disable_irq(struct device *dev, int irq);
+
+/**
+ * pld_pci_read_config_word() - Read PCI config
+ * @pdev: pci device
+ * @offset: Config space offset
+ * @val : Value
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_pci_read_config_word(struct pci_dev *pdev, int offset, uint16_t *val);
+
+/**
+ * pld_pci_write_config_word() - Write PCI config
+ * @pdev: pci device
+ * @offset: Config space offset
+ * @val : Value
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_pci_write_config_word(struct pci_dev *pdev, int offset, uint16_t val);
+
+/**
+ * pld_pci_read_config_dword() - Read PCI config
+ * @pdev: pci device
+ * @offset: Config space offset
+ * @val : Value
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_pci_read_config_dword(struct pci_dev *pdev, int offset, uint32_t *val);
+
+/**
+ * pld_pci_write_config_dword() - Write PCI config
+ * @pdev: pci device
+ * @offset: Config space offset
+ * @val : Value
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_pci_write_config_dword(struct pci_dev *pdev, int offset, uint32_t val);
 #if defined(CONFIG_WCNSS_MEM_PRE_ALLOC) && defined(FEATURE_SKB_PRE_ALLOC)
 
 /**
diff --git a/core/pld/src/pld_common.c b/core/pld/src/pld_common.c
index ce690fe..46dd193 100644
--- a/core/pld/src/pld_common.c
+++ b/core/pld/src/pld_common.c
@@ -36,6 +36,8 @@
 #endif
 
 #include "pld_pcie.h"
+#include "pld_pcie_fw_sim.h"
+#include "pld_snoc_fw_sim.h"
 #include "pld_snoc.h"
 #include "pld_sdio.h"
 #include "pld_usb.h"
@@ -45,6 +47,8 @@
 #define PLD_SNOC_REGISTERED BIT(1)
 #define PLD_SDIO_REGISTERED BIT(2)
 #define PLD_USB_REGISTERED BIT(3)
+#define PLD_SNOC_FW_SIM_REGISTERED BIT(4)
+#define PLD_PCIE_FW_SIM_REGISTERED BIT(5)
 #define PLD_BUS_MASK 0xf
 
 static struct pld_context *pld_ctx;
@@ -288,6 +292,20 @@
 	}
 	pld_context->pld_driver_state |= PLD_SDIO_REGISTERED;
 
+	ret = pld_snoc_fw_sim_register_driver();
+	if (ret) {
+		pr_err("Fail to register snoc fw sim driver\n");
+		goto fail_snoc_fw_sim;
+	}
+	pld_context->pld_driver_state |= PLD_SNOC_FW_SIM_REGISTERED;
+
+	ret = pld_pcie_fw_sim_register_driver();
+	if (ret) {
+		pr_err("Fail to register pcie fw sim driver\n");
+		goto fail_pcie_fw_sim;
+	}
+	pld_context->pld_driver_state |= PLD_PCIE_FW_SIM_REGISTERED;
+
 	ret = pld_usb_register_driver();
 	if (ret) {
 		pr_err("Fail to register usb driver\n");
@@ -298,6 +316,10 @@
 	return ret;
 
 fail_usb:
+	pld_pcie_fw_sim_unregister_driver();
+fail_pcie_fw_sim:
+	pld_snoc_fw_sim_unregister_driver();
+fail_snoc_fw_sim:
 	pld_sdio_unregister_driver();
 fail_sdio:
 	pld_snoc_unregister_driver();
@@ -336,6 +358,8 @@
 	}
 
 	pld_pcie_unregister_driver();
+	pld_snoc_fw_sim_unregister_driver();
+	pld_pcie_fw_sim_unregister_driver();
 	pld_snoc_unregister_driver();
 	pld_sdio_unregister_driver();
 	pld_usb_unregister_driver();
@@ -370,6 +394,14 @@
 	case PLD_BUS_TYPE_SNOC:
 		ret = pld_snoc_wlan_enable(dev, config, mode, QWLAN_VERSIONSTR);
 		break;
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
+		ret = pld_snoc_fw_sim_wlan_enable(dev, config, mode,
+						  QWLAN_VERSIONSTR);
+		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+		ret = pld_pcie_fw_sim_wlan_enable(dev, config, mode,
+						  QWLAN_VERSIONSTR);
+		break;
 	case PLD_BUS_TYPE_SDIO:
 		ret = pld_sdio_wlan_enable(dev, config, mode, QWLAN_VERSIONSTR);
 		break;
@@ -407,6 +439,12 @@
 	case PLD_BUS_TYPE_SNOC:
 		ret = pld_snoc_wlan_disable(dev, mode);
 		break;
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
+		ret = pld_snoc_fw_sim_wlan_disable(dev, mode);
+		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+		ret = pld_pcie_fw_sim_wlan_disable(dev, mode);
+		break;
 	case PLD_BUS_TYPE_SDIO:
 		break;
 	default:
@@ -438,6 +476,8 @@
 	case PLD_BUS_TYPE_SNOC:
 		ret = pld_snoc_set_fw_log_mode(dev, fw_log_mode);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SDIO:
 		break;
 	default:
@@ -500,6 +540,8 @@
 						       target_type,
 						       target_version);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 		break;
 	case PLD_BUS_TYPE_SDIO:
@@ -531,9 +573,12 @@
 void pld_is_pci_link_down(struct device *dev)
 {
 	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+		break;
 	case PLD_BUS_TYPE_PCIE:
 		pld_pcie_link_down(dev);
 		break;
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 		break;
 	default:
@@ -558,6 +603,8 @@
 	case PLD_BUS_TYPE_PCIE:
 		pld_pcie_schedule_recovery_work(dev, reason);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 		break;
 	default:
@@ -586,6 +633,8 @@
 	case PLD_BUS_TYPE_PCIE:
 		ret = pld_pcie_wlan_pm_control(dev, vote);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 		break;
 	case PLD_BUS_TYPE_SDIO:
@@ -613,6 +662,8 @@
 	case PLD_BUS_TYPE_PCIE:
 		mem = pld_pcie_get_virt_ramdump_mem(dev, size);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 		break;
 	case PLD_BUS_TYPE_SDIO:
@@ -632,6 +683,8 @@
 	case PLD_BUS_TYPE_PCIE:
 		pld_pcie_release_virt_ramdump_mem(address);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 		break;
 	case PLD_BUS_TYPE_SDIO:
@@ -658,6 +711,8 @@
 	case PLD_BUS_TYPE_PCIE:
 		pld_pcie_device_crashed(dev);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 		break;
 	case PLD_BUS_TYPE_SDIO:
@@ -683,6 +738,8 @@
 	case PLD_BUS_TYPE_PCIE:
 		pld_pcie_device_self_recovery(dev, reason);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 		break;
 	case PLD_BUS_TYPE_SDIO:
@@ -708,6 +765,8 @@
 	case PLD_BUS_TYPE_PCIE:
 		pld_pcie_intr_notify_q6(dev);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 		break;
 	default:
@@ -731,6 +790,8 @@
 	case PLD_BUS_TYPE_PCIE:
 		pld_pcie_request_pm_qos(dev, qos_val);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 		break;
 	case PLD_BUS_TYPE_SDIO:
@@ -758,6 +819,8 @@
 	case PLD_BUS_TYPE_PCIE:
 		pld_pcie_remove_pm_qos(dev);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 		break;
 	case PLD_BUS_TYPE_SDIO:
@@ -787,6 +850,8 @@
 	case PLD_BUS_TYPE_PCIE:
 		ret = pld_pcie_request_bus_bandwidth(dev, bandwidth);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 		break;
 	case PLD_BUS_TYPE_SDIO:
@@ -818,6 +883,10 @@
 	case PLD_BUS_TYPE_PCIE:
 		ret = pld_pcie_get_platform_cap(dev, cap);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+		ret = pld_pcie_fw_sim_get_platform_cap(dev, cap);
+		break;
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 		break;
 	case PLD_BUS_TYPE_SDIO:
@@ -853,6 +922,8 @@
 		ret = pld_pcie_get_sha_hash(dev, data, data_len,
 					    hash_idx, out);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 		break;
 	case PLD_BUS_TYPE_SDIO:
@@ -879,6 +950,8 @@
 	case PLD_BUS_TYPE_PCIE:
 		ptr = pld_pcie_get_fw_ptr(dev);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 		break;
 	case PLD_BUS_TYPE_SDIO:
@@ -906,6 +979,8 @@
 	case PLD_BUS_TYPE_PCIE:
 		ret = pld_pcie_auto_suspend(dev);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 		break;
 	case PLD_BUS_TYPE_SDIO:
@@ -933,6 +1008,8 @@
 	case PLD_BUS_TYPE_PCIE:
 		ret = pld_pcie_auto_resume(dev);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 		break;
 	case PLD_BUS_TYPE_SDIO:
@@ -961,6 +1038,8 @@
 	case PLD_BUS_TYPE_PCIE:
 		ret = pld_pcie_force_wake_request(dev);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 	case PLD_BUS_TYPE_SDIO:
 	case PLD_BUS_TYPE_USB:
@@ -991,6 +1070,8 @@
 	case PLD_BUS_TYPE_PCIE:
 		ret = pld_pcie_is_device_awake(dev);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 	case PLD_BUS_TYPE_SDIO:
 	case PLD_BUS_TYPE_USB:
@@ -1020,6 +1101,8 @@
 	case PLD_BUS_TYPE_PCIE:
 		ret = pld_pcie_force_wake_release(dev);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 	case PLD_BUS_TYPE_SDIO:
 	case PLD_BUS_TYPE_USB:
@@ -1056,6 +1139,11 @@
 		ret = pld_snoc_ce_request_irq(dev, ce_id,
 					      handler, flags, name, ctx);
 		break;
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
+		ret = pld_snoc_fw_sim_ce_request_irq(dev, ce_id,
+						     handler, flags, name, ctx);
+		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
 	case PLD_BUS_TYPE_PCIE:
 		break;
 	default:
@@ -1083,6 +1171,10 @@
 	case PLD_BUS_TYPE_SNOC:
 		ret = pld_snoc_ce_free_irq(dev, ce_id, ctx);
 		break;
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
+		ret = pld_snoc_fw_sim_ce_free_irq(dev, ce_id, ctx);
+		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
 	case PLD_BUS_TYPE_PCIE:
 		break;
 	default:
@@ -1106,6 +1198,10 @@
 	case PLD_BUS_TYPE_SNOC:
 		pld_snoc_enable_irq(dev, ce_id);
 		break;
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
+		pld_snoc_fw_sim_enable_irq(dev, ce_id);
+		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
 	case PLD_BUS_TYPE_PCIE:
 		break;
 	case PLD_BUS_TYPE_SDIO:
@@ -1129,6 +1225,10 @@
 	case PLD_BUS_TYPE_SNOC:
 		pld_snoc_disable_irq(dev, ce_id);
 		break;
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
+		pld_snoc_fw_sim_disable_irq(dev, ce_id);
+		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
 	case PLD_BUS_TYPE_PCIE:
 		break;
 	case PLD_BUS_TYPE_SDIO:
@@ -1157,6 +1257,12 @@
 	case PLD_BUS_TYPE_SNOC:
 		ret = pld_snoc_get_soc_info(dev, info);
 		break;
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
+		ret = pld_snoc_fw_sim_get_soc_info(dev, info);
+		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+		ret = pld_pcie_fw_sim_get_soc_info(dev, info);
+		break;
 	case PLD_BUS_TYPE_PCIE:
 		ret = pld_pcie_get_soc_info(dev, info);
 		break;
@@ -1185,9 +1291,14 @@
 	case PLD_BUS_TYPE_SNOC:
 		ret = pld_snoc_get_ce_id(dev, irq);
 		break;
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
+		ret = pld_snoc_fw_sim_get_ce_id(dev, irq);
+		break;
 	case PLD_BUS_TYPE_PCIE:
 		ret = pld_pcie_get_ce_id(dev, irq);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+		break;
 	default:
 		ret = -EINVAL;
 		break;
@@ -1211,6 +1322,10 @@
 	case PLD_BUS_TYPE_SNOC:
 		ret = pld_snoc_get_irq(dev, ce_id);
 		break;
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
+		ret = pld_snoc_fw_sim_get_irq(dev, ce_id);
+		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
 	case PLD_BUS_TYPE_PCIE:
 	default:
 		ret = -EINVAL;
@@ -1232,6 +1347,8 @@
 	case PLD_BUS_TYPE_PCIE:
 		pld_pcie_lock_pm_sem(dev);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 		break;
 	case PLD_BUS_TYPE_SDIO:
@@ -1256,6 +1373,8 @@
 	case PLD_BUS_TYPE_PCIE:
 		pld_pcie_release_pm_sem(dev);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 		break;
 	case PLD_BUS_TYPE_SDIO:
@@ -1286,6 +1405,9 @@
 		 * handle the power on sequence for PCIe SoC
 		 */
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
+		break;
 	case PLD_BUS_TYPE_SNOC:
 		ret = pld_snoc_power_on(dev);
 		break;
@@ -1315,6 +1437,9 @@
 		 * handle the power off sequence for PCIe SoC
 		 */
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
+		break;
 	case PLD_BUS_TYPE_SNOC:
 		ret = pld_snoc_power_off(dev);
 		break;
@@ -1354,6 +1479,8 @@
 		break;
 	case PLD_BUS_TYPE_SDIO:
 	case PLD_BUS_TYPE_USB:
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 		break;
 	default:
 		ret = -EINVAL;
@@ -1391,6 +1518,8 @@
 		break;
 	case PLD_BUS_TYPE_SDIO:
 	case PLD_BUS_TYPE_USB:
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 		break;
 	default:
 		ret = -EINVAL;
@@ -1419,6 +1548,9 @@
 	case PLD_BUS_TYPE_PCIE:
 		ptr = pld_pcie_smmu_get_domain(dev);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
+		break;
 	case PLD_BUS_TYPE_SDIO:
 	case PLD_BUS_TYPE_USB:
 		pr_err("Not supported on type %d\n", type);
@@ -1446,6 +1578,9 @@
 	case PLD_BUS_TYPE_SNOC:
 		ptr = pld_snoc_smmu_get_mapping(dev);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
+		break;
 	case PLD_BUS_TYPE_PCIE:
 		ptr = pld_pcie_smmu_get_mapping(dev);
 		break;
@@ -1478,6 +1613,9 @@
 	case PLD_BUS_TYPE_SNOC:
 		ret = pld_snoc_smmu_map(dev, paddr, iova_addr, size);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
+		break;
 	case PLD_BUS_TYPE_PCIE:
 		ret = pld_pcie_smmu_map(dev, paddr, iova_addr, size);
 		break;
@@ -1516,9 +1654,16 @@
 						       user_base_data,
 						       base_vector);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+		ret = pld_pcie_fw_sim_get_user_msi_assignment(dev, user_name,
+							      num_vectors,
+							      user_base_data,
+							      base_vector);
+		break;
 	case PLD_BUS_TYPE_SNOC:
 	case PLD_BUS_TYPE_SDIO:
 	case PLD_BUS_TYPE_USB:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 		pr_err("Not supported on type %d\n", type);
 		ret = -ENODEV;
 		break;
@@ -1532,6 +1677,273 @@
 }
 
 /**
+ * pld_srng_request_irq() - Register IRQ for SRNG
+ * @dev: device
+ * @irq: IRQ number
+ * @handler: IRQ callback function
+ * @flags: IRQ flags
+ * @name: IRQ name
+ * @ctx: IRQ context
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_srng_request_irq(struct device *dev, int irq, irq_handler_t handler,
+			 unsigned long irqflags,
+			 const char *devname,
+			 void *dev_data)
+{
+	int ret = 0;
+	enum pld_bus_type type = pld_get_bus_type(dev);
+
+	switch (type) {
+	case PLD_BUS_TYPE_PCIE:
+		ret = request_irq(irq, handler, irqflags, devname, dev_data);
+		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+		ret = pld_pcie_fw_sim_request_irq(dev, irq, handler,
+						  irqflags, devname,
+						  dev_data);
+		break;
+	case PLD_BUS_TYPE_SNOC:
+	case PLD_BUS_TYPE_SDIO:
+	case PLD_BUS_TYPE_USB:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
+		pr_err("Not supported on type %d\n", type);
+		ret = -ENODEV;
+		break;
+	default:
+		pr_err("Invalid device type %d\n", type);
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pld_srng_free_irq() - Free IRQ for SRNG
+ * @dev: device
+ * @irq: IRQ number
+ * @handler: IRQ callback function
+ * @flags: IRQ flags
+ * @name: IRQ name
+ * @ctx: IRQ context
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_srng_free_irq(struct device *dev, int irq, void *dev_data)
+{
+	int ret = 0;
+	enum pld_bus_type type = pld_get_bus_type(dev);
+
+	switch (type) {
+	case PLD_BUS_TYPE_PCIE:
+		free_irq(irq, dev_data);
+		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+		ret = pld_pcie_fw_sim_free_irq(dev, irq, dev_data);
+		break;
+	case PLD_BUS_TYPE_SNOC:
+	case PLD_BUS_TYPE_SDIO:
+	case PLD_BUS_TYPE_USB:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
+		pr_err("Not supported on type %d\n", type);
+		ret = -ENODEV;
+		break;
+	default:
+		pr_err("Invalid device type %d\n", type);
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pld_srng_enable_irq() - Enable IRQ for SRNG
+ * @dev: device
+ * @irq: IRQ number
+ *
+ * Return: void
+ */
+void pld_srng_enable_irq(struct device *dev, int irq)
+{
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_SNOC:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
+		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+		pld_pcie_fw_sim_enable_irq(dev, irq);
+		break;
+	case PLD_BUS_TYPE_PCIE:
+		enable_irq(irq);
+		break;
+	case PLD_BUS_TYPE_SDIO:
+		break;
+	default:
+		pr_err("Invalid device type\n");
+		break;
+	}
+}
+
+/**
+ * pld_disable_irq() - Disable IRQ for SRNG
+ * @dev: device
+ * @irq: IRQ number
+ *
+ * Return: void
+ */
+void pld_srng_disable_irq(struct device *dev, int irq)
+{
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_SNOC:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
+		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+		pld_pcie_fw_sim_disable_irq(dev, irq);
+		break;
+	case PLD_BUS_TYPE_PCIE:
+		disable_irq_nosync(irq);
+		break;
+	case PLD_BUS_TYPE_SDIO:
+		break;
+	default:
+		pr_err("Invalid device type\n");
+		break;
+	}
+}
+
+/**
+ * pld_pci_read_config_word() - Read PCI config
+ * @pdev: pci device
+ * @offset: Config space offset
+ * @val : Value
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_pci_read_config_word(struct pci_dev *pdev, int offset, uint16_t *val)
+{
+	int ret = 0;
+
+	switch (pld_get_bus_type(&pdev->dev)) {
+	case PLD_BUS_TYPE_SNOC:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
+		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+		break;
+	case PLD_BUS_TYPE_PCIE:
+		ret = pci_read_config_word(pdev, offset, val);
+		break;
+	case PLD_BUS_TYPE_SDIO:
+		break;
+	default:
+		pr_err("Invalid device type\n");
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pld_pci_write_config_word() - Write PCI config
+ * @pdev: pci device
+ * @offset: Config space offset
+ * @val : Value
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_pci_write_config_word(struct pci_dev *pdev, int offset, uint16_t val)
+{
+	int ret = 0;
+
+	switch (pld_get_bus_type(&pdev->dev)) {
+	case PLD_BUS_TYPE_SNOC:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
+		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+		break;
+	case PLD_BUS_TYPE_PCIE:
+		ret = pci_write_config_word(pdev, offset, val);
+		break;
+	case PLD_BUS_TYPE_SDIO:
+		break;
+	default:
+		pr_err("Invalid device type\n");
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pld_pci_read_config_dword() - Read PCI config
+ * @pdev: pci device
+ * @offset: Config space offset
+ * @val : Value
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_pci_read_config_dword(struct pci_dev *pdev, int offset, uint32_t *val)
+{
+	int ret = 0;
+
+	switch (pld_get_bus_type(&pdev->dev)) {
+	case PLD_BUS_TYPE_SNOC:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
+		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+		break;
+	case PLD_BUS_TYPE_PCIE:
+		ret = pci_read_config_dword(pdev, offset, val);
+		break;
+	case PLD_BUS_TYPE_SDIO:
+		break;
+	default:
+		pr_err("Invalid device type\n");
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pld_pci_write_config_dword() - Write PCI config
+ * @pdev: pci device
+ * @offset: Config space offset
+ * @val : Value
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_pci_write_config_dword(struct pci_dev *pdev, int offset, uint32_t val)
+{
+	int ret = 0;
+
+	switch (pld_get_bus_type(&pdev->dev)) {
+	case PLD_BUS_TYPE_SNOC:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
+		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+		break;
+	case PLD_BUS_TYPE_PCIE:
+		ret = pci_write_config_dword(pdev, offset, val);
+		break;
+	case PLD_BUS_TYPE_SDIO:
+		break;
+	default:
+		pr_err("Invalid device type\n");
+		break;
+	}
+
+	return ret;
+}
+
+/**
  * pld_get_msi_irq() - Get MSI IRQ number used for request_irq()
  * @dev: device structure
  * @vector: MSI vector (offset) number
@@ -1548,9 +1960,13 @@
 	case PLD_BUS_TYPE_PCIE:
 		ret = pld_pcie_get_msi_irq(dev, vector);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+		ret = pld_pcie_fw_sim_get_msi_irq(dev, vector);
+		break;
 	case PLD_BUS_TYPE_SNOC:
 	case PLD_BUS_TYPE_SDIO:
 	case PLD_BUS_TYPE_USB:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 		pr_err("Not supported on type %d\n", type);
 		ret = -ENODEV;
 		break;
@@ -1580,9 +1996,14 @@
 	case PLD_BUS_TYPE_PCIE:
 		pld_pcie_get_msi_address(dev, msi_addr_low, msi_addr_high);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+		pld_pcie_fw_sim_get_msi_address(dev, msi_addr_low,
+						msi_addr_high);
+		break;
 	case PLD_BUS_TYPE_SNOC:
 	case PLD_BUS_TYPE_SDIO:
 	case PLD_BUS_TYPE_USB:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 		pr_err("Not supported on type %d\n", type);
 		break;
 	default:
@@ -1608,6 +2029,8 @@
 	case PLD_BUS_TYPE_PCIE:
 		ret = pld_pcie_is_drv_connected(dev);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 	case PLD_BUS_TYPE_SDIO:
 	case PLD_BUS_TYPE_USB:
@@ -1636,9 +2059,12 @@
 	case PLD_BUS_TYPE_SNOC:
 		ret = pld_snoc_socinfo_get_serial_number(dev);
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
 	case PLD_BUS_TYPE_PCIE:
 		pr_err("Not supported on type %d\n", type);
 		break;
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
+		break;
 	default:
 		pr_err("Invalid device type %d\n", type);
 		break;
@@ -1664,6 +2090,9 @@
 	case PLD_BUS_TYPE_SNOC:
 		ret = pld_snoc_is_qmi_disable(dev);
 		break;
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
+		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
 	case PLD_BUS_TYPE_PCIE:
 	case PLD_BUS_TYPE_SDIO:
 		pr_err("Not supported on type %d\n", type);
@@ -1699,6 +2128,11 @@
 	case PLD_BUS_TYPE_SNOC:
 		ret = pld_snoc_is_fw_down(dev);
 		break;
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
+		ret = pld_snoc_fw_sim_is_fw_down(dev);
+		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+		break;
 	case PLD_BUS_TYPE_PCIE:
 		ret = pld_pcie_is_fw_down(dev);
 		break;
@@ -1735,6 +2169,9 @@
 		return pld_snoc_force_assert_target(dev);
 	case PLD_BUS_TYPE_PCIE:
 		return pld_pcie_force_assert_target(dev);
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+		return -EOPNOTSUPP;
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SDIO:
 		return -EINVAL;
 	default:
@@ -1758,6 +2195,8 @@
 	switch (type) {
 	case PLD_BUS_TYPE_PCIE:
 		return pld_pcie_collect_rddm(dev);
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 	case PLD_BUS_TYPE_SDIO:
 	case PLD_BUS_TYPE_USB:
@@ -1873,6 +2312,8 @@
 	case PLD_BUS_TYPE_SDIO:
 		ret = pld_sdio_is_fw_dump_skipped();
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	default:
 		break;
 	}
@@ -1888,6 +2329,8 @@
 	case PLD_BUS_TYPE_SNOC:
 		ret = pld_snoc_is_pdr();
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	default:
 		break;
 	}
@@ -1903,6 +2346,8 @@
 	case PLD_BUS_TYPE_SNOC:
 		ret = pld_snoc_is_fw_rejuvenate();
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	default:
 		break;
 	}
@@ -1917,6 +2362,10 @@
 	case PLD_BUS_TYPE_PCIE:
 		ret = pld_pcie_platform_driver_support();
 		break;
+	case PLD_BUS_TYPE_PCIE_FW_SIM:
+		ret = true;
+		break;
+	case PLD_BUS_TYPE_SNOC_FW_SIM:
 	case PLD_BUS_TYPE_SNOC:
 		break;
 	case PLD_BUS_TYPE_SDIO:
@@ -1949,6 +2398,12 @@
 		case PLD_BUS_TYPE_PCIE:
 			errno = pld_pcie_idle_shutdown(dev);
 			break;
+		case PLD_BUS_TYPE_PCIE_FW_SIM:
+			errno = pld_pcie_fw_sim_idle_shutdown(dev);
+			break;
+		case PLD_BUS_TYPE_SNOC_FW_SIM:
+			errno = pld_snoc_fw_sim_idle_shutdown(dev);
+			break;
 		default:
 			pr_err("Invalid device type %d\n", type);
 			break;
@@ -1976,6 +2431,12 @@
 		case PLD_BUS_TYPE_PCIE:
 			errno = pld_pcie_idle_restart(dev);
 			break;
+		case PLD_BUS_TYPE_PCIE_FW_SIM:
+			errno = pld_pcie_fw_sim_idle_restart(dev);
+			break;
+		case PLD_BUS_TYPE_SNOC_FW_SIM:
+			errno = pld_snoc_fw_sim_idle_restart(dev);
+			break;
 		default:
 			pr_err("Invalid device type %d\n", type);
 			break;
diff --git a/core/pld/src/pld_pcie.h b/core/pld/src/pld_pcie.h
index aab8196..8abc885 100644
--- a/core/pld/src/pld_pcie.h
+++ b/core/pld/src/pld_pcie.h
@@ -22,6 +22,7 @@
 #ifdef CONFIG_PLD_PCIE_CNSS
 #include <net/cnss2.h>
 #endif
+#include <linux/pci.h>
 #include "pld_internal.h"
 
 #ifdef DYNAMIC_SINGLE_CHIP
@@ -36,7 +37,7 @@
 
 #endif
 
-#ifndef HIF_PCI
+#ifndef CONFIG_PLD_PCIE_CNSS
 static inline int pld_pcie_register_driver(void)
 {
 	return 0;
diff --git a/core/pld/src/pld_pcie_fw_sim.c b/core/pld/src/pld_pcie_fw_sim.c
new file mode 100644
index 0000000..46f9ac2
--- /dev/null
+++ b/core/pld/src/pld_pcie_fw_sim.c
@@ -0,0 +1,453 @@
+/*
+ * Copyright (c) 2016-2019 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
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include "osif_psoc_sync.h"
+
+#include "pld_pcie_fw_sim.h"
+
+#ifdef CONFIG_PLD_PCIE_FW_SIM
+
+#ifdef QCA_WIFI_3_0_ADRASTEA
+#define CE_COUNT_MAX 12
+#else
+#define CE_COUNT_MAX 8
+#endif
+
+/**
+ * pld_pcie_fw_sim_probe() - Probe function for PCIE platform driver
+ * @pdev: PCIE device
+ * @id: PCIE device ID table
+ *
+ * The probe function will be called when PCIE device provided
+ * in the ID table is detected.
+ *
+ * Return: int
+ */
+static int pld_pcie_fw_sim_probe(struct pci_dev *pdev,
+				 const struct pci_device_id *id)
+{
+	struct pld_context *pld_context;
+	int ret = 0;
+
+	pld_context = pld_get_global_context();
+	if (!pld_context) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	ret = pld_add_dev(pld_context, &pdev->dev, NULL,
+			  PLD_BUS_TYPE_PCIE_FW_SIM);
+	if (ret)
+		goto out;
+
+	return pld_context->ops->probe(&pdev->dev,
+		       PLD_BUS_TYPE_PCIE_FW_SIM, pdev, (void *)id);
+
+out:
+	return ret;
+}
+
+/**
+ * pld_pcie_fw_sim_remove() - Remove function for PCIE device
+ * @pdev: PCIE device
+ *
+ * The remove function will be called when PCIE device is disconnected
+ *
+ * Return: void
+ */
+static void pld_pcie_fw_sim_remove(struct pci_dev *pdev)
+{
+	struct pld_context *pld_context;
+	int errno;
+	struct osif_psoc_sync *psoc_sync;
+
+	errno = osif_psoc_sync_trans_start_wait(&pdev->dev, &psoc_sync);
+	if (errno)
+		return;
+
+	osif_psoc_sync_unregister(&pdev->dev);
+	osif_psoc_sync_wait_for_ops(psoc_sync);
+
+	pld_context = pld_get_global_context();
+
+	if (!pld_context)
+		goto out;
+
+	pld_context->ops->remove(&pdev->dev, PLD_BUS_TYPE_PCIE_FW_SIM);
+
+	pld_del_dev(pld_context, &pdev->dev);
+
+out:
+	osif_psoc_sync_trans_stop(psoc_sync);
+	osif_psoc_sync_destroy(psoc_sync);
+}
+
+/**
+ * pld_pcie_fw_sim_idle_restart_cb() - Perform idle restart
+ * @pdev: PCIE device
+ * @id: PCIE device ID
+ *
+ * This function will be called if there is an idle restart request
+ *
+ * Return: int
+ */
+static int pld_pcie_fw_sim_idle_restart_cb(struct pci_dev *pdev,
+					   const struct pci_device_id *id)
+{
+	struct pld_context *pld_context;
+
+	pld_context = pld_get_global_context();
+	if (pld_context->ops->idle_restart)
+		return pld_context->ops->idle_restart(&pdev->dev,
+						      PLD_BUS_TYPE_PCIE_FW_SIM);
+
+	return -ENODEV;
+}
+
+/**
+ * pld_pcie_fw_sim_idle_shutdown_cb() - Perform idle shutdown
+ * @pdev: PCIE device
+ * @id: PCIE device ID
+ *
+ * This function will be called if there is an idle shutdown request
+ *
+ * Return: int
+ */
+static int pld_pcie_fw_sim_idle_shutdown_cb(struct pci_dev *pdev)
+{
+	struct pld_context *pld_context;
+
+	pld_context = pld_get_global_context();
+	if (pld_context->ops->shutdown)
+		return pld_context->ops->idle_shutdown(&pdev->dev,
+						PLD_BUS_TYPE_PCIE_FW_SIM);
+
+	return -ENODEV;
+}
+
+/**
+ * pld_pcie_fw_sim_reinit() - SSR re-initialize function for PCIE device
+ * @pdev: PCIE device
+ * @id: PCIE device ID
+ *
+ * During subsystem restart(SSR), this function will be called to
+ * re-initialize pcie device.
+ *
+ * Return: int
+ */
+static int pld_pcie_fw_sim_reinit(struct pci_dev *pdev,
+				  const struct pci_device_id *id)
+{
+	struct pld_context *pld_context;
+
+	pld_context = pld_get_global_context();
+	if (pld_context->ops->reinit)
+		return pld_context->ops->reinit(&pdev->dev,
+				PLD_BUS_TYPE_PCIE_FW_SIM, pdev, (void *)id);
+
+	return -ENODEV;
+}
+
+/**
+ * pld_pcie_fw_sim_shutdown() - SSR shutdown function for PCIE device
+ * @pdev: PCIE device
+ *
+ * During SSR, this function will be called to shutdown PCIE device.
+ *
+ * Return: void
+ */
+static void pld_pcie_fw_sim_shutdown(struct pci_dev *pdev)
+{
+	struct pld_context *pld_context;
+
+	pld_context = pld_get_global_context();
+	if (pld_context->ops->shutdown)
+		pld_context->ops->shutdown(&pdev->dev,
+						PLD_BUS_TYPE_PCIE_FW_SIM);
+}
+
+/**
+ * pld_pcie_fw_sim_crash_shutdown() - Crash shutdown function for PCIE device
+ * @pdev: PCIE device
+ *
+ * This function will be called when a crash is detected, it will shutdown
+ * the PCIE device.
+ *
+ * Return: void
+ */
+static void pld_pcie_fw_sim_crash_shutdown(struct pci_dev *pdev)
+{
+	struct pld_context *pld_context;
+
+	pld_context = pld_get_global_context();
+	if (pld_context->ops->crash_shutdown)
+		pld_context->ops->crash_shutdown(&pdev->dev,
+						PLD_BUS_TYPE_PCIE_FW_SIM);
+}
+
+/**
+ * pld_pcie_fw_sim_notify_handler() - Modem state notification callback function
+ * @pdev: PCIE device
+ * @state: modem power state
+ *
+ * This function will be called when there's a modem power state change.
+ *
+ * Return: void
+ */
+static void pld_pcie_fw_sim_notify_handler(struct pci_dev *pdev, int state)
+{
+	struct pld_context *pld_context;
+
+	pld_context = pld_get_global_context();
+	if (pld_context->ops->modem_status)
+		pld_context->ops->modem_status(&pdev->dev,
+					       PLD_BUS_TYPE_PCIE_FW_SIM, state);
+}
+
+/**
+ * pld_pcie_fw_sim_uevent() - update wlan driver status callback function
+ * @pdev: PCIE device
+ * @status driver uevent status
+ *
+ * This function will be called when platform driver wants to update wlan
+ * driver's status.
+ *
+ * Return: void
+ */
+static void pld_pcie_fw_sim_uevent(struct pci_dev *pdev, uint32_t status)
+{
+	struct pld_context *pld_context;
+	struct pld_uevent_data data;
+
+	pld_context = pld_get_global_context();
+	if (!pld_context)
+		return;
+
+	switch (status) {
+	case CNSS_RECOVERY:
+		data.uevent = PLD_FW_RECOVERY_START;
+		break;
+	case CNSS_FW_DOWN:
+		data.uevent = PLD_FW_DOWN;
+		break;
+	default:
+		goto out;
+	}
+
+	if (pld_context->ops->uevent)
+		pld_context->ops->uevent(&pdev->dev, &data);
+
+out:
+	return;
+}
+
+static struct pci_device_id pld_pcie_fw_sim_id_table[] = {
+	{ 0x168c, 0x003c, PCI_ANY_ID, PCI_ANY_ID },
+	{ 0x168c, 0x003e, PCI_ANY_ID, PCI_ANY_ID },
+	{ 0x168c, 0x0041, PCI_ANY_ID, PCI_ANY_ID },
+	{ 0x168c, 0xabcd, PCI_ANY_ID, PCI_ANY_ID },
+	{ 0x168c, 0x7021, PCI_ANY_ID, PCI_ANY_ID },
+	{ 0 }
+};
+
+#ifdef MULTI_IF_NAME
+#define PLD_PCIE_FW_SIM_OPS_NAME "pld_pcie_fw_sim_" MULTI_IF_NAME
+#else
+#define PLD_PCIE_FW_SIM_OPS_NAME "pld_pcie_fw_sim"
+#endif
+
+struct cnss_wlan_driver pld_pcie_fw_sim_ops = {
+	.name       = PLD_PCIE_FW_SIM_OPS_NAME,
+	.id_table   = pld_pcie_fw_sim_id_table,
+	.probe      = pld_pcie_fw_sim_probe,
+	.remove     = pld_pcie_fw_sim_remove,
+	.idle_restart  = pld_pcie_fw_sim_idle_restart_cb,
+	.idle_shutdown = pld_pcie_fw_sim_idle_shutdown_cb,
+	.reinit     = pld_pcie_fw_sim_reinit,
+	.shutdown   = pld_pcie_fw_sim_shutdown,
+	.crash_shutdown = pld_pcie_fw_sim_crash_shutdown,
+	.modem_status   = pld_pcie_fw_sim_notify_handler,
+	.update_status  = pld_pcie_fw_sim_uevent,
+};
+
+/**
+ * pld_pcie_fw_sim_register_driver() - Register PCIE device callback functions
+ *
+ * Return: int
+ */
+int pld_pcie_fw_sim_register_driver(void)
+{
+	return cnss_fw_sim_wlan_register_driver(&pld_pcie_fw_sim_ops);
+}
+
+/**
+ * pld_pcie_fw_sim_unregister_driver() - Unregister PCIE device callback
+ *					 functions
+ *
+ * Return: void
+ */
+void pld_pcie_fw_sim_unregister_driver(void)
+{
+	cnss_fw_sim_wlan_unregister_driver(&pld_pcie_fw_sim_ops);
+}
+
+/**
+ * pld_pcie_fw_sim_wlan_enable() - Enable WLAN
+ * @dev: device
+ * @config: WLAN configuration data
+ * @mode: WLAN mode
+ * @host_version: host software version
+ *
+ * This function enables WLAN FW. It passed WLAN configuration data,
+ * WLAN mode and host software version to FW.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_pcie_fw_sim_wlan_enable(struct device *dev,
+				struct pld_wlan_enable_cfg *config,
+				enum pld_driver_mode mode,
+				const char *host_version)
+{
+	struct cnss_wlan_enable_cfg cfg;
+	enum cnss_driver_mode cnss_mode;
+
+	cfg.num_ce_tgt_cfg = config->num_ce_tgt_cfg;
+	cfg.ce_tgt_cfg = (struct cnss_ce_tgt_pipe_cfg *)
+		config->ce_tgt_cfg;
+	cfg.num_ce_svc_pipe_cfg = config->num_ce_svc_pipe_cfg;
+	cfg.ce_svc_cfg = (struct cnss_ce_svc_pipe_cfg *)
+		config->ce_svc_cfg;
+	cfg.num_shadow_reg_cfg = config->num_shadow_reg_cfg;
+	cfg.shadow_reg_cfg = (struct cnss_shadow_reg_cfg *)
+		config->shadow_reg_cfg;
+	cfg.num_shadow_reg_v2_cfg = config->num_shadow_reg_v2_cfg;
+	cfg.shadow_reg_v2_cfg = (struct cnss_shadow_reg_v2_cfg *)
+		config->shadow_reg_v2_cfg;
+	cfg.rri_over_ddr_cfg_valid = config->rri_over_ddr_cfg_valid;
+	if (config->rri_over_ddr_cfg_valid) {
+		cfg.rri_over_ddr_cfg.base_addr_low =
+			 config->rri_over_ddr_cfg.base_addr_low;
+		cfg.rri_over_ddr_cfg.base_addr_high =
+			 config->rri_over_ddr_cfg.base_addr_high;
+	}
+
+	switch (mode) {
+	case PLD_FTM:
+		cnss_mode = CNSS_FTM;
+		break;
+	case PLD_EPPING:
+		cnss_mode = CNSS_EPPING;
+		break;
+	default:
+		cnss_mode = CNSS_MISSION;
+		break;
+	}
+	return cnss_fw_sim_wlan_enable(dev, &cfg, cnss_mode, host_version);
+}
+
+/**
+ * pld_pcie_fw_sim_wlan_disable() - Disable WLAN
+ * @dev: device
+ * @mode: WLAN mode
+ *
+ * This function disables WLAN FW. It passes WLAN mode to FW.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_pcie_fw_sim_wlan_disable(struct device *dev, enum pld_driver_mode mode)
+{
+	return cnss_fw_sim_wlan_disable(dev, CNSS_OFF);
+}
+
+/**
+ * pld_pcie_fw_sim_get_soc_info() - Get SOC information
+ * @dev: device
+ * @info: buffer to SOC information
+ *
+ * Return SOC info to the buffer.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_pcie_fw_sim_get_soc_info(struct device *dev, struct pld_soc_info *info)
+{
+	int ret = 0;
+	struct cnss_soc_info cnss_info = {0};
+
+	if (!info)
+		return -ENODEV;
+
+	ret = cnss_fw_sim_get_soc_info(dev, &cnss_info);
+	if (ret)
+		return ret;
+
+	info->v_addr = cnss_info.va;
+	info->p_addr = cnss_info.pa;
+	info->chip_id = cnss_info.chip_id;
+	info->chip_family = cnss_info.chip_family;
+	info->board_id = cnss_info.board_id;
+	info->soc_id = cnss_info.soc_id;
+	info->fw_version = cnss_info.fw_version;
+	strlcpy(info->fw_build_timestamp, cnss_info.fw_build_timestamp,
+		sizeof(info->fw_build_timestamp));
+	info->device_version.family_number =
+		cnss_info.device_version.family_number;
+	info->device_version.device_number =
+		cnss_info.device_version.device_number;
+	info->device_version.major_version =
+		cnss_info.device_version.major_version;
+	info->device_version.minor_version =
+		cnss_info.device_version.minor_version;
+
+	return 0;
+}
+
+/**
+ * pld_pcie_fw_sim_get_platform_cap() - Get platform capabilities
+ * @dev: device
+ * @cap: buffer to the capabilities
+ *
+ * Return capabilities to the buffer.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_pcie_fw_sim_get_platform_cap(struct device *dev,
+				     struct pld_platform_cap *cap)
+{
+	int ret = 0;
+	struct cnss_platform_cap cnss_cap;
+
+	if (!cap)
+		return -ENODEV;
+
+	ret = cnss_fw_sim_get_platform_cap(dev, &cnss_cap);
+	if (ret)
+		return ret;
+
+	memcpy(cap, &cnss_cap, sizeof(*cap));
+	return 0;
+}
+
+#endif
diff --git a/core/pld/src/pld_pcie_fw_sim.h b/core/pld/src/pld_pcie_fw_sim.h
new file mode 100644
index 0000000..0eed0d5
--- /dev/null
+++ b/core/pld/src/pld_pcie_fw_sim.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) 2016-2019 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
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __PLD_PCIE_FW_SIM_H__
+#define __PLD_PCIE_FW_SIM_H__
+
+#include "pld_internal.h"
+
+#ifndef CONFIG_PLD_PCIE_FW_SIM
+
+static inline int pld_pcie_fw_sim_register_driver(void)
+{
+	return 0;
+}
+
+static inline void pld_pcie_fw_sim_unregister_driver(void)
+{
+}
+
+static inline int pld_pcie_fw_sim_wlan_enable(struct device *dev,
+					      struct pld_wlan_enable_cfg *cfg,
+					      enum pld_driver_mode mode,
+					      const char *host_version)
+{
+	return 0;
+}
+
+static inline int pld_pcie_fw_sim_wlan_disable(struct device *dev,
+					       enum pld_driver_mode mode)
+{
+	return 0;
+}
+
+static inline void pld_pcie_fw_sim_link_down(struct device *dev)
+{
+}
+
+static inline int pld_pcie_fw_sim_is_fw_down(struct device *dev)
+{
+	return 0;
+}
+
+static inline int pld_pcie_fw_sim_get_platform_cap(struct device *dev,
+						   struct pld_platform_cap *cap)
+{
+	return 0;
+}
+
+static inline int pld_pcie_fw_sim_get_soc_info(struct device *dev,
+					       struct pld_soc_info *info)
+{
+	return 0;
+}
+
+static inline int pld_pcie_fw_sim_get_user_msi_assignment(struct device *dev,
+							  char *user_name,
+							  int *num_vectors,
+							  uint32_t *base_data,
+							  uint32_t *base_vector)
+{
+	return -EINVAL;
+}
+
+static inline int pld_pcie_fw_sim_get_msi_irq(struct device *dev,
+					      unsigned int vector)
+{
+	return 0;
+}
+
+static inline void pld_pcie_fw_sim_get_msi_address(struct device *dev,
+						   uint32_t *msi_addr_low,
+						   uint32_t *msi_addr_high)
+{
+}
+
+static inline int pld_pcie_fw_sim_request_irq(struct device *dev, int irq,
+					      irq_handler_t handler,
+					      unsigned long irqflags,
+					      const char *devname,
+					      void *dev_data)
+{
+	return 0;
+}
+
+static inline int pld_pcie_fw_sim_free_irq(struct device *dev,
+					   unsigned int ce_id, void *ctx)
+{
+	return 0;
+}
+
+static inline void pld_pcie_fw_sim_enable_irq(struct device *dev,
+					      unsigned int irq)
+{
+}
+
+static inline void pld_pcie_fw_sim_disable_irq(struct device *dev,
+					       unsigned int irq)
+{
+}
+
+static inline int pld_pcie_fw_sim_idle_shutdown(struct device *dev)
+{
+	return 0;
+}
+
+static inline int pld_pcie_fw_sim_idle_restart(struct device *dev)
+{
+	return 0;
+}
+#else
+#include <net/cnss2.h>
+
+int pld_pcie_fw_sim_wlan_enable(struct device *dev,
+				struct pld_wlan_enable_cfg *config,
+				enum pld_driver_mode mode,
+				const char *host_version);
+int pld_pcie_fw_sim_wlan_disable(struct device *dev, enum pld_driver_mode mode);
+int pld_pcie_fw_sim_register_driver(void);
+void pld_pcie_fw_sim_unregister_driver(void);
+int pld_pcie_fw_sim_get_platform_cap(struct device *dev,
+				     struct pld_platform_cap *cap);
+int pld_pcie_fw_sim_get_soc_info(struct device *dev, struct pld_soc_info *info);
+
+static inline int pld_pcie_fw_sim_get_user_msi_assignment(struct device *dev,
+							  char *user_name,
+							  int *num_vectors,
+							  uint32_t *base_data,
+							  uint32_t *base_vector)
+{
+	return cnss_fw_sim_get_user_msi_assignment(dev, user_name, num_vectors,
+					    base_data, base_vector);
+}
+
+static inline int pld_pcie_fw_sim_get_msi_irq(struct device *dev,
+					      unsigned int vector)
+{
+	return cnss_fw_sim_get_msi_irq(dev, vector);
+}
+
+static inline void pld_pcie_fw_sim_get_msi_address(struct device *dev,
+						   uint32_t *msi_addr_low,
+						   uint32_t *msi_addr_high)
+{
+	cnss_fw_sim_get_msi_address(dev, msi_addr_low, msi_addr_high);
+}
+
+static inline int pld_pcie_fw_sim_request_irq(struct device *dev, int irq,
+					      irq_handler_t handler,
+					      unsigned long irqflags,
+					      const char *devname,
+					      void *dev_data)
+{
+	return cnss_fw_sim_request_irq(dev, irq, handler,
+				       irqflags, devname, dev_data);
+}
+
+static inline int pld_pcie_fw_sim_free_irq(struct device *dev,
+					   int irq, void *dev_data)
+{
+	return cnss_fw_sim_free_irq(dev, irq, dev_data);
+}
+
+static inline void pld_pcie_fw_sim_enable_irq(struct device *dev, int irq)
+{
+	cnss_fw_sim_enable_irq(dev, irq);
+}
+
+static inline void pld_pcie_fw_sim_disable_irq(struct device *dev, int irq)
+{
+	cnss_fw_sim_disable_irq(dev, irq);
+}
+
+static inline int pld_pcie_fw_sim_idle_shutdown(struct device *dev)
+{
+	return cnss_fw_sim_idle_shutdown(dev);
+}
+
+static inline int pld_pcie_fw_sim_idle_restart(struct device *dev)
+{
+	return cnss_fw_sim_idle_restart(dev);
+}
+#endif
+#endif
diff --git a/core/pld/src/pld_snoc_fw_sim.c b/core/pld/src/pld_snoc_fw_sim.c
new file mode 100644
index 0000000..94c2359
--- /dev/null
+++ b/core/pld/src/pld_snoc_fw_sim.c
@@ -0,0 +1,397 @@
+/*
+ * Copyright (c) 2016-2019 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
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+
+#include "pld_snoc_fw_sim.h"
+
+#ifdef CONFIG_PLD_SNOC_FW_SIM
+/**
+ * pld_snoc_fw_sim_probe() - Probe function for platform driver
+ * @dev: device
+ *
+ * The probe function will be called when platform device
+ * is detected.
+ *
+ * Return: int
+ */
+static int pld_snoc_fw_sim_probe(struct device *dev)
+{
+	struct pld_context *pld_context;
+	int ret = 0;
+
+	pld_context = pld_get_global_context();
+	if (!pld_context) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	ret = pld_add_dev(pld_context, dev, NULL, PLD_BUS_TYPE_SNOC_FW_SIM);
+	if (ret)
+		goto out;
+
+	return pld_context->ops->probe(dev, PLD_BUS_TYPE_SNOC_FW_SIM,
+				       NULL, NULL);
+
+out:
+	return ret;
+}
+
+/**
+ * pld_snoc_fw_sim_remove() - Remove function for platform device
+ * @dev: device
+ *
+ * The remove function will be called when platform device
+ * is disconnected
+ *
+ * Return: void
+ */
+static void pld_snoc_fw_sim_remove(struct device *dev)
+{
+	struct pld_context *pld_context;
+
+	pld_context = pld_get_global_context();
+
+	if (!pld_context)
+		return;
+
+	pld_context->ops->remove(dev, PLD_BUS_TYPE_SNOC_FW_SIM);
+
+	pld_del_dev(pld_context, dev);
+}
+
+/**
+ * pld_snoc_fw_sim_reinit() - SSR re-initialize function for platform device
+ * @dev: device
+ *
+ * During subsystem restart(SSR), this function will be called to
+ * re-initialize platform device.
+ *
+ * Return: int
+ */
+static int pld_snoc_fw_sim_reinit(struct device *dev)
+{
+	struct pld_context *pld_context;
+
+	pld_context = pld_get_global_context();
+	if (pld_context->ops->reinit)
+		return pld_context->ops->reinit(dev, PLD_BUS_TYPE_SNOC_FW_SIM,
+						NULL, NULL);
+
+	return -ENODEV;
+}
+
+/**
+ * pld_snoc_fw_sim_shutdown() - SSR shutdown function for platform device
+ * @dev: device
+ *
+ * During SSR, this function will be called to shutdown platform device.
+ *
+ * Return: void
+ */
+static void pld_snoc_fw_sim_shutdown(struct device *dev)
+{
+	struct pld_context *pld_context;
+
+	pld_context = pld_get_global_context();
+	if (pld_context->ops->shutdown)
+		pld_context->ops->shutdown(dev, PLD_BUS_TYPE_SNOC_FW_SIM);
+}
+
+/**
+ * pld_snoc_fw_sim_crash_shutdown() -Crash shutdown function for platform device
+ * @dev: device
+ *
+ * This function will be called when a crash is detected, it will shutdown
+ * platform device.
+ *
+ * Return: void
+ */
+static void pld_snoc_fw_sim_crash_shutdown(void *dev)
+{
+	struct pld_context *pld_context;
+
+	pld_context = pld_get_global_context();
+	if (pld_context->ops->crash_shutdown)
+		pld_context->ops->crash_shutdown(dev, PLD_BUS_TYPE_SNOC_FW_SIM);
+}
+
+/**
+ * pld_snoc_fw_sim_pm_suspend() - PM suspend callback function for power
+ *				  management
+ * @dev: device
+ *
+ * This function is to suspend the platform device when power management
+ * is enabled.
+ *
+ * Return: void
+ */
+static int pld_snoc_fw_sim_pm_suspend(struct device *dev)
+{
+	struct pld_context *pld_context;
+	pm_message_t state;
+
+	state.event = PM_EVENT_SUSPEND;
+	pld_context = pld_get_global_context();
+	return pld_context->ops->suspend(dev, PLD_BUS_TYPE_SNOC_FW_SIM, state);
+}
+
+/**
+ * pld_snoc_fw_sim_pm_resume() -PM resume callback function for power management
+ * @pdev: device
+ *
+ * This function is to resume the platform device when power management
+ * is enabled.
+ *
+ * Return: void
+ */
+static int pld_snoc_fw_sim_pm_resume(struct device *dev)
+{
+	struct pld_context *pld_context;
+
+	pld_context = pld_get_global_context();
+	return pld_context->ops->resume(dev, PLD_BUS_TYPE_SNOC_FW_SIM);
+}
+
+/**
+ * pld_snoc_fw_sim_suspend_noirq() - Complete the actions started by suspend()
+ * @dev: device
+ *
+ * Complete the actions started by suspend().  Carry out any
+ * additional operations required for suspending the device that might be
+ * racing with its driver's interrupt handler, which is guaranteed not to
+ * run while suspend_noirq() is being executed.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+static int pld_snoc_fw_sim_suspend_noirq(struct device *dev)
+{
+	struct pld_context *pld_context;
+
+	pld_context = pld_get_global_context();
+	if (!pld_context)
+		return -EINVAL;
+
+	if (pld_context->ops->suspend_noirq)
+		return pld_context->ops->suspend_noirq(dev,
+						      PLD_BUS_TYPE_SNOC_FW_SIM);
+	return 0;
+}
+
+/**
+ * pld_snoc_fw_sim_resume_noirq() - Prepare for the execution of resume()
+ * @pdev: device
+ *
+ * Prepare for the execution of resume() by carrying out any
+ * operations required for resuming the device that might be racing with
+ * its driver's interrupt handler, which is guaranteed not to run while
+ * resume_noirq() is being executed.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+static int pld_snoc_fw_sim_resume_noirq(struct device *dev)
+{
+	struct pld_context *pld_context;
+
+	pld_context = pld_get_global_context();
+	if (!pld_context)
+		return -EINVAL;
+
+	if (pld_context->ops->resume_noirq)
+		return pld_context->ops->resume_noirq(dev,
+						      PLD_BUS_TYPE_SNOC_FW_SIM);
+
+	return 0;
+}
+
+static int pld_snoc_fw_sim_uevent(struct device *dev,
+				  struct icnss_uevent_data *uevent)
+{
+	struct pld_context *pld_context;
+	struct icnss_uevent_fw_down_data *uevent_data = NULL;
+	struct pld_uevent_data data;
+
+	pld_context = pld_get_global_context();
+	if (!pld_context)
+		return -EINVAL;
+
+	if (!pld_context->ops->uevent)
+		return 0;
+
+	if (!uevent)
+		return -EINVAL;
+
+	switch (uevent->uevent) {
+	case ICNSS_UEVENT_FW_CRASHED:
+		data.uevent = PLD_FW_CRASHED;
+		break;
+	case ICNSS_UEVENT_FW_DOWN:
+		if (!uevent->data)
+			return -EINVAL;
+		uevent_data = (struct icnss_uevent_fw_down_data *)uevent->data;
+		data.uevent = PLD_FW_DOWN;
+		data.fw_down.crashed = uevent_data->crashed;
+		break;
+	default:
+		return 0;
+	}
+
+	pld_context->ops->uevent(dev, &data);
+	return 0;
+}
+
+#ifdef MULTI_IF_NAME
+#define PLD_SNOC_FW_SIM_OPS_NAME "pld_snoc_fw_sim_" MULTI_IF_NAME
+#else
+#define PLD_SNOC_FW_SIM_OPS_NAME "pld_snoc_fw_sim"
+#endif
+
+struct icnss_driver_ops pld_snoc_fw_sim_ops = {
+	.name       = PLD_SNOC_FW_SIM_OPS_NAME,
+	.probe      = pld_snoc_fw_sim_probe,
+	.remove     = pld_snoc_fw_sim_remove,
+	.shutdown   = pld_snoc_fw_sim_shutdown,
+	.reinit     = pld_snoc_fw_sim_reinit,
+	.crash_shutdown = pld_snoc_fw_sim_crash_shutdown,
+	.pm_suspend = pld_snoc_fw_sim_pm_suspend,
+	.pm_resume  = pld_snoc_fw_sim_pm_resume,
+	.suspend_noirq = pld_snoc_fw_sim_suspend_noirq,
+	.resume_noirq = pld_snoc_fw_sim_resume_noirq,
+	.uevent = pld_snoc_fw_sim_uevent,
+};
+
+/**
+ * pld_snoc_fw_sim_register_driver() - Register platform device callback
+ *				       functions
+ *
+ * Return: int
+ */
+int pld_snoc_fw_sim_register_driver(void)
+{
+	return icnss_register_driver(&pld_snoc_fw_sim_ops);
+}
+
+/**
+ * pld_snoc_fw_sim_unregister_driver() - Unregister platform device callback
+ *					 functions
+ *
+ * Return: void
+ */
+void pld_snoc_fw_sim_unregister_driver(void)
+{
+	icnss_unregister_driver(&pld_snoc_fw_sim_ops);
+}
+
+/**
+ * pld_snoc_fw_sim_wlan_enable() - Enable WLAN
+ * @dev: device
+ * @config: WLAN configuration data
+ * @mode: WLAN mode
+ * @host_version: host software version
+ *
+ * This function enables WLAN FW. It passed WLAN configuration data,
+ * WLAN mode and host software version to FW.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_snoc_fw_sim_wlan_enable(struct device *dev,
+				struct pld_wlan_enable_cfg *config,
+				enum pld_driver_mode mode,
+				const char *host_version)
+{
+	struct icnss_wlan_enable_cfg cfg;
+	enum icnss_driver_mode icnss_mode;
+
+	if (!dev)
+		return -ENODEV;
+
+	cfg.num_ce_tgt_cfg = config->num_ce_tgt_cfg;
+	cfg.ce_tgt_cfg = (struct ce_tgt_pipe_cfg *)
+		config->ce_tgt_cfg;
+	cfg.num_ce_svc_pipe_cfg = config->num_ce_svc_pipe_cfg;
+	cfg.ce_svc_cfg = (struct ce_svc_pipe_cfg *)
+		config->ce_svc_cfg;
+	cfg.num_shadow_reg_cfg = config->num_shadow_reg_cfg;
+	cfg.shadow_reg_cfg = (struct icnss_shadow_reg_cfg *)
+		config->shadow_reg_cfg;
+
+	switch (mode) {
+	case PLD_FTM:
+		icnss_mode = ICNSS_FTM;
+		break;
+	case PLD_EPPING:
+		icnss_mode = ICNSS_EPPING;
+		break;
+	default:
+		icnss_mode = ICNSS_MISSION;
+		break;
+	}
+
+	return icnss_wlan_enable(dev, &cfg, icnss_mode, host_version);
+}
+
+/**
+ * pld_snoc_fw_sim_wlan_disable() - Disable WLAN
+ * @dev: device
+ * @mode: WLAN mode
+ *
+ * This function disables WLAN FW. It passes WLAN mode to FW.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_snoc_fw_sim_wlan_disable(struct device *dev, enum pld_driver_mode mode)
+{
+	if (!dev)
+		return -ENODEV;
+
+	return icnss_wlan_disable(dev, ICNSS_OFF);
+}
+
+/**
+ * pld_snoc_fw_sim_get_soc_info() - Get SOC information
+ * @dev: device
+ * @info: buffer to SOC information
+ *
+ * Return SOC info to the buffer.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_snoc_fw_sim_get_soc_info(struct device *dev, struct pld_soc_info *info)
+{
+	int ret = 0;
+	struct icnss_soc_info icnss_info;
+
+	if (!info || !dev)
+		return -ENODEV;
+
+	ret = icnss_get_soc_info(dev, &icnss_info);
+	if (0 != ret)
+		return ret;
+
+	memcpy(info, &icnss_info, sizeof(*info));
+	return 0;
+}
+#endif
diff --git a/core/pld/src/pld_snoc_fw_sim.h b/core/pld/src/pld_snoc_fw_sim.h
new file mode 100644
index 0000000..5f68eb2
--- /dev/null
+++ b/core/pld/src/pld_snoc_fw_sim.h
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2016-2019 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
+ * above copyright notice and this permission notice appear in all
+ * copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
+ * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __PLD_SNOC_FW_SIM_H__
+#define __PLD_SNOC_FW_SIM_H__
+
+#include "pld_internal.h"
+
+#ifndef CONFIG_PLD_SNOC_FW_SIM
+static inline int pld_snoc_fw_sim_register_driver(void)
+{
+	return 0;
+}
+
+static inline void pld_snoc_fw_sim_unregister_driver(void)
+{
+}
+
+static inline int pld_snoc_fw_sim_wlan_enable(struct device *dev,
+					      struct pld_wlan_enable_cfg *cfg,
+					      enum pld_driver_mode mode,
+					      const char *host_version)
+{
+	return 0;
+}
+
+static inline int pld_snoc_fw_sim_wlan_disable(struct device *dev,
+					       enum pld_driver_mode mode)
+{
+	return 0;
+}
+
+static inline int pld_snoc_fw_sim_ce_request_irq(struct device *dev,
+						 unsigned int ce_id,
+					  irqreturn_t (*handler)(int, void *),
+					  unsigned long flags,
+					  const char *name, void *ctx)
+{
+	return 0;
+}
+
+static inline int pld_snoc_fw_sim_ce_free_irq(struct device *dev,
+					      unsigned int ce_id, void *ctx)
+{
+	return 0;
+}
+
+static inline void pld_snoc_fw_sim_enable_irq(struct device *dev,
+					      unsigned int ce_id)
+{
+}
+
+static inline void pld_snoc_fw_sim_disable_irq(struct device *dev,
+					       unsigned int ce_id)
+{
+}
+
+static inline int pld_snoc_fw_sim_get_soc_info(struct device *dev,
+					       struct pld_soc_info *info)
+{
+	return 0;
+}
+
+static inline int pld_snoc_fw_sim_get_ce_id(struct device *dev, int irq)
+{
+	return 0;
+}
+
+static inline int pld_snoc_fw_sim_get_irq(struct device *dev, int ce_id)
+{
+	return 0;
+}
+
+static inline int pld_snoc_fw_sim_is_fw_down(struct device *dev)
+{
+	return 0;
+}
+
+static inline int pld_snoc_fw_sim_idle_shutdown(struct device *dev)
+{
+	return 0;
+}
+
+static inline int pld_snoc_fw_sim_idle_restart(struct device *dev)
+{
+	return 0;
+}
+
+#else
+#include <soc/icnss.h>
+
+int pld_snoc_fw_sim_register_driver(void);
+void pld_snoc_fw_sim_unregister_driver(void);
+int pld_snoc_fw_sim_wlan_enable(struct device *dev,
+				struct pld_wlan_enable_cfg *config,
+				enum pld_driver_mode mode,
+				const char *host_version);
+int pld_snoc_fw_sim_wlan_disable(struct device *dev, enum pld_driver_mode mode);
+int pld_snoc_fw_sim_get_soc_info(struct device *dev, struct pld_soc_info *info);
+
+static inline int pld_snoc_fw_sim_ce_request_irq(struct device *dev,
+						 unsigned int ce_id,
+					irqreturn_t (*handler)(int, void *),
+					unsigned long flags,
+					const char *name, void *ctx)
+{
+	if (!dev)
+		return -ENODEV;
+
+	return icnss_ce_request_irq(dev, ce_id, handler, flags, name, ctx);
+}
+
+static inline int pld_snoc_fw_sim_ce_free_irq(struct device *dev,
+					      unsigned int ce_id, void *ctx)
+{
+	if (!dev)
+		return -ENODEV;
+
+	return icnss_ce_free_irq(dev, ce_id, ctx);
+}
+
+static inline void pld_snoc_fw_sim_enable_irq(struct device *dev,
+					      unsigned int ce_id)
+{
+	if (dev)
+		icnss_enable_irq(dev, ce_id);
+}
+
+static inline void pld_snoc_fw_sim_disable_irq(struct device *dev,
+					       unsigned int ce_id)
+{
+	if (dev)
+		icnss_disable_irq(dev, ce_id);
+}
+
+static inline int pld_snoc_fw_sim_get_ce_id(struct device *dev, int irq)
+{
+	if (!dev)
+		return -ENODEV;
+
+	return icnss_get_ce_id(dev, irq);
+}
+
+static inline int pld_snoc_fw_sim_get_irq(struct device *dev, int ce_id)
+{
+	if (!dev)
+		return -ENODEV;
+
+	return icnss_get_irq(dev, ce_id);
+}
+
+static inline int pld_snoc_fw_sim_is_fw_down(struct device *dev)
+{
+	return icnss_is_fw_down();
+}
+
+static inline int pld_snoc_fw_sim_idle_shutdown(struct device *dev)
+{
+	return icnss_idle_shutdown(dev);
+}
+
+static inline int pld_snoc_fw_sim_idle_restart(struct device *dev)
+{
+	return icnss_idle_restart(dev);
+}
+
+#endif
+#endif