wifi: Modify for support WOW on Sound united

Test: Pass

Change-Id: Ic0142b09f6d7c42491806c813303a19db4a4a8e6
CR-Id: AUTO00014958
Signed-off-by: Shengxi Xu <shengxi.xu@mediatek.com>
Reviewed-on: http://gerrit.mediatek.inc:8080/1494004
CheckPatch: Check Patch <srv_checkpatch@mediatek.com>
Reviewed-by: Jiehang Zheng <jiehang.zheng@mediatek.com>
Tested-by: Jiehang Zheng <jiehang.zheng@mediatek.com>
diff --git a/Makefile b/Makefile
index b657c94..0df8602 100644
--- a/Makefile
+++ b/Makefile
@@ -163,6 +163,7 @@
 			$(NIC_DIR)nic_umac.o
 
 OS_OBJS :=	$(OS_DIR)gl_init.o \
+			$(OS_DIR)gl_gpio.o \
 			$(OS_DIR)gl_kal.o  \
 			$(OS_DIR)gl_bow.o \
 			$(OS_DIR)gl_wext.o \
diff --git a/Makefile.ce b/Makefile.ce
index 7c66a86..88575c1 100644
--- a/Makefile.ce
+++ b/Makefile.ce
@@ -183,7 +183,9 @@
 CFG_SUPPORT_SINGLE_SKU_LOCAL_DB=0
 endif
 
-
+ifeq ($(WOW_WAKE_UP), 1)
+PLATFORM_FLAGS += -DCFG_USE_LINUX_GPIO_GLUE=1
+endif
 
 #/***** Manage configs into compile options ******/
 ifneq ($(CFG_NUM_DIFFERENT_CHANNELS_STA),)
diff --git a/Makefile.x86 b/Makefile.x86
index d279330..8543ae7 100644
--- a/Makefile.x86
+++ b/Makefile.x86
@@ -89,6 +89,10 @@
 
 CFG_CHIP_RESET_SUPPORT=0
 
+ifeq ($(WOW_WAKE_UP), 1)
+PLATFORM_FLAGS += -DCFG_USE_LINUX_GPIO_GLUE=1
+endif
+
 #/***** Manage configs into compile options ******/
 ifneq ($(CFG_NUM_DIFFERENT_CHANNELS_STA),)
 PLATFORM_FLAGS += -DCFG_NUM_DIFFERENT_CHANNELS_STA=$(CFG_NUM_DIFFERENT_CHANNELS_STA)
