blob: 5de3076851ffc82681f0d8453ace3495e770cdee [file] [log] [blame]
/******************************************************************************
*
* 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 */