qcacld-3.0: Add PLD layer

PLD stands for platform driver. It is a interface between CLD and
CNSS/ICNSS. It hides the CNSS/ICNSS APIs from CLD and provides a set
of common APIs.
Other modules should include pld_common.h if they want to call PLD
APIs.

CRs-Fixed: 979275
Change-Id: I3571fc70f502dc367c65f13b412cd5d37ee41d3c
diff --git a/Kbuild b/Kbuild
index d4da7c5..1031b35 100755
--- a/Kbuild
+++ b/Kbuild
@@ -847,6 +847,23 @@
 WMA_OBJS +=	$(WMA_SRC_DIR)/wma_utils_ut.o
 endif
 
+############## PLD ##########
+PLD_DIR := core/pld
+PLD_INC_DIR := $(PLD_DIR)/inc
+PLD_SRC_DIR := $(PLD_DIR)/src
+
+PLD_INC :=	-I$(WLAN_ROOT)/$(PLD_INC_DIR) \
+		-I$(WLAN_ROOT)/$(PLD_SRC_DIR)
+
+PLD_OBJS :=	$(PLD_SRC_DIR)/pld_common.o
+
+ifeq ($(CONFIG_PCI), y)
+PLD_OBJS +=	$(PLD_SRC_DIR)/pld_pcie.o
+endif
+ifeq ($(CONFIG_ICNSS),y)
+PLD_OBJS +=	$(PLD_SRC_DIR)/pld_snoc.o
+endif
+
 TARGET_INC :=	-I$(WLAN_ROOT)/target/inc
 
 LINUX_INC :=	-Iinclude/linux
@@ -884,6 +901,8 @@
 		$(PTT_INC) \
 		$(WLAN_LOGGING_INC)
 
+INCS +=		$(PLD_INC)
+
 ifeq ($(CONFIG_REMOVE_PKT_LOG), 0)
 INCS +=		$(PKTLOG_INC)
 endif
@@ -917,6 +936,8 @@
 OBJS +=		$(NLINK_OBJS)
 OBJS +=		$(PTT_OBJS)
 
+OBJS +=		$(PLD_OBJS)
+
 ifeq ($(CONFIG_REMOVE_PKT_LOG), 0)
 OBJS +=		$(PKTLOG_OBJS)
 endif
