/*
* Copyright (C) 2011-2014 MediaTek Inc.
*
* This program is free software: you can redistribute it and/or modify it under the terms of the
* GNU General Public License version 2 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 the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program.
* If not, see .
*/
#include
#ifdef DFT_TAG
#undef DFT_TAG
#endif
#define DFT_TAG "[WMT-DETECT]"
#include "wmt_detect.h"
#include "wmt_gpio.h"
#define INVALID_PIN_ID (0xFFFFFFFF)
/*copied form WMT module*/
static int wmt_detect_dump_pin_conf(void)
{
WMT_DETECT_INFO_FUNC("[WMT-DETECT]=>dump wmt pin configuration start<=\n");
if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_LDO_EN_PIN].gpio_num) {
WMT_DETECT_INFO_FUNC("LDO(GPIO%d)\n",
gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_LDO_EN_PIN].gpio_num);
} else
WMT_DETECT_INFO_FUNC("LDO(not defined)\n");
if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num) {
WMT_DETECT_INFO_FUNC("PMU(GPIO%d)\n",
gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num);
} else
WMT_DETECT_INFO_FUNC("PMU(not defined)\n");
if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMUV28_EN_PIN].gpio_num) {
WMT_DETECT_INFO_FUNC("PMUV28(GPIO%d)\n",
gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMUV28_EN_PIN].gpio_num);
} else
WMT_DETECT_INFO_FUNC("PMUV28(not defined)\n");
if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num) {
WMT_DETECT_INFO_FUNC("RST(GPIO%d)\n",
gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num);
} else
WMT_DETECT_INFO_FUNC("RST(not defined)\n");
if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_BGF_EINT_PIN].gpio_num) {
WMT_DETECT_INFO_FUNC("BGF_EINT(GPIO%d)\n",
gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_BGF_EINT_PIN].gpio_num);
} else
WMT_DETECT_INFO_FUNC("BGF_EINT(not defined)\n");
if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_BGF_EINT_PIN].gpio_num) {
WMT_DETECT_INFO_FUNC("BGF_EINT_NUM(%d)\n",
gpio_to_irq(gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_BGF_EINT_PIN].gpio_num));
} else
WMT_DETECT_INFO_FUNC("BGF_EINT_NUM(not defined)\n");
if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num) {
WMT_DETECT_INFO_FUNC("WIFI_EINT(GPIO%d)\n",
gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num);
} else
WMT_DETECT_INFO_FUNC("WIFI_EINT(not defined)\n");
if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num) {
WMT_DETECT_INFO_FUNC("WIFI_EINT_NUM(%d)\n",
gpio_to_irq(gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num));
} else
WMT_DETECT_INFO_FUNC("WIFI_EINT_NUM(not defined)\n");
WMT_DETECT_INFO_FUNC("[WMT-PLAT]=>dump wmt pin configuration emds<=\n");
return 0;
}
int _wmt_detect_output_low(unsigned int id)
{
if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[id].gpio_num) {
gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[id].gpio_num, 0);
WMT_DETECT_DBG_FUNC("WMT-DETECT: set GPIO%d to output %d\n",
gpio_ctrl_info.gpio_ctrl_state[id].gpio_num,
gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[id].gpio_num));
}
return 0;
}
int _wmt_detect_output_high(unsigned int id)
{
if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[id].gpio_num) {
gpio_direction_output(gpio_ctrl_info.gpio_ctrl_state[id].gpio_num, 1);
WMT_DETECT_DBG_FUNC("WMT-DETECT: set GPIO%d to output %d\n",
gpio_ctrl_info.gpio_ctrl_state[id].gpio_num,
gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[id].gpio_num));
}
return 0;
}
int _wmt_detect_read_gpio_input(unsigned int id)
{
int retval = 0;
if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[id].gpio_num) {
retval = gpio_get_value(gpio_ctrl_info.gpio_ctrl_state[id].gpio_num);
WMT_DETECT_DBG_FUNC("WMT-DETECT: get GPIO%d val%d\n",
gpio_ctrl_info.gpio_ctrl_state[id].gpio_num, retval);
}
return retval;
}
/*This power on sequence must support all combo chip's basic power on sequence
* 1. LDO control is a must, if external LDO exist
* 2. PMU control is a must
* 3. RST control is a must
* 4. WIFI_EINT pin control is a must, used for GPIO mode for EINT status checkup
* 5. RTC32k clock control is a must
* */
static int wmt_detect_chip_pwr_on(void)
{
int retval = -1;
/*setting validiation check*/
if ((INVALID_PIN_ID == gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num) ||
(INVALID_PIN_ID == gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num) ||
(INVALID_PIN_ID == gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num)) {
WMT_DETECT_ERR_FUNC("WMT-DETECT: either PMU(%d) or RST(%d) or WIFI_EINT(%d) is not set\n",
gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num,
gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num,
gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num);
return retval;
}
/*set LDO/PMU/RST to output 0, no pull*/
if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_LDO_EN_PIN].gpio_num)
_wmt_detect_output_low(GPIO_COMBO_LDO_EN_PIN);
if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_state[GPIO_PULL_DIS]) {
pinctrl_select_state(gpio_ctrl_info.pinctrl_info,
gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_state[GPIO_PULL_DIS]);
WMT_DETECT_INFO_FUNC("wmt_gpio:set GPIO_COMBO_PMU_EN_PIN to GPIO_PULL_DIS done!\n");
} else
WMT_DETECT_ERR_FUNC("wmt_gpio:set GPIO_COMBO_PMU_EN_PIN to GPIO_PULL_DIS fail, is NULL!\n");
_wmt_detect_output_low(GPIO_COMBO_PMU_EN_PIN);
if (gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_state[GPIO_PULL_DIS]) {
pinctrl_select_state(gpio_ctrl_info.pinctrl_info,
gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_state[GPIO_PULL_DIS]);
WMT_DETECT_INFO_FUNC("wmt_gpio:set GPIO_COMBO_RST_PIN to GPIO_PULL_DIS done!\n");
} else
WMT_DETECT_ERR_FUNC("wmt_gpio:set GPIO_COMBO_RST_PIN to GPIO_PULL_DIS fail, is NULL!\n");
_wmt_detect_output_low(GPIO_COMBO_RST_PIN);
#if 0
_wmt_detect_output_high(GPIO_WIFI_EINT_PIN);
#endif
/*pull high LDO*/
if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_LDO_EN_PIN].gpio_num)
_wmt_detect_output_high(GPIO_COMBO_LDO_EN_PIN);
/*sleep for LDO stable time*/
msleep(MAX_LDO_STABLE_TIME);
/*export RTC clock, sleep for RTC stable time*/
rtc_gpio_enable_32k(RTC_GPIO_USER_GPS);
msleep(MAX_RTC_STABLE_TIME);
/*PMU output low, RST output low, to make chip power off completely*/
/*always done*/
/*sleep for power off stable time*/
msleep(MAX_OFF_STABLE_TIME);
/*PMU output high, and sleep for reset stable time*/
_wmt_detect_output_high(GPIO_COMBO_PMU_EN_PIN);
#ifdef CONFIG_MTK_COMBO_COMM_NPWR
if ((gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_I2S_DAT_PIN].gpio_num != INVALID_PIN_ID) &&
(gpio_ctrl_info.gpio_ctrl_state[GPIO_PCM_DAISYNC_PIN].gpio_num != INVALID_PIN_ID)) {
msleep(20);
_wmt_detect_output_high(GPIO_PCM_DAISYNC_PIN);
msleep(20);
_wmt_detect_output_high(GPIO_COMBO_I2S_DAT_PIN);
msleep(20);
_wmt_detect_output_low(GPIO_COMBO_I2S_DAT_PIN);
msleep(20);
_wmt_detect_output_low(GPIO_PCM_DAISYNC_PIN);
msleep(20);
}
#endif
msleep(MAX_RST_STABLE_TIME);
/*RST output high, and sleep for power on stable time */
_wmt_detect_output_high(GPIO_COMBO_RST_PIN);
msleep(MAX_ON_STABLE_TIME);
retval = 0;
return retval;
}
static int wmt_detect_chip_pwr_off(void)
{
/*set RST pin to input low status*/
if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_LDO_EN_PIN].gpio_num)
_wmt_detect_output_low(GPIO_COMBO_LDO_EN_PIN);
/*set RST pin to input low status*/
if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_RST_PIN].gpio_num)
_wmt_detect_output_low(GPIO_COMBO_RST_PIN);
/*set PMU pin to input low status*/
if (INVALID_PIN_ID != gpio_ctrl_info.gpio_ctrl_state[GPIO_COMBO_PMU_EN_PIN].gpio_num)
_wmt_detect_output_low(GPIO_COMBO_PMU_EN_PIN);
return 0;
}
int wmt_detect_read_ext_cmb_status(void)
{
int retval = 0;
/*read WIFI_EINT pin status*/
if (INVALID_PIN_ID == gpio_ctrl_info.gpio_ctrl_state[GPIO_WIFI_EINT_PIN].gpio_num) {
retval = 0;
WMT_DETECT_ERR_FUNC("WMT-DETECT: no WIFI_EINT pin set\n");
} else {
retval = _wmt_detect_read_gpio_input(GPIO_WIFI_EINT_PIN);
WMT_DETECT_ERR_FUNC("WMT-DETECT: WIFI_EINT input status:%d\n", retval);
}
return retval;
}
int wmt_detect_chip_pwr_ctrl(int on)
{
int retval = -1;
if (0 == on) {
/*power off combo chip */
retval = wmt_detect_chip_pwr_off();
} else {
wmt_detect_dump_pin_conf();
/*power on combo chip */
retval = wmt_detect_chip_pwr_on();
}
return retval;
}
int wmt_detect_sdio_pwr_ctrl(int on)
{
int retval = -1;
#ifdef MTK_WCN_COMBO_CHIP_SUPPORT
if (0 == on) {
/*power off SDIO slot */
retval = board_sdio_ctrl(1, 0);
} else {
/*power on SDIO slot */
retval = board_sdio_ctrl(1, 1);
}
#else
WMT_DETECT_WARN_FUNC("WMT-DETECT: MTK_WCN_COMBO_CHIP_SUPPORT is not set\n");
#endif
return retval;
}