diff --git a/os/linux/gl_gpio.c b/os/linux/gl_gpio.c
new file mode 100644
index 0000000..5de3076
--- /dev/null
+++ b/os/linux/gl_gpio.c
@@ -0,0 +1,258 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual license.  When you use or
+ * distribute this software, you may choose to be licensed under
+ * version 2 of the GNU General Public License ("GPLv2 License")
+ * or BSD License.
+ *
+ * GPLv2 License
+ *
+ * Copyright(C) 2016 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(C) 2016 MediaTek Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+#include "gl_os.h"
+
+#ifdef CFG_USE_LINUX_GPIO_GLUE
+
+
+/*******************************************************************************
+*                         C O M P I L E R   F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                    E X T E R N A L   R E F E R E N C E S
+********************************************************************************
+*/
+#include <linux/of_gpio.h>
+#include <linux/of_irq.h>
+#include "gl_gpio.h"
+
+/*******************************************************************************
+*                              C O N S T A N T S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                             D A T A   T Y P E S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                            P U B L I C   D A T A
+********************************************************************************
+*/
+static struct GPIO_GLUE_INFO gGpioGlueInfo = {
+	{
+		{
+			.pinName = "mt7668-wowlan",
+			.pinIndex = WLAN_GPIO_WOW_PIN,
+			.debounce = WLAN_GPIO_PIN_WOW_DEBOUNCE_TIME,
+			.gpio = 0,
+			.irq = 0,
+		},
+		{
+			.pinName = "mt7668-bcn-tsf",
+			.pinIndex = WLAN_GPIO_BCN_TSF_PIN,
+			.debounce = 0,
+			.gpio = 0,
+			.irq = 0,
+		},
+	}
+};
+
+/*******************************************************************************
+*                           P R I V A T E   D A T A
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                                 M A C R O S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                  F U N C T I O N   D E C L A R A T I O N S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                              F U N C T I O N S
+********************************************************************************
+*/
+
+/**
+ * _wlanGpioAlloc - GPIO pin allocated
+ * @np: wifi device node in dts file
+ * @pGpioCtrl: ctrl information for GPIO pin
+ */
+static INT_32 _wlanGpioAlloc(struct device_node *np,
+	struct GPIO_CTRL_INFO *pGpioCtrl)
+{
+	INT_32 ret = 0;
+
+	/* Parameter Check */
+	if (np == NULL || pGpioCtrl == NULL) {
+		DBGLOG(INIT, STATE, "%s parameter check fail !\n", __func__);
+		return -EINVAL;
+	}
+
+	/* debug info */
+	DBGLOG(INIT, STATE, "%s pinName=%s\n", __func__, pGpioCtrl->pinName);
+	DBGLOG(INIT, STATE, "%s pinIndex=%d\n", __func__, pGpioCtrl->pinIndex);
+	DBGLOG(INIT, STATE, "%s debounce=%d\n", __func__, pGpioCtrl->debounce);
+
+	/* init gpio  */
+	pGpioCtrl->gpio = of_get_named_gpio(np, WLAN_GPIO_PIN_NAME,
+					pGpioCtrl->pinIndex);
+
+	if (!gpio_is_valid(pGpioCtrl->gpio)) {
+		DBGLOG(INIT, STATE, "%s get invalid %s gpio %d\n",
+				__func__, pGpioCtrl->pinName, pGpioCtrl->gpio);
+		return -EINVAL;
+	}
+
+	DBGLOG(INIT, STATE, "%s get %s gpio(%d) suscessfully\n",
+		__func__, pGpioCtrl->pinName, pGpioCtrl->gpio);
+
+	ret = gpio_request(pGpioCtrl->gpio, pGpioCtrl->pinName);
+	if (ret < 0) {
+		DBGLOG(INIT, STATE, "%s request %s gpio(%d) fail\n",
+				__func__, pGpioCtrl->pinName, pGpioCtrl->gpio);
+		return ret;
+	}
+
+	ret = gpio_direction_input(pGpioCtrl->gpio);
+	if (ret != 0) {
+		DBGLOG(INIT, STATE, "%s set %s gpio(%d) to input mode fail\n",
+				__func__, pGpioCtrl->pinName, pGpioCtrl->gpio);
+		gpio_free(pGpioCtrl->gpio);
+		return ret;
+	}
+
+	DBGLOG(INIT, STATE, "%s set %s gpio(%d) to input mode\n",
+		__func__, pGpioCtrl->pinName, pGpioCtrl->gpio);
+
+	if (pGpioCtrl->debounce) {
+		gpio_set_debounce(pGpioCtrl->gpio, pGpioCtrl->debounce);
+		if (ret < 0) {
+			DBGLOG(INIT, STATE,
+				"%s set %s gpio(%d) debounce fail\n",
+				__func__, pGpioCtrl->pinName, pGpioCtrl->gpio);
+			gpio_free(pGpioCtrl->gpio);
+			return ret;
+		}
+
+		DBGLOG(INIT, STATE, "%s set %s gpio(%d) debounce %d\n",
+			__func__, pGpioCtrl->pinName, pGpioCtrl->gpio,
+			pGpioCtrl->debounce);
+	}
+
+	/* init irq */
+	pGpioCtrl->irq = of_irq_get(np, pGpioCtrl->pinIndex);
+
+	DBGLOG(INIT, STATE, "%s get %s irq(%d) suscessfully\n",
+		__func__, pGpioCtrl->pinName, pGpioCtrl->irq);
+
+	return ret;
+}
+
+/**
+ * wlanPlatformCfgInit - platform resource initialized for wlan
+ */
+INT_32 wlanPlatformCfgInit(void)
+{
+	struct GPIO_GLUE_INFO *prGpioGlueInfo = &gGpioGlueInfo;
+	INT_32 ret = 0;
+
+	/* get wlan device node */
+	prGpioGlueInfo->np = of_find_compatible_node(NULL,
+				NULL, "mediatek,mt7668-wifi");
+	if (prGpioGlueInfo->np == NULL) {
+		DBGLOG(INIT, STATE, "%s can't find device tree node!\n",
+				__func__);
+		return -EINVAL;
+	}
+
+	/* init WOW PIN */
+	ret = _wlanGpioAlloc(prGpioGlueInfo->np,
+			&prGpioGlueInfo->pinInfo[WLAN_GPIO_WOW_PIN]);
+	if (ret != 0) {
+		DBGLOG(INIT, STATE, "%s _wlanGpioAlloc wow fail(%d)!\n",
+				__func__, ret);
+		return ret;
+	}
+
+	/* init BCN TSF PIN */
+	ret = _wlanGpioAlloc(prGpioGlueInfo->np,
+			&prGpioGlueInfo->pinInfo[WLAN_GPIO_BCN_TSF_PIN]);
+	if (ret != 0) {
+		DBGLOG(INIT, STATE, "%s _wlanGpioAlloc bcn tsf fail(%d)!\n",
+				__func__, ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+/**
+ * wlanPlatformCfgDestroy - remove platform resource for wifi
+ */
+void wlanPlatformCfgDestroy(void)
+{
+	struct GPIO_GLUE_INFO *prGpioGlueInfo = &gGpioGlueInfo;
+
+	gpio_free(prGpioGlueInfo->pinInfo[WLAN_GPIO_WOW_PIN].gpio);
+
+	gpio_free(prGpioGlueInfo->pinInfo[WLAN_GPIO_BCN_TSF_PIN].gpio);
+
+	kalMemZero(prGpioGlueInfo, sizeof(struct GPIO_CTRL_INFO));
+}
+
+struct GPIO_GLUE_INFO *wlanPlatformCfgGet(void)
+{
+	return &gGpioGlueInfo;
+}
+
+#endif /* CFG_USE_LINUX_GPIO_GLUE */
+
+
diff --git a/os/linux/gl_init.c b/os/linux/gl_init.c
index e882606..45ad6a2 100644
--- a/os/linux/gl_init.c
+++ b/os/linux/gl_init.c
@@ -1153,6 +1153,16 @@
 /*----------------------------------------------------------------------------*/
 static void wlanUninit(struct net_device *prDev)
 {
+	P_GLUE_INFO_T prGlueInfo = NULL;
+
+	if (!prDev)
+		return;
+
+	prGlueInfo = *((P_GLUE_INFO_T *) netdev_priv(prDev));
+
+#if CFG_WOW_SUPPORT
+	kalWowUninit(prGlueInfo);
+#endif
 }				/* end of wlanUninit() */
 
 /*----------------------------------------------------------------------------*/
@@ -1754,6 +1764,10 @@
 	/* init CSI wait queue  */
 	init_waitqueue_head(&(prGlueInfo->prAdapter->rCsiData.waitq));
 
+#ifdef CFG_USE_LINUX_GPIO_GLUE
+	prGlueInfo->prGpioGlueInfo = wlanPlatformCfgGet();
+#endif
+
 	return prWdev;
 
 netcreate_err:
@@ -2861,6 +2875,11 @@
 		glP2pCreateWirelessDevice((P_GLUE_INFO_T) wiphy_priv(gprWdev->wiphy));
 	gprP2pWdev = gprP2pRoleWdev[0];/* P2PDev and P2PRole[0] share the same Wdev */
 
+#ifdef CFG_USE_LINUX_GPIO_GLUE
+		/* Allocate platform resource */
+		wlanPlatformCfgInit();
+#endif
+
 	ret = ((glRegisterBus(wlanProbe, wlanRemove) == WLAN_STATUS_SUCCESS) ? 0 : -EIO);
 
 	if (ret == -EIO) {
@@ -2894,6 +2913,12 @@
 #if WLAN_INCLUDE_PROC
 	procUninitProcFs();
 #endif
+
+#ifdef CFG_USE_LINUX_GPIO_GLUE
+	/* Allocate platform resource */
+	wlanPlatformCfgDestroy();
+#endif
+
 	DBGLOG(INIT, INFO, "exitWlan\n");
 
 }				/* end of exitWlan() */
diff --git a/os/linux/gl_kal.c b/os/linux/gl_kal.c
index 9767852..5eb45f5 100644
--- a/os/linux/gl_kal.c
+++ b/os/linux/gl_kal.c
@@ -78,6 +78,9 @@
 #include <net/netlink.h>
 #endif
 #include <linux/ctype.h>
+#ifdef CFG_USE_LINUX_GPIO_GLUE
+#include <linux/interrupt.h>
+#endif
 
 /*******************************************************************************
 *                              C O N S T A N T S
@@ -5089,10 +5092,173 @@
 #endif
 
 #if CFG_WOW_SUPPORT
+#ifdef CFG_USE_LINUX_GPIO_GLUE
+static irqreturn_t wowHandler(int irq, void *data)
+{
+
+	disable_irq_nosync(irq);
+
+	return IRQ_WAKE_THREAD;
+}
+
+static irqreturn_t wowThreadFn(int irq, void *data)
+{
+	DBGLOG(INIT, ERROR, "WOW wakup interrupt come in!!\n");
+
+	return IRQ_HANDLED;
+}
+
+INT_32 wlanWowIrqEnable(IN struct GPIO_GLUE_INFO *prGpioGlueInfo)
+{
+	struct GPIO_CTRL_INFO *wowPinInfo = NULL;
+	INT_32 ret = 0;
+
+	if (prGpioGlueInfo == NULL) {
+		DBGLOG(INIT, ERROR, "%s parameter check fail\n", __func__);
+		return -EINVAL;
+	}
+
+	wowPinInfo = &prGpioGlueInfo->pinInfo[WLAN_GPIO_WOW_PIN];
+
+	if (wowPinInfo->irq <= 0) {
+		DBGLOG(INIT, ERROR, "%s no IRQ specified\n", __func__);
+		return -EINVAL;
+	}
+
+	enable_irq(wowPinInfo->irq);
+
+	ret = enable_irq_wake(wowPinInfo->irq);
+	if (ret != 0) {
+		DBGLOG(INIT, ERROR, "%s enable_irq_wake(%d) fail(%d)!\n",
+				__func__, wowPinInfo->irq, ret);
+	} else {
+		DBGLOG(INIT, STATE, "%s enable_irq_wake(%d) success!\n",
+				__func__, wowPinInfo->irq);
+	}
+
+	return ret;
+}
+
+INT_32 wlanWowIrqDisable(IN struct GPIO_GLUE_INFO *prGpioGlueInfo)
+{
+	struct GPIO_CTRL_INFO *wowPinInfo = NULL;
+	INT_32 ret = 0;
+
+	if (prGpioGlueInfo == NULL) {
+		DBGLOG(INIT, ERROR, "%s parameter check fail\n", __func__);
+		return -EINVAL;
+	}
+
+	wowPinInfo = &prGpioGlueInfo->pinInfo[WLAN_GPIO_WOW_PIN];
+
+	if (wowPinInfo->irq <= 0) {
+		DBGLOG(INIT, ERROR, "%s no IRQ specified\n", __func__);
+		return -EINVAL;
+	}
+
+	DBGLOG(INIT, STATE, "%s get wow irq(%d) suscessfully\n",
+		__func__, wowPinInfo->irq);
+
+	disable_irq(wowPinInfo->irq);
+
+	DBGLOG(INIT, STATE, "%s disable_irq success!\n", __func__);
+
+	return ret;
+}
+
+INT_32 wlanWowIrqInit(IN struct GPIO_GLUE_INFO *prGpioGlueInfo)
+{
+	struct GPIO_CTRL_INFO *wowPinInfo = NULL;
+	INT_32 ret = 0;
+
+	if (prGpioGlueInfo == NULL) {
+		DBGLOG(INIT, ERROR, "%s parameter check fail\n", __func__);
+		return -EINVAL;
+	}
+
+	wowPinInfo = &prGpioGlueInfo->pinInfo[WLAN_GPIO_WOW_PIN];
+
+	if (wowPinInfo->irq <= 0) {
+		DBGLOG(INIT, ERROR, "%s no IRQ specified\n", __func__);
+		return -EINVAL;
+	}
+
+	ret = request_threaded_irq(wowPinInfo->irq,
+					  wowHandler, wowThreadFn,
+					  IRQF_ONESHOT | IRQF_TRIGGER_LOW,
+					  wowPinInfo->pinName,
+					  NULL);
+	if (ret) {
+		DBGLOG(INIT, ERROR, "%s failed to request IRQ\n", __func__);
+		return ret;
+	}
+
+	disable_irq(wowPinInfo->irq);
+	DBGLOG(INIT, STATE, "%s disable_irq(%d) !\n",
+				__func__, wowPinInfo->irq);
+
+	return ret;
+}
+
+INT_32 wlanWowIrqFree(IN struct GPIO_GLUE_INFO *prGpioGlueInfo)
+{
+	struct GPIO_CTRL_INFO *wowPinInfo = NULL;
+	INT_32 ret = 0;
+
+	if (prGpioGlueInfo == NULL) {
+		DBGLOG(INIT, ERROR, "%s prGpioGlueInfo is NULL\n", __func__);
+		return -EINVAL;
+	}
+
+	wowPinInfo = &prGpioGlueInfo->pinInfo[WLAN_GPIO_WOW_PIN];
+
+	if (wowPinInfo->irq <= 0) {
+		DBGLOG(INIT, ERROR, "%s no IRQ specified\n", __func__);
+		return -EINVAL;
+	}
+
+	free_irq(wowPinInfo->irq, NULL);
+
+	DBGLOG(INIT, STATE, "%s free_irq(%d) !\n",
+				__func__, wowPinInfo->irq);
+
+	return ret;
+}
+
+#endif /* CFG_USE_LINUX_GPIO_GLUE */
+
+VOID kalWowUninit(IN P_GLUE_INFO_T prGlueInfo)
+{
+	if (prGlueInfo == NULL) {
+		DBGLOG(INIT, ERROR, "%s prGlueInfo is NULL\n", __func__);
+		return;
+	}
+
+	kalMemZero(&prGlueInfo->prAdapter->rWowCtrl.stWowPort, sizeof(WOW_PORT_T));
+
+#ifdef CFG_USE_LINUX_GPIO_GLUE
+	wlanWowIrqFree(prGlueInfo->prGpioGlueInfo);
+
+	DBGLOG(INIT, STATE, "%s wow module uninitialized end!\n", __func__);
+#endif /* CFG_USE_LINUX_GPIO_GLUE */
+}
+
 VOID kalWowInit(IN P_GLUE_INFO_T prGlueInfo)
 {
-	kalMemZero(&prGlueInfo->prAdapter->rWowCtrl.stWowPort, sizeof(WOW_PORT_T));
+	if (prGlueInfo == NULL) {
+		DBGLOG(INIT, ERROR, "%s prGlueInfo is NULL\n", __func__);
+		return;
+	}
+
+	kalMemZero(&prGlueInfo->prAdapter->rWowCtrl.stWowPort,
+		sizeof(WOW_PORT_T));
 	prGlueInfo->prAdapter->rWowCtrl.ucReason = INVALID_WOW_WAKE_UP_REASON;
+
+#ifdef CFG_USE_LINUX_GPIO_GLUE
+	wlanWowIrqInit(prGlueInfo->prGpioGlueInfo);
+
+	DBGLOG(INIT, STATE, "%s wow module initialized end!\n", __func__);
+#endif /* CFG_USE_LINUX_GPIO_GLUE */
 }
 
 VOID kalWowCmdEventSetCb(IN P_ADAPTER_T prAdapter, IN P_CMD_INFO_T prCmdInfo, IN PUINT_8 pucEventBuf)
@@ -5244,6 +5410,10 @@
 		wait++;
 	}
 
+#ifdef CFG_USE_LINUX_GPIO_GLUE
+	if (enable == 1)
+		wlanWowIrqEnable(prGlueInfo->prGpioGlueInfo);
+#endif
 }
 #endif
 
diff --git a/os/linux/include/gl_gpio.h b/os/linux/include/gl_gpio.h
new file mode 100644
index 0000000..6c1ef9a
--- /dev/null
+++ b/os/linux/include/gl_gpio.h
@@ -0,0 +1,118 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual license.  When you use or
+ * distribute this software, you may choose to be licensed under
+ * version 2 of the GNU General Public License ("GPLv2 License")
+ * or BSD License.
+ *
+ * GPLv2 License
+ *
+ * Copyright(C) 2016 MediaTek Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See http://www.gnu.org/licenses/gpl-2.0.html for more details.
+ *
+ * BSD LICENSE
+ *
+ * Copyright(C) 2016 MediaTek Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *  * Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *****************************************************************************/
+
+#ifndef _GL_GPIO_H
+#define _GL_GPIO_H
+
+#include "gl_os.h"
+
+#ifdef CFG_USE_LINUX_GPIO_GLUE
+
+/*******************************************************************************
+*                         C O M P I L E R   F L A G S
+********************************************************************************
+*/
+
+/*******************************************************************************
+*                    E X T E R N A L   R E F E R E N C E S
+********************************************************************************
+*/
+
+#include <linux/of.h>
+
+/*******************************************************************************
+*                              C O N S T A N T S
+********************************************************************************
+*/
+
+#define WLAN_GPIO_PIN_NAME "mt7668-wifi-gpio"
+#define WLAN_GPIO_PIN_NAME_LEN 32
+
+#define  WLAN_GPIO_PIN_WOW_DEBOUNCE_TIME 100 /* ms */
+
+
+enum {
+	WLAN_GPIO_WOW_PIN,
+	WLAN_GPIO_BCN_TSF_PIN,
+	WLAN_GPIO_PIN_ID_MAX
+};
+
+/*******************************************************************************
+*                             D A T A   T Y P E S
+********************************************************************************
+*/
+
+struct GPIO_CTRL_INFO {
+	CHAR pinName[WLAN_GPIO_PIN_NAME_LEN];
+	INT_32 pinIndex;
+	INT_32 gpio;
+	INT_32 irq;
+	INT_32 debounce;
+};
+
+struct GPIO_GLUE_INFO {
+	struct GPIO_CTRL_INFO pinInfo[WLAN_GPIO_PIN_ID_MAX];
+	struct device_node *np;
+};
+
+/*******************************************************************************
+*                  F U N C T I O N   D E C L A R A T I O N S
+********************************************************************************
+*/
+INT_32 wlanPlatformCfgInit(void);
+void wlanPlatformCfgDestroy(void);
+struct GPIO_GLUE_INFO *wlanPlatformCfgGet(void);
+
+#endif /* CFG_USE_LINUX_GPIO_GLUE */
+
+#endif /* _GL_GPIO_H */
+
diff --git a/os/linux/include/gl_kal.h b/os/linux/include/gl_kal.h
index bed8470..050237b 100644
--- a/os/linux/include/gl_kal.h
+++ b/os/linux/include/gl_kal.h
@@ -1230,6 +1230,7 @@
 #if CFG_WOW_SUPPORT
 VOID kalWowInit(IN P_GLUE_INFO_T prGlueInfo);
 VOID kalWowProcess(IN P_GLUE_INFO_T prGlueInfo, UINT_8 enable);
+VOID kalWowUninit(IN P_GLUE_INFO_T prGlueInfo);
 #endif
 
 int main_thread(void *data);
diff --git a/os/linux/include/gl_os.h b/os/linux/include/gl_os.h
index 81ffe31..92c18b8 100644
--- a/os/linux/include/gl_os.h
+++ b/os/linux/include/gl_os.h
@@ -249,6 +249,10 @@
 #endif
 #include <linux/time.h>
 
+#ifdef CFG_USE_LINUX_GPIO_GLUE
+#include "gl_gpio.h"
+#endif
+
 extern BOOLEAN fgIsBusAccessFailed;
 extern const struct ieee80211_iface_combination *p_mtk_iface_combinations_sta;
 extern const INT_32 mtk_iface_combinations_sta_num;
@@ -640,6 +644,9 @@
 	INT_32 i4RssiCache;
 	UINT_32 u4LinkSpeedCache;
 
+#ifdef CFG_USE_LINUX_GPIO_GLUE
+	struct GPIO_GLUE_INFO *prGpioGlueInfo;
+#endif
 };
 
 typedef irqreturn_t(*PFN_WLANISR) (int irq, void *dev_id, struct pt_regs *regs);