diff --git a/core/pld/inc/pld_common.h b/core/pld/inc/pld_common.h
new file mode 100644
index 0000000..9345eaf
--- /dev/null
+++ b/core/pld/inc/pld_common.h
@@ -0,0 +1,346 @@
+/*
+ * Copyright (c) 2016 The Linux Foundation. All rights reserved.
+ *
+ * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
+ *
+ *
+ * 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.
+ */
+
+/*
+ * This file was originally distributed by Qualcomm Atheros, Inc.
+ * under proprietary terms before Copyright ownership was assigned
+ * to the Linux Foundation.
+ */
+
+#ifndef __PLD_COMMON_H__
+#define __PLD_COMMON_H__
+
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/pm.h>
+
+/**
+ * enum pld_bus_type - bus type
+ * @PLD_BUS_TYPE_NONE: invalid bus type, only return in error cases
+ * @PLD_BUS_TYPE_PCIE: PCIE bus
+ * @PLD_BUS_TYPE_SNOC: SNOC bus
+ */
+enum pld_bus_type {
+	PLD_BUS_TYPE_NONE = -1,
+	PLD_BUS_TYPE_PCIE = 0,
+	PLD_BUS_TYPE_SNOC
+};
+
+#define PLD_MAX_FIRMWARE_SIZE (1 * 1024 * 1024)
+
+/**
+ * enum pld_bus_width_type - bus bandwith
+ * @PLD_BUS_WIDTH_NONE: don't vote for bus bandwidth
+ * @PLD_BUS_WIDTH_LOW: vote for low bus bandwidth
+ * @PLD_BUS_WIDTH_MEDIUM: vote for medium bus bandwidth
+ * @PLD_BUS_WIDTH_HIGH: vote for high bus bandwidth
+ */
+enum pld_bus_width_type {
+	PLD_BUS_WIDTH_NONE,
+	PLD_BUS_WIDTH_LOW,
+	PLD_BUS_WIDTH_MEDIUM,
+	PLD_BUS_WIDTH_HIGH
+};
+
+#define PLD_MAX_FILE_NAME 20
+
+/**
+ * struct pld_fw_file - WLAN FW file names
+ * @image_file: WLAN FW image file
+ * @board_data: WLAN FW board data file
+ * @otp_data: WLAN FW OTP file
+ * @utf_file: WLAN FW UTF file
+ * @utf_board_data: WLAN FW UTF board data file
+ * @epping_file: WLAN FW EPPING mode file
+ * @evicted_data: WLAN FW evicted file
+ *
+ * pld_fw_files is used to store WLAN FW file names
+ */
+struct pld_fw_files {
+	char image_file[PLD_MAX_FILE_NAME];
+	char board_data[PLD_MAX_FILE_NAME];
+	char otp_data[PLD_MAX_FILE_NAME];
+	char utf_file[PLD_MAX_FILE_NAME];
+	char utf_board_data[PLD_MAX_FILE_NAME];
+	char epping_file[PLD_MAX_FILE_NAME];
+	char evicted_data[PLD_MAX_FILE_NAME];
+};
+
+/**
+ * struct pld_image_desc_info - FW image description
+ * @fw_addr: FW image address
+ * @fw_size: FW image size
+ * @bdata_addr: FW board data address
+ * @bdata_size: FW board data size
+ *
+ * pld_image_desc_info is used to store FW image description
+ * information.
+ */
+struct pld_image_desc_info {
+	dma_addr_t fw_addr;
+	u32 fw_size;
+	dma_addr_t bdata_addr;
+	u32 bdata_size;
+};
+
+#define PLD_CODESWAP_MAX_CODESEGS 16
+
+/**
+ * struct pld_codeswap_codeseg_info - code swap segment information
+ * @codeseg_total_bytes: total bytes of segments
+ * @num_codesegs: number of code segments
+ * @codeseg_size: code segment size
+ * @codeseg_size_log2: log2 of code segment size
+ * @codeseg_busaddr: array of addresses of each code segment
+ *
+ * pld_codeswap_codeseg_info is used to store code swap segment
+ * information.
+ */
+struct pld_codeswap_codeseg_info {
+	u32   codeseg_total_bytes;
+	u32   num_codesegs;
+	u32   codeseg_size;
+	u32   codeseg_size_log2;
+	void *codeseg_busaddr[PLD_CODESWAP_MAX_CODESEGS];
+};
+
+/**
+ * enum pld_platform_cap_flag - platform capability flag
+ * @PLD_HAS_EXTERNAL_SWREG: has external regulator
+ * @PLD_HAS_UART_ACCESS: has UART access
+ */
+enum pld_platform_cap_flag {
+	PLD_HAS_EXTERNAL_SWREG = 0x01,
+	PLD_HAS_UART_ACCESS = 0x02,
+};
+
+/**
+ * struct pld_platform_cap - platform capabilities
+ * @cap_flag: capabilities flag
+ *
+ * pld_platform_cap provides platform capabilities which are
+ * extracted from DTS.
+ */
+struct pld_platform_cap {
+	u32 cap_flag;
+};
+
+/**
+ * enum pld_driver_status - WLAN driver status
+ * @PLD_UNINITIALIZED: driver is uninitialized
+ * @PLD_INITIALIZED: driver is initialized
+ * @PLD_LOAD_UNLOADL: driver is in load-unload status
+ */
+enum pld_driver_status {
+	PLD_UNINITIALIZED,
+	PLD_INITIALIZED,
+	PLD_LOAD_UNLOAD
+};
+
+/**
+ * struct pld_ce_tgt_pipe_cfg - copy engine target pipe configuration
+ * @pipe_num: pipe number
+ * @pipe_dir: pipe direction
+ * @nentries: number of entries
+ * @nbytes_max: max number of bytes
+ * @flags: flags
+ * @reserved: reserved
+ *
+ * pld_ce_tgt_pipe_cfg is used to store copy engine target pipe
+ * configuration.
+ */
+struct pld_ce_tgt_pipe_cfg {
+	u32 pipe_num;
+	u32 pipe_dir;
+	u32 nentries;
+	u32 nbytes_max;
+	u32 flags;
+	u32 reserved;
+};
+
+/**
+ * struct pld_ce_svc_pipe_cfg - copy engine service pipe configuration
+ * @service_id: service ID
+ * @pipe_dir: pipe direction
+ * @pipe_num: pipe number
+ *
+ * pld_ce_svc_pipe_cfg is used to store copy engine service pipe
+ * configuration.
+ */
+struct pld_ce_svc_pipe_cfg {
+	u32 service_id;
+	u32 pipe_dir;
+	u32 pipe_num;
+};
+
+/**
+ * struct pld_shadow_reg_cfg - shadow register configuration
+ * @ce_id: copy engine ID
+ * @reg_offset: register offset
+ *
+ * pld_shadow_reg_cfg is used to store shadow register configuration.
+ */
+struct pld_shadow_reg_cfg {
+	u16 ce_id;
+	u16 reg_offset;
+};
+
+/**
+ * struct pld_wlan_enable_cfg - WLAN FW configuration
+ * @num_ce_tgt_cfg: number of CE target configuration
+ * @ce_tgt_cfg: CE target configuration
+ * @num_ce_svc_pipe_cfg: number of CE service configuration
+ * @ce_svc_cfg: CE service configuration
+ * @num_shadow_reg_cfg: number of shadow register configuration
+ * @shadow_reg_cfg: shadow register configuration
+ *
+ * pld_wlan_enable_cfg stores WLAN FW configurations. It will be
+ * passed to WLAN FW when WLAN host driver calls wlan_enable.
+ */
+struct pld_wlan_enable_cfg {
+	u32 num_ce_tgt_cfg;
+	struct pld_ce_tgt_pipe_cfg *ce_tgt_cfg;
+	u32 num_ce_svc_pipe_cfg;
+	struct pld_ce_svc_pipe_cfg *ce_svc_cfg;
+	u32 num_shadow_reg_cfg;
+	struct pld_shadow_reg_cfg *shadow_reg_cfg;
+};
+
+/**
+ * enum pld_driver_mode - WLAN host driver mode
+ * @PLD_MISSION: mission mode
+ * @PLD_FTM: FTM mode
+ * @PLD_EPPING: EPPING mode
+ * @PLD_WALTEST: WAL test mode, FW standalone test mode
+ * @PLD_OFF: OFF mode
+ */
+enum pld_driver_mode {
+	PLD_MISSION,
+	PLD_FTM,
+	PLD_EPPING,
+	PLD_WALTEST,
+	PLD_OFF
+};
+
+/**
+ * struct pld_soc_info - SOC information
+ * @v_addr: virtual address of preallocated memory
+ * @p_addr: physical address of preallcoated memory
+ * @version: version number
+ *
+ * pld_soc_info is used to store WLAN SOC information.
+ */
+struct pld_soc_info {
+	void __iomem *v_addr;
+	phys_addr_t p_addr;
+	u32 version;
+};
+
+/**
+ * struct pld_driver_ops - driver callback functions
+ * @probe: required operation, will be called when device is detected
+ * @remove: required operation, will be called when device is removed
+ * @shutdown: optional operation, will be called during SSR
+ * @reinit: optional operation, will be called during SSR
+ * @crash_shutdown: optional operation, will be called when a crash is
+ *                  detected
+ * @suspend: required operation, will be called for power management
+ *           is enabled
+ * @resume: required operation, will be called for power management
+ *          is enabled
+ * @modem_status: optional operation, will be called when platform driver
+ *                sending modem power status to WLAN FW
+ */
+struct pld_driver_ops {
+	int (*probe)(struct device *dev,
+		     enum pld_bus_type bus_type,
+		     void *bdev, void *id);
+	void (*remove)(struct device *dev,
+		       enum pld_bus_type bus_type);
+	void (*shutdown)(struct device *dev,
+			 enum pld_bus_type bus_type);
+	int (*reinit)(struct device *dev,
+		      enum pld_bus_type bus_type,
+		      void *bdev, void *id);
+	void (*crash_shutdown)(struct device *dev,
+			       enum pld_bus_type bus_type);
+	int (*suspend)(struct device *dev,
+		       enum pld_bus_type bus_type,
+		       pm_message_t state);
+	int (*resume)(struct device *dev,
+		      enum pld_bus_type bus_type);
+	void (*modem_status)(struct device *dev,
+			     enum pld_bus_type bus_type,
+			     int state);
+};
+
+int pld_init(void);
+void pld_deinit(void);
+
+int pld_register_driver(struct pld_driver_ops *ops);
+void pld_unregister_driver(void);
+
+int pld_wlan_enable(struct device *dev, struct pld_wlan_enable_cfg *config,
+		    enum pld_driver_mode mode, const char *host_version);
+int pld_wlan_disable(struct device *dev, enum pld_driver_mode mode);
+int pld_set_fw_debug_mode(struct device *dev, bool enablefwlog);
+int pld_get_fw_files_for_target(struct device *dev,
+				struct pld_fw_files *pfw_files,
+				u32 target_type, u32 target_version);
+int pld_get_fw_image(struct device *dev,
+		     struct pld_image_desc_info *image_desc_info);
+void pld_is_pci_link_down(struct device *dev);
+int pld_pcie_shadow_control(struct device *dev, bool enable);
+int pld_get_codeswap_struct(struct device *dev,
+			    struct pld_codeswap_codeseg_info *swap_seg);
+int pld_set_wlan_unsafe_channel(struct device *dev, u16 *unsafe_ch_list,
+				u16 ch_count);
+int pld_get_wlan_unsafe_channel(struct device *dev, u16 *unsafe_ch_list,
+				u16 *ch_count, u16 buf_len);
+int pld_wlan_set_dfs_nol(struct device *dev, void *info, u16 info_len);
+int pld_wlan_get_dfs_nol(struct device *dev, void *info, u16 info_len);
+int pld_wlan_pm_control(struct device *dev, bool vote);
+void *pld_get_virt_ramdump_mem(struct device *dev, unsigned long *size);
+void pld_device_crashed(struct device *dev);
+void pld_device_self_recovery(struct device *dev);
+void pld_intr_notify_q6(struct device *dev);
+void pld_request_pm_qos(struct device *dev, u32 qos_val);
+void pld_remove_pm_qos(struct device *dev);
+int pld_request_bus_bandwidth(struct device *dev, int bandwidth);
+int pld_get_platform_cap(struct device *dev, struct pld_platform_cap *cap);
+void pld_set_driver_status(struct device *dev, enum pld_driver_status status);
+int pld_get_bmi_setup(struct device *dev);
+int pld_get_sha_hash(struct device *dev, const u8 *data,
+		     u32 data_len, u8 *hash_idx, u8 *out);
+void *pld_get_fw_ptr(struct device *dev);
+int pld_auto_suspend(struct device *dev);
+int pld_auto_resume(struct device *dev);
+
+int pld_ce_request_irq(struct device *dev, unsigned int ce_id,
+		       irqreturn_t (*handler)(int, void *),
+		       unsigned long flags, const char *name, void *ctx);
+int pld_ce_free_irq(struct device *dev, unsigned int ce_id, void *ctx);
+void pld_enable_irq(struct device *dev, unsigned int ce_id);
+void pld_disable_irq(struct device *dev, unsigned int ce_id);
+int pld_get_soc_info(struct device *dev, struct pld_soc_info *info);
+int pld_get_ce_id(struct device *dev, int irq);
+
+#endif
diff --git a/core/pld/src/pld_common.c b/core/pld/src/pld_common.c
new file mode 100644
index 0000000..902c210
--- /dev/null
+++ b/core/pld/src/pld_common.c
@@ -0,0 +1,1117 @@
+/*
+ * Copyright (c) 2016 The Linux Foundation. All rights reserved.
+ *
+ * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
+ *
+ *
+ * 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.
+ */
+
+/*
+ * This file was originally distributed by Qualcomm Atheros, Inc.
+ * under proprietary terms before Copyright ownership was assigned
+ * to the Linux Foundation.
+ */
+
+#define pr_fmt(fmt) "wlan_pld:%s:%d:: " fmt, __func__, __LINE__
+
+#include <linux/printk.h>
+#include <linux/err.h>
+#include <linux/string.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/pm.h>
+
+#ifdef CONFIG_CNSS
+#include <net/cnss.h>
+#endif
+#ifdef CONFIG_ICNSS
+#include <soc/qcom/icnss.h>
+#endif
+
+#include "pld_pcie.h"
+#include "pld_snoc.h"
+#include "pld_common.h"
+#include "pld_internal.h"
+
+#define PLD_PCIE_REGISTERED BIT(0)
+#define PLD_SNOC_REGISTERED BIT(1)
+
+static struct pld_context *pld_ctx;
+
+/**
+ * pld_init() - Initialize PLD module
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_init(void)
+{
+	struct pld_context *pld_context;
+
+	pld_context = kzalloc(sizeof(*pld_context), GFP_KERNEL);
+	if (!pld_context)
+		return -ENOMEM;
+
+	spin_lock_init(&pld_context->pld_lock);
+
+	INIT_LIST_HEAD(&pld_context->dev_list);
+
+	pld_ctx = pld_context;
+
+	return 0;
+}
+
+/**
+ * pld_deinit() - Uninitialize PLD module
+ *
+ * Return: void
+ */
+void pld_deinit(void)
+{
+	struct dev_node *dev_node;
+	struct pld_context *pld_context;
+	unsigned long flags;
+
+	pld_context = pld_ctx;
+	if (!pld_context) {
+		pld_ctx = NULL;
+		return;
+	}
+
+	spin_lock_irqsave(&pld_context->pld_lock, flags);
+	while (!list_empty(&pld_context->dev_list)) {
+		dev_node = list_first_entry(&pld_context->dev_list,
+					    struct dev_node, list);
+		list_del(&dev_node->list);
+		kfree(dev_node);
+	}
+	spin_unlock_irqrestore(&pld_context->pld_lock, flags);
+
+	kfree(pld_context);
+
+	pld_ctx = NULL;
+}
+
+/**
+ * pld_get_global_context() - Get global context of PLD
+ *
+ * Return: PLD global context
+ */
+struct pld_context *pld_get_global_context(void)
+{
+	return pld_ctx;
+}
+
+/**
+ * pld_get_bus_type() - Bus type of the device
+ * @dev: device
+ *
+ * Return: PLD bus type
+ */
+enum pld_bus_type pld_get_bus_type(struct device *dev)
+{
+	struct pld_context *pld_context;
+	struct dev_node *dev_node;
+	unsigned long flags;
+
+	pld_context = pld_get_global_context();
+
+	if (dev == NULL || pld_context == NULL) {
+		pr_err("Invalid info: dev %p, context %p\n",
+		       dev, pld_context);
+		return PLD_BUS_TYPE_NONE;
+	}
+
+	spin_lock_irqsave(&pld_context->pld_lock, flags);
+	list_for_each_entry(dev_node, &pld_context->dev_list, list) {
+		if (dev_node->dev == dev) {
+			spin_unlock_irqrestore(&pld_context->pld_lock, flags);
+			return dev_node->bus_type;
+		}
+	}
+	spin_unlock_irqrestore(&pld_context->pld_lock, flags);
+
+	return PLD_BUS_TYPE_NONE;
+}
+
+/**
+ * pld_register_driver() - Register driver to kernel
+ * @ops: Callback functions that will be registered to kernel
+ *
+ * This function should be called when other modules want to
+ * register platform driver callback functions to kernel. The
+ * probe() is expected to be called after registration if the
+ * device is online.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_register_driver(struct pld_driver_ops *ops)
+{
+	int ret = 0;
+	struct pld_context *pld_context;
+
+	pld_context = pld_get_global_context();
+
+	if (pld_context == NULL) {
+		pr_err("global context is NULL\n");
+		ret = -ENODEV;
+		goto out;
+	}
+
+	if (pld_context->ops) {
+		pr_err("driver already registered\n");
+		ret = -EEXIST;
+		goto out;
+	}
+
+	if (!ops || !ops->probe || !ops->remove ||
+	    !ops->suspend || !ops->resume) {
+		pr_err("Required callback functions are missing\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	pld_context->ops = ops;
+
+	if (0 == pld_pcie_register_driver())
+		pld_context->pld_driver_state |= PLD_PCIE_REGISTERED;
+	if (0 == pld_snoc_register_driver())
+		pld_context->pld_driver_state |= PLD_SNOC_REGISTERED;
+
+	if (0 == pld_context->pld_driver_state) {
+		pr_err("All driver falied to register\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+out:
+	return ret;
+}
+
+/**
+ * pld_unregister_driver() - Unregister driver to kernel
+ *
+ * This function should be called when other modules want to
+ * unregister callback functions from kernel. The remove() is
+ * expected to be called after registration.
+ *
+ * Return: void
+ */
+void pld_unregister_driver(void)
+{
+	struct pld_context *pld_context;
+
+	pld_context = pld_get_global_context();
+
+	if (pld_context == NULL) {
+		pr_err("global context is NULL\n");
+		return;
+	}
+
+	if (pld_context->ops == NULL) {
+		pr_err("driver not registered\n");
+		return;
+	}
+
+	pld_pcie_unregister_driver();
+	pld_snoc_unregister_driver();
+
+	pld_context->pld_driver_state = 0;
+
+	pld_context->ops = NULL;
+}
+
+/**
+ * pld_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_wlan_enable(struct device *dev, struct pld_wlan_enable_cfg *config,
+		    enum pld_driver_mode mode, const char *host_version)
+{
+	int ret = 0;
+
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		ret = pld_pcie_wlan_enable(config, mode, host_version);
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		ret = pld_snoc_wlan_enable(config, mode, host_version);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pld_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_wlan_disable(struct device *dev, enum pld_driver_mode mode)
+{
+	int ret = 0;
+
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		ret = pld_pcie_wlan_disable(mode);
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		ret = pld_snoc_wlan_disable(mode);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pld_set_fw_debug_mode() - Set FW debug mode
+ * @dev: device
+ * @enablefwlog: 0 for QXDM, 1 for WMI
+ *
+ * Switch Fw debug mode between DIAG logging and WMI logging.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_set_fw_debug_mode(struct device *dev, bool enablefwlog)
+{
+	int ret = 0;
+
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		ret = pld_pcie_set_fw_debug_mode(enablefwlog);
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pld_get_fw_files_for_target() - Get FW file names
+ * @dev: device
+ * @pfw_files: buffer for FW file names
+ * @target_type: target type
+ * @target_version: target version
+ *
+ * Return target specific FW file names to the buffer.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_get_fw_files_for_target(struct device *dev,
+				struct pld_fw_files *pfw_files,
+				u32 target_type, u32 target_version)
+{
+	int ret = 0;
+
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		ret = pld_pcie_get_fw_files_for_target(pfw_files,
+				       target_type, target_version);
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pld_get_fw_image() - Get FW image descriptor
+ * @dev: device
+ * @image_desc_info: buffer for image descriptor
+ *
+ * Return FW image descriptor to the buffer.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_get_fw_image(struct device *dev,
+		     struct pld_image_desc_info *image_desc_info)
+{
+	int ret = 0;
+
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		ret = pld_pcie_get_fw_image(image_desc_info);
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pld_is_pci_link_down() - Notification for pci link down event
+ * @dev: device
+ *
+ * Notify platform that pci link is down.
+ *
+ * Return: void
+ */
+void pld_is_pci_link_down(struct device *dev)
+{
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		cnss_wlan_pci_link_down();
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		break;
+	default:
+		pr_err("Invalid device type\n");
+		break;
+	}
+}
+
+/**
+ * pld_pcie_shadow_control() - Control pci shadow registers
+ * @dev: device
+ * @enable: 0 for disable, 1 for enable
+ *
+ * This function is for suspend/resume. It can control if we
+ * use pci shadow registers (for saving config space) or not.
+ * During suspend we disable it to avoid config space corruption.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_pcie_shadow_control(struct device *dev, bool enable)
+{
+	int ret = 0;
+
+	/* cnss_shadow_control is not supported on BF64.0.3 kernel yet
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		ret = cnss_shadow_control(enable);
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+	*/
+	return ret;
+}
+
+/**
+ * pld_get_codeswap_struct() - Get codeswap structure
+ * @dev: device
+ * @swap_seg: buffer to codeswap information
+ *
+ * Return codeswap structure information to the buffer.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_get_codeswap_struct(struct device *dev,
+			    struct pld_codeswap_codeseg_info *swap_seg)
+{
+	int ret = 0;
+
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		ret = pld_pcie_get_codeswap_struct(swap_seg);
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pld_set_wlan_unsafe_channel() - Set unsafe channel
+ * @dev: device
+ * @unsafe_ch_list: unsafe channel list
+ * @ch_count: number of channel
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_set_wlan_unsafe_channel(struct device *dev,
+				u16 *unsafe_ch_list, u16 ch_count)
+{
+	int ret = 0;
+
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		ret = cnss_set_wlan_unsafe_channel(unsafe_ch_list,
+						   ch_count);
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pld_get_wlan_unsafe_channel() - Get unsafe channel
+ * @dev: device
+ * @unsafe_ch_list: buffer to unsafe channel list
+ * @ch_count: number of channel
+ * @buf_len: buffer length
+ *
+ * Return WLAN unsafe channel to the buffer.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_get_wlan_unsafe_channel(struct device *dev, u16 *unsafe_ch_list,
+				u16 *ch_count, u16 buf_len)
+{
+	int ret = 0;
+
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		ret = cnss_get_wlan_unsafe_channel(unsafe_ch_list,
+						   ch_count, buf_len);
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pld_wlan_set_dfs_nol() - Set DFS info
+ * @dev: device
+ * @info: DFS info
+ * @info_len: info length
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_wlan_set_dfs_nol(struct device *dev, void *info, u16 info_len)
+{
+	int ret = 0;
+
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		ret = cnss_wlan_set_dfs_nol(info, info_len);
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pld_wlan_get_dfs_nol() - Get DFS info
+ * @dev: device
+ * @info: buffer to DFS info
+ * @info_len: info length
+ *
+ * Return DFS info to the buffer.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_wlan_get_dfs_nol(struct device *dev, void *info, u16 info_len)
+{
+	int ret = 0;
+
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		ret = cnss_wlan_get_dfs_nol(info, info_len);
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pld_wlan_pm_control() - WLAN PM control on PCIE
+ * @dev: device
+ * @vote: 0 for enable PCIE PC, 1 for disable PCIE PC
+ *
+ * This is for PCIE power collaps control during suspend/resume.
+ * When PCIE power collaps is disabled, WLAN FW can access memory
+ * through PCIE when system is suspended.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_wlan_pm_control(struct device *dev, bool vote)
+{
+	int ret = 0;
+
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		ret = cnss_wlan_pm_control(vote);
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pld_get_virt_ramdump_mem() - Get virtual ramdump memory
+ * @dev: device
+ * @size: buffer to virtual memory size
+ *
+ * Return: virtual ramdump memory address
+ */
+void *pld_get_virt_ramdump_mem(struct device *dev, unsigned long *size)
+{
+	void *mem = NULL;
+
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		mem = cnss_get_virt_ramdump_mem(size);
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		break;
+	default:
+		pr_err("Invalid device type\n");
+		break;
+	}
+
+	return mem;
+}
+
+/**
+ * pld_device_crashed() - Notification for device crash event
+ * @dev: device
+ *
+ * Notify subsystem a device crashed event. A subsystem restart
+ * is expected to happen after calling this function.
+ *
+ * Return: void
+ */
+void pld_device_crashed(struct device *dev)
+{
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		cnss_device_crashed();
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		break;
+	default:
+		pr_err("Invalid device type\n");
+		break;
+	}
+}
+
+/**
+ * pld_device_self_recovery() - Device self recovery
+ * @dev: device
+ *
+ * Return: void
+ */
+void pld_device_self_recovery(struct device *dev)
+{
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		cnss_device_self_recovery();
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		break;
+	default:
+		pr_err("Invalid device type\n");
+		break;
+	}
+}
+
+/**
+ * pld_intr_notify_q6() - Notify Q6 FW interrupts
+ * @dev: device
+ *
+ * Notify Q6 that a FW interrupt is triggered.
+ *
+ * Return: void
+ */
+void pld_intr_notify_q6(struct device *dev)
+{
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		cnss_intr_notify_q6();
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		break;
+	default:
+		pr_err("Invalid device type\n");
+		break;
+	}
+}
+
+/**
+ * pld_request_pm_qos() - Request system PM
+ * @dev: device
+ * @qos_val: request value
+ *
+ * It votes for the value of aggregate QoS expectations.
+ *
+ * Return: void
+ */
+void pld_request_pm_qos(struct device *dev, u32 qos_val)
+{
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		cnss_request_pm_qos(qos_val);
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		break;
+	default:
+		pr_err("Invalid device type\n");
+		break;
+	}
+}
+
+/**
+ * pld_remove_pm_qos() - Remove system PM
+ * @dev: device
+ *
+ * Remove the vote request for Qos expectations.
+ *
+ * Return: void
+ */
+void pld_remove_pm_qos(struct device *dev)
+{
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		cnss_remove_pm_qos();
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		break;
+	default:
+		pr_err("Invalid device type\n");
+		break;
+	}
+}
+
+/**
+ * pld_request_bus_bandwidth() - Request bus bandwidth
+ * @dev: device
+ * @bandwidth: bus bandwidth
+ *
+ * Votes for HIGH/MEDIUM/LOW bus bandwidth.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_request_bus_bandwidth(struct device *dev, int bandwidth)
+{
+	int ret = 0;
+
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		ret = cnss_request_bus_bandwidth(bandwidth);
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pld_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_get_platform_cap(struct device *dev, struct pld_platform_cap *cap)
+{
+	int ret = 0;
+
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		ret = pld_pcie_get_platform_cap(cap);
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pld_set_driver_status() - Set driver status
+ * @dev: device
+ * @status: driver status
+ *
+ * Return: void
+ */
+void pld_set_driver_status(struct device *dev, enum pld_driver_status status)
+{
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		pld_pcie_set_driver_status(status);
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		break;
+	default:
+		pr_err("Invalid device type\n");
+		break;
+	}
+}
+
+/**
+ * pld_get_bmi_setup() - Get BMI setup
+ * @dev: device
+ *
+ * BMI read/write test should be run if BMI test is enabled.
+ *
+ * Return: BMI test setup
+ */
+int pld_get_bmi_setup(struct device *dev)
+{
+	int ret = 0;
+
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		ret = cnss_get_bmi_setup();
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pld_get_sha_hash() - Get sha hash number
+ * @dev: device
+ * @data: input data
+ * @data_len: data length
+ * @hash_idx: hash index
+ * @out:  output buffer
+ *
+ * Return computed hash to the out buffer.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_get_sha_hash(struct device *dev, const u8 *data,
+		     u32 data_len, u8 *hash_idx, u8 *out)
+{
+	int ret = 0;
+
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		ret = cnss_get_sha_hash(data, data_len,
+					    hash_idx, out);
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pld_get_fw_ptr() - Get secure FW memory address
+ * @dev: device
+ *
+ * Return: secure memory address
+ */
+void *pld_get_fw_ptr(struct device *dev)
+{
+	void *ptr = NULL;
+
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		ptr = cnss_get_fw_ptr();
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		break;
+	default:
+		pr_err("Invalid device type\n");
+		break;
+	}
+
+	return ptr;
+}
+
+/**
+ * pld_auto_suspend() - Auto suspend
+ * @dev: device
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_auto_suspend(struct device *dev)
+{
+	int ret = 0;
+
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		ret = cnss_auto_suspend();
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pld_auto_resume() - Auto resume
+ * @dev: device
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_auto_resume(struct device *dev)
+{
+	int ret = 0;
+
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_PCIE:
+		ret = cnss_auto_resume();
+		break;
+	case PLD_BUS_TYPE_SNOC:
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pld_ce_request_irq() - Register IRQ for CE
+ * @dev: device
+ * @ce_id: CE 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_ce_request_irq(struct device *dev, unsigned int ce_id,
+		       irqreturn_t (*handler)(int, void *),
+		       unsigned long flags, const char *name, void *ctx)
+{
+	int ret = 0;
+
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_SNOC:
+		ret = icnss_ce_request_irq(ce_id, handler, flags, name, ctx);
+		break;
+	case PLD_BUS_TYPE_PCIE:
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pld_ce_free_irq() - Free IRQ for CE
+ * @dev: device
+ * @ce_id: CE number
+ * @ctx: IRQ context
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_ce_free_irq(struct device *dev, unsigned int ce_id, void *ctx)
+{
+	int ret = 0;
+
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_SNOC:
+		ret = icnss_ce_free_irq(ce_id, ctx);
+		break;
+	case PLD_BUS_TYPE_PCIE:
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pld_enable_irq() - Enable IRQ for CE
+ * @dev: device
+ * @ce_id: CE number
+ *
+ * Return: void
+ */
+void pld_enable_irq(struct device *dev, unsigned int ce_id)
+{
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_SNOC:
+		icnss_enable_irq(ce_id);
+		break;
+	case PLD_BUS_TYPE_PCIE:
+		break;
+	default:
+		pr_err("Invalid device type\n");
+		break;
+	}
+}
+
+/**
+ * pld_disable_irq() - Disable IRQ for CE
+ * @dev: device
+ * @ce_id: CE number
+ *
+ * Return: void
+ */
+void pld_disable_irq(struct device *dev, unsigned int ce_id)
+{
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_SNOC:
+		icnss_disable_irq(ce_id);
+		break;
+	case PLD_BUS_TYPE_PCIE:
+		break;
+	default:
+		pr_err("Invalid device type\n");
+		break;
+	}
+}
+
+/**
+ * pld_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_get_soc_info(struct device *dev, struct pld_soc_info *info)
+{
+	int ret = 0;
+
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_SNOC:
+		ret = pld_snoc_get_soc_info(info);
+		break;
+	case PLD_BUS_TYPE_PCIE:
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
+
+/**
+ * pld_get_ce_id() - Get CE number for the provided IRQ
+ * @dev: device
+ * @irq: IRQ number
+ *
+ * Return: CE number
+ */
+int pld_get_ce_id(struct device *dev, int irq)
+{
+	int ret = 0;
+
+	switch (pld_get_bus_type(dev)) {
+	case PLD_BUS_TYPE_SNOC:
+		ret = icnss_get_ce_id(irq);
+		break;
+	case PLD_BUS_TYPE_PCIE:
+		ret = pld_pcie_get_ce_id(irq);
+		break;
+	default:
+		ret = -EINVAL;
+		break;
+	}
+
+	return ret;
+}
diff --git a/core/pld/src/pld_internal.h b/core/pld/src/pld_internal.h
new file mode 100644
index 0000000..3619848
--- /dev/null
+++ b/core/pld/src/pld_internal.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2016 The Linux Foundation. All rights reserved.
+ *
+ * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
+ *
+ *
+ * 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.
+ */
+
+/*
+ * This file was originally distributed by Qualcomm Atheros, Inc.
+ * under proprietary terms before Copyright ownership was assigned
+ * to the Linux Foundation.
+ */
+
+#ifndef __PLD_COMMON_I_H__
+#define __PLD_COMMON_I_H__
+
+struct dev_node {
+	struct device *dev;
+	struct list_head list;
+	enum pld_bus_type bus_type;
+};
+
+struct pld_context {
+	struct pld_driver_ops *ops;
+	spinlock_t pld_lock;
+	struct list_head dev_list;
+	uint32_t pld_driver_state;
+};
+
+struct pld_context *pld_get_global_context(void);
+
+#endif
diff --git a/core/pld/src/pld_pcie.c b/core/pld/src/pld_pcie.c
new file mode 100644
index 0000000..ca77780
--- /dev/null
+++ b/core/pld/src/pld_pcie.c
@@ -0,0 +1,524 @@
+/*
+ * Copyright (c) 2016 The Linux Foundation. All rights reserved.
+ *
+ * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
+ *
+ *
+ * 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.
+ */
+
+/*
+ * This file was originally distributed by Qualcomm Atheros, Inc.
+ * under proprietary terms before Copyright ownership was assigned
+ * to the Linux Foundation.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/pci.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+
+#ifdef CONFIG_CNSS
+#include <net/cnss.h>
+#endif
+
+#include "pld_common.h"
+#include "pld_internal.h"
+
+#ifdef CONFIG_PCI
+
+#ifdef QCA_WIFI_3_0_ADRASTEA
+#define CE_COUNT_MAX 12
+#else
+#define CE_COUNT_MAX 8
+#endif
+
+/**
+ * pld_pcie_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_probe(struct pci_dev *pdev,
+			  const struct pci_device_id *id)
+{
+	struct pld_context *pld_context;
+	unsigned long flags;
+	struct dev_node *dev_node;
+	int ret = 0;
+
+	pld_context = pld_get_global_context();
+	if (!pld_context) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	dev_node = kzalloc(sizeof(*dev_node), GFP_KERNEL);
+	if (dev_node == NULL) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	dev_node->dev = &pdev->dev;
+	dev_node->bus_type = PLD_BUS_TYPE_PCIE;
+
+	spin_lock_irqsave(&pld_context->pld_lock, flags);
+	list_add_tail(&dev_node->list, &pld_context->dev_list);
+	spin_unlock_irqrestore(&pld_context->pld_lock, flags);
+
+	return pld_context->ops->probe(&pdev->dev,
+		       PLD_BUS_TYPE_PCIE, pdev, (void *)id);
+
+out:
+	return ret;
+}
+
+
+/**
+ * pld_pcie_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_remove(struct pci_dev *pdev)
+{
+	struct pld_context *pld_context;
+	unsigned long flags;
+	struct dev_node *dev_node, *tmp;
+
+	pld_context = pld_get_global_context();
+
+	if (!pld_context)
+		return;
+
+	spin_lock_irqsave(&pld_context->pld_lock, flags);
+	list_for_each_entry_safe(dev_node, tmp, &pld_context->dev_list, list) {
+		if (dev_node->dev == &pdev->dev) {
+			list_del(&dev_node->list);
+			kfree(dev_node);
+		}
+	}
+	spin_unlock_irqrestore(&pld_context->pld_lock, flags);
+
+	pld_context->ops->remove(&pdev->dev, PLD_BUS_TYPE_PCIE);
+}
+
+#ifdef CONFIG_CNSS
+/**
+ * pld_pcie_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_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, pdev, (void *)id);
+
+	return -ENODEV;
+}
+
+/**
+ * pld_pcie_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_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);
+}
+
+/**
+ * pld_pcie_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_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);
+}
+
+/**
+ * pld_pcie_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_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, state);
+}
+#endif
+
+/**
+ * pld_pcie_suspend() - Suspend callback function for power management
+ * @pdev: PCIE device
+ * @state: power state
+ *
+ * This function is to suspend the PCIE device when power management is
+ * enabled.
+ *
+ * Return: void
+ */
+static int pld_pcie_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct pld_context *pld_context;
+
+	pld_context = pld_get_global_context();
+	return pld_context->ops->suspend(&pdev->dev,
+					 PLD_BUS_TYPE_PCIE, state);
+}
+
+/**
+ * pld_pcie_resume() - Resume callback function for power management
+ * @pdev: PCIE device
+ *
+ * This function is to resume the PCIE device when power management is
+ * enabled.
+ *
+ * Return: void
+ */
+static int pld_pcie_resume(struct pci_dev *pdev)
+{
+	struct pld_context *pld_context;
+
+	pld_context = pld_get_global_context();
+	return pld_context->ops->resume(&pdev->dev, PLD_BUS_TYPE_PCIE);
+}
+
+static struct pci_device_id pld_pcie_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 CONFIG_CNSS
+struct cnss_wlan_driver pld_pcie_ops = {
+	.name       = "pld_pcie",
+	.id_table   = pld_pcie_id_table,
+	.probe      = pld_pcie_probe,
+	.remove     = pld_pcie_remove,
+	.reinit     = pld_pcie_reinit,
+	.shutdown   = pld_pcie_shutdown,
+	.crash_shutdown = pld_pcie_crash_shutdown,
+	.modem_status   = pld_pcie_notify_handler,
+#ifdef CONFIG_PM
+	.suspend    = pld_pcie_suspend,
+	.resume     = pld_pcie_resume,
+#endif
+};
+
+/**
+ * pld_pcie_register_driver() - Register PCIE device callback functions
+ *
+ * Return: int
+ */
+int pld_pcie_register_driver(void)
+{
+	return cnss_wlan_register_driver(&pld_pcie_ops);
+}
+
+/**
+ * pld_pcie_unregister_driver() - Unregister PCIE device callback functions
+ *
+ * Return: void
+ */
+void pld_pcie_unregister_driver(void)
+{
+	cnss_wlan_unregister_driver(&pld_pcie_ops);
+}
+#else
+struct pci_driver pld_pcie_ops = {
+	.name       = "pld_pcie",
+	.id_table   = pld_pcie_id_table,
+	.probe      = pld_pcie_probe,
+	.remove     = pld_pcie_remove,
+#ifdef CONFIG_PM
+	.suspend    = pld_pcie_suspend,
+	.resume     = pld_pcie_resume,
+#endif
+};
+
+int pld_pcie_register_driver(void)
+{
+	return pci_register_driver(&pld_pcie_ops);
+}
+
+void pld_pcie_unregister_driver(void)
+{
+	pci_unregister_driver(&pld_pcie_ops);
+}
+#endif
+
+/**
+ * pld_pcie_get_ce_id() - Get CE number for the provided IRQ
+ * @irq: IRQ number
+ *
+ * Return: CE number
+ */
+int pld_pcie_get_ce_id(int irq)
+{
+	int ce_id = irq - 100;
+	if (ce_id < CE_COUNT_MAX && ce_id >= 0)
+		return ce_id;
+
+	return -EINVAL;
+}
+
+#ifdef CONFIG_CNSS
+#ifdef QCA_WIFI_3_0_ADRASTEA
+/**
+ * pld_pcie_wlan_enable() - Enable WLAN
+ * @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_wlan_enable(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;
+
+	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_wlan_enable(&cfg, cnss_mode, host_version);
+}
+
+/**
+ * pld_pcie_wlan_disable() - Disable WLAN
+ * @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_wlan_disable(enum pld_driver_mode mode)
+{
+	return cnss_wlan_disable(CNSS_OFF);
+}
+
+/**
+ * pld_pcie_set_fw_debug_mode() - Set FW debug mode
+ * @mode: 0 for QXDM, 1 for WMI
+ *
+ * Switch Fw debug mode between DIAG logging and WMI logging.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_pcie_set_fw_debug_mode(bool mode)
+{
+	return cnss_set_fw_debug_mode(mode);
+}
+#endif
+
+/**
+ * pld_pcie_get_fw_files_for_target() - Get FW file names
+ * @pfw_files: buffer for FW file names
+ * @target_type: target type
+ * @target_version: target version
+ *
+ * Return target specific FW file names to the buffer.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_pcie_get_fw_files_for_target(struct pld_fw_files *pfw_files,
+				     u32 target_type, u32 target_version)
+{
+	int ret = 0;
+	struct cnss_fw_files cnss_fw_files;
+
+	if (pfw_files == NULL)
+		return -ENODEV;
+
+	ret = cnss_get_fw_files_for_target(&cnss_fw_files,
+					   target_type, target_version);
+	if (0 != ret)
+		return ret;
+
+	memcpy(pfw_files, &cnss_fw_files, sizeof(*pfw_files));
+	return 0;
+}
+
+/**
+ * pld_pcie_get_fw_image() - Get FW image descriptor
+ * @image_desc_info: buffer for image descriptor
+ *
+ * Return FW image descriptor to the buffer.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_pcie_get_fw_image(struct pld_image_desc_info *image_desc_info)
+{
+	int ret = 0;
+	struct image_desc_info cnss_image_desc_info;
+
+	if (image_desc_info == NULL)
+		return -ENODEV;
+
+	ret = cnss_get_fw_image(&cnss_image_desc_info);
+	if (0 != ret)
+		return ret;
+
+	memcpy(image_desc_info, &cnss_image_desc_info,
+	       sizeof(*image_desc_info));
+	return 0;
+}
+
+/**
+ * pld_pcie_get_codeswap_struct() - Get codeswap structure
+ * @swap_seg: buffer to codeswap information
+ *
+ * Return codeswap structure information to the buffer.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_pcie_get_codeswap_struct(struct pld_codeswap_codeseg_info *swap_seg)
+{
+	int ret = 0;
+	struct codeswap_codeseg_info cnss_swap_seg;
+
+	if (swap_seg == NULL)
+		return -ENODEV;
+
+	ret = cnss_get_codeswap_struct(&cnss_swap_seg);
+	if (0 != ret)
+		return ret;
+
+	memcpy(swap_seg, &cnss_swap_seg, sizeof(*swap_seg));
+	return 0;
+}
+
+/**
+ * pld_pcie_get_platform_cap() - Get platform capabilities
+ * @cap: buffer to the capabilities
+ *
+ * Return capabilities to the buffer.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_pcie_get_platform_cap(struct pld_platform_cap *cap)
+{
+	int ret = 0;
+	struct cnss_platform_cap cnss_cap;
+
+	if (cap == NULL)
+		return -ENODEV;
+
+	ret = cnss_get_platform_cap(&cnss_cap);
+	if (0 != ret)
+		return ret;
+
+	memcpy(cap, &cnss_cap, sizeof(*cap));
+	return 0;
+}
+
+/**
+ * pld_pcie_set_driver_status() - Set driver status
+ * @status: driver status
+ *
+ * Return: void
+ */
+void pld_pcie_set_driver_status(enum pld_driver_status status)
+{
+	enum cnss_driver_status cnss_status;
+
+	switch (status) {
+	case PLD_UNINITIALIZED:
+		cnss_status = CNSS_UNINITIALIZED;
+		break;
+	case PLD_INITIALIZED:
+		cnss_status = CNSS_INITIALIZED;
+		break;
+	default:
+		cnss_status = CNSS_LOAD_UNLOAD;
+		break;
+	}
+	cnss_set_driver_status(cnss_status);
+}
+#endif
+
+#endif
diff --git a/core/pld/src/pld_pcie.h b/core/pld/src/pld_pcie.h
new file mode 100644
index 0000000..16d022b
--- /dev/null
+++ b/core/pld/src/pld_pcie.h
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2016 The Linux Foundation. All rights reserved.
+ *
+ * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
+ *
+ *
+ * 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.
+ */
+
+/*
+ * This file was originally distributed by Qualcomm Atheros, Inc.
+ * under proprietary terms before Copyright ownership was assigned
+ * to the Linux Foundation.
+ */
+
+#ifndef __PLD_PCIE_H__
+#define __PLD_PCIE_H__
+
+#include "pld_common.h"
+
+#ifndef CONFIG_PCI
+static inline int pld_pcie_register_driver(void)
+{
+	return 0;
+}
+
+static inline void pld_pcie_unregister_driver(void)
+{
+	return;
+}
+
+static inline int pld_pcie_get_ce_id(int irq)
+{
+	return 0;
+}
+#else
+int pld_pcie_register_driver(void);
+void pld_pcie_unregister_driver(void);
+int pld_pcie_get_ce_id(int irq);
+#endif
+
+#if (!defined(CONFIG_CNSS)) || (!defined(QCA_WIFI_3_0_ADRASTEA))
+static inline int pld_pcie_wlan_enable(struct pld_wlan_enable_cfg *config,
+		    enum pld_driver_mode mode, const char *host_version)
+{
+	return 0;
+}
+static inline int pld_pcie_wlan_disable(enum pld_driver_mode mode)
+{
+	return 0;
+}
+static inline int pld_pcie_set_fw_debug_mode(bool enablefwlog)
+{
+	return 0;
+}
+static inline void cnss_intr_notify_q6(void)
+{
+	return;
+}
+#else
+int pld_pcie_wlan_enable(struct pld_wlan_enable_cfg *config,
+			 enum pld_driver_mode mode, const char *host_version);
+int pld_pcie_wlan_disable(enum pld_driver_mode mode);
+int pld_pcie_set_fw_debug_mode(bool enablefwlog);
+#endif
+
+#if (!defined(CONFIG_CNSS)) || (!defined(CONFIG_CNSS_SECURE_FW))
+static inline int cnss_get_sha_hash(const u8 *data,
+				    u32 data_len, u8 *hash_idx, u8 *out)
+{
+	return 0;
+}
+static inline void *cnss_get_fw_ptr(void)
+{
+	return NULL;
+}
+#endif
+
+#ifndef CONFIG_CNSS
+static inline int
+pld_pcie_get_fw_files_for_target(struct pld_fw_files *pfw_files,
+				 u32 target_type, u32 target_version)
+{
+	return 0;
+}
+static inline int
+pld_pcie_get_fw_image(struct pld_image_desc_info *image_desc_info)
+{
+	return 0;
+}
+static inline void cnss_wlan_pci_link_down(void)
+{
+	return;
+}
+static inline int cnss_pcie_shadow_control(bool enable)
+{
+	return 0;
+}
+static inline int
+pld_pcie_get_codeswap_struct(struct pld_codeswap_codeseg_info *swap_seg)
+{
+	return 0;
+}
+static inline int
+cnss_set_wlan_unsafe_channel(u16 *unsafe_ch_list, u16 ch_count)
+{
+	return 0;
+}
+static inline int cnss_get_wlan_unsafe_channel(u16 *unsafe_ch_list,
+				u16 *ch_count, u16 buf_len)
+{
+	return 0;
+}
+static inline int cnss_wlan_set_dfs_nol(void *info, u16 info_len)
+{
+	return 0;
+}
+static inline int cnss_wlan_get_dfs_nol(void *info, u16 info_len)
+{
+	return 0;
+}
+static inline int cnss_wlan_pm_control(bool vote)
+{
+	return 0;
+}
+static inline void *cnss_get_virt_ramdump_mem(unsigned long *size)
+{
+	return NULL;
+}
+static inline void cnss_device_crashed(void)
+{
+	return;
+}
+static inline void cnss_device_self_recovery(void)
+{
+	return;
+}
+static inline void cnss_request_pm_qos(u32 qos_val)
+{
+	return;
+}
+static inline void cnss_remove_pm_qos(void)
+{
+	return;
+}
+static inline int cnss_request_bus_bandwidth(int bandwidth)
+{
+	return 0;
+}
+static inline int pld_pcie_get_platform_cap(struct pld_platform_cap *cap)
+{
+	return 0;
+}
+static inline void pld_pcie_set_driver_status(enum pld_driver_status status)
+{
+	return;
+}
+static inline int cnss_get_bmi_setup(void)
+{
+	return 0;
+}
+static inline int cnss_auto_suspend(void)
+{
+	return 0;
+}
+static inline int cnss_auto_resume(void)
+{
+	return 0;
+}
+#else
+int pld_pcie_get_fw_files_for_target(struct pld_fw_files *pfw_files,
+				     u32 target_type, u32 target_version);
+int pld_pcie_get_fw_image(struct pld_image_desc_info *image_desc_info);
+int pld_pcie_get_codeswap_struct(struct pld_codeswap_codeseg_info *swap_seg);
+int pld_pcie_get_platform_cap(struct pld_platform_cap *cap);
+void pld_pcie_set_driver_status(enum pld_driver_status status);
+#endif
+
+#endif
diff --git a/core/pld/src/pld_snoc.c b/core/pld/src/pld_snoc.c
new file mode 100644
index 0000000..40cee70
--- /dev/null
+++ b/core/pld/src/pld_snoc.c
@@ -0,0 +1,317 @@
+/*
+ * Copyright (c) 2016 The Linux Foundation. All rights reserved.
+ *
+ * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
+ *
+ *
+ * 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.
+ */
+
+/*
+ * This file was originally distributed by Qualcomm Atheros, Inc.
+ * under proprietary terms before Copyright ownership was assigned
+ * to the Linux Foundation.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+
+#ifdef CONFIG_ICNSS
+#include <soc/qcom/icnss.h>
+#endif
+
+#include "pld_common.h"
+#include "pld_internal.h"
+
+#ifdef CONFIG_ICNSS
+/**
+ * pld_snoc_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_probe(struct device *dev)
+{
+	struct pld_context *pld_context;
+	unsigned long flags;
+	struct dev_node *dev_node;
+	int ret = 0;
+
+	pld_context = pld_get_global_context();
+	if (!pld_context) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	dev_node = kzalloc(sizeof(*dev_node), GFP_KERNEL);
+	if (dev_node == NULL) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	dev_node->dev = dev;
+	dev_node->bus_type = PLD_BUS_TYPE_SNOC;
+
+	spin_lock_irqsave(&pld_context->pld_lock, flags);
+	list_add_tail(&dev_node->list, &pld_context->dev_list);
+	spin_unlock_irqrestore(&pld_context->pld_lock, flags);
+
+	return pld_context->ops->probe(dev, PLD_BUS_TYPE_SNOC,
+				       NULL, NULL);
+
+out:
+	return ret;
+}
+
+/**
+ * pld_snoc_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_remove(struct device *dev)
+{
+	struct pld_context *pld_context;
+	unsigned long flags;
+	struct dev_node *dev_node, *tmp;
+
+	pld_context = pld_get_global_context();
+
+	if (!pld_context)
+		return;
+
+	spin_lock_irqsave(&pld_context->pld_lock, flags);
+	list_for_each_entry_safe(dev_node, tmp, &pld_context->dev_list, list) {
+		if (dev_node->dev == dev) {
+			list_del(&dev_node->list);
+			kfree(dev_node);
+		}
+	}
+	spin_unlock_irqrestore(&pld_context->pld_lock, flags);
+
+	pld_context->ops->remove(dev, PLD_BUS_TYPE_SNOC);
+}
+
+/**
+ * pld_snoc_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_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,
+						NULL, NULL);
+
+	return -ENODEV;
+}
+
+/**
+ * pld_snoc_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_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);
+}
+
+/**
+ * pld_snoc_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_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);
+}
+
+/**
+ * pld_snoc_suspend() - Suspend callback function for power management
+ * @dev: device
+ * @state: power state
+ *
+ * This function is to suspend the platform device when power management
+ * is enabled.
+ *
+ * Return: void
+ */
+static int pld_snoc_suspend(struct device *dev, pm_message_t state)
+{
+	struct pld_context *pld_context;
+
+	pld_context = pld_get_global_context();
+	return pld_context->ops->suspend(dev, PLD_BUS_TYPE_SNOC, state);
+}
+
+/**
+ * pld_snoc_resume() - 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_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);
+}
+
+struct icnss_driver_ops pld_snoc_ops = {
+	.name       = "pld_snoc",
+	.probe      = pld_snoc_probe,
+	.remove     = pld_snoc_remove,
+	.shutdown   = pld_snoc_shutdown,
+	.reinit     = pld_snoc_reinit,
+	.crash_shutdown = pld_snoc_crash_shutdown,
+	.suspend    = pld_snoc_suspend,
+	.resume     = pld_snoc_resume,
+};
+
+/**
+ * pld_snoc_register_driver() - Register platform device callback functions
+ *
+ * Return: int
+ */
+int pld_snoc_register_driver(void)
+{
+	return icnss_register_driver(&pld_snoc_ops);
+}
+
+/**
+ * pld_snoc_unregister_driver() - Unregister platform device callback functions
+ *
+ * Return: void
+ */
+void pld_snoc_unregister_driver(void)
+{
+	icnss_unregister_driver(&pld_snoc_ops);
+}
+
+/**
+ * pld_snoc_wlan_enable() - Enable WLAN
+ * @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_wlan_enable(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;
+
+	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(&cfg, icnss_mode, host_version);
+}
+
+/**
+ * pld_snoc_wlan_disable() - Disable WLAN
+ * @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_wlan_disable(enum pld_driver_mode mode)
+{
+	return icnss_wlan_disable(ICNSS_OFF);
+}
+
+/**
+ * pld_snoc_get_soc_info() - Get SOC information
+ * @info: buffer to SOC information
+ *
+ * Return SOC info to the buffer.
+ *
+ * Return: 0 for success
+ *         Non zero failure code for errors
+ */
+int pld_snoc_get_soc_info(struct pld_soc_info *info)
+{
+	int ret = 0;
+	struct icnss_soc_info icnss_info;
+
+	if (info == NULL)
+		return -ENODEV;
+
+	ret = icnss_get_soc_info(&icnss_info);
+	if (0 != ret)
+		return ret;
+
+	memcpy(info, &icnss_info, sizeof(*info));
+	return 0;
+}
+
+#endif
diff --git a/core/pld/src/pld_snoc.h b/core/pld/src/pld_snoc.h
new file mode 100644
index 0000000..3217106
--- /dev/null
+++ b/core/pld/src/pld_snoc.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2016 The Linux Foundation. All rights reserved.
+ *
+ * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
+ *
+ *
+ * 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.
+ */
+
+/*
+ * This file was originally distributed by Qualcomm Atheros, Inc.
+ * under proprietary terms before Copyright ownership was assigned
+ * to the Linux Foundation.
+ */
+
+#ifndef __PLD_SNOC_H__
+#define __PLD_SNOC_H__
+
+#include "pld_common.h"
+
+#ifndef CONFIG_ICNSS
+static inline int pld_snoc_register_driver(void)
+{
+	return 0;
+}
+
+static inline void pld_snoc_unregister_driver(void)
+{
+	return;
+}
+static inline int pld_snoc_wlan_enable(struct pld_wlan_enable_cfg *config,
+		    enum pld_driver_mode mode, const char *host_version)
+{
+	return 0;
+}
+static inline int pld_snoc_wlan_disable(enum pld_driver_mode mode)
+{
+	return 0;
+}
+static inline int icnss_ce_request_irq(unsigned int ce_id,
+		       irqreturn_t (*handler)(int, void *),
+		       unsigned long flags, const char *name, void *ctx)
+{
+	return 0;
+}
+static inline int icnss_ce_free_irq(unsigned int ce_id, void *ctx)
+{
+	return 0;
+}
+static inline void icnss_enable_irq(unsigned int ce_id)
+{
+	return;
+}
+static inline void icnss_disable_irq(unsigned int ce_id)
+{
+	return;
+}
+static inline int icnss_get_soc_info(struct pld_soc_info *info)
+{
+	return 0;
+}
+static inline int icnss_get_ce_id(int irq)
+{
+	return 0;
+}
+static inline int pld_snoc_get_soc_info(struct pld_soc_info *info)
+{
+	return 0;
+}
+#else
+int pld_snoc_register_driver(void);
+void pld_snoc_unregister_driver(void);
+int pld_snoc_wlan_enable(struct pld_wlan_enable_cfg *config,
+			 enum pld_driver_mode mode, const char *host_version);
+int pld_snoc_wlan_disable(enum pld_driver_mode mode);
+int pld_snoc_get_soc_info(struct pld_soc_info *info);
+#endif
+
+#endif