qcacld-3.0: Add gpio irq as wakeup source

On some third party platform, the in-band bus suspend-resume is
not supported well, instead add gpio irq as wakeup source to
support out-of-band suspend-resume.

Change-Id: I7621f04d093013e15719b5c84dc244604be238df
CRs-Fixed: 2815754
This commit is contained in:
Li Feng
2020-11-09 16:56:42 +08:00
committed by snandini
parent e75553536a
commit 292b491dd8
10 changed files with 411 additions and 2 deletions

5
Kbuild
View File

@@ -419,6 +419,10 @@ ifeq ($(CONFIG_WLAN_FEATURE_MEDIUM_ASSESS), y)
HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_medium_assess.o
endif
ifeq ($(CONFIG_WLAN_ENABLE_GPIO_WAKEUP),y)
HDD_OBJS += $(HDD_SRC_DIR)/wlan_hdd_gpio_wakeup.o
endif
###### OSIF_SYNC ########
SYNC_DIR := os_if/sync
SYNC_INC_DIR := $(SYNC_DIR)/inc
@@ -3716,6 +3720,7 @@ cppflags-y += -DFEATURE_IPA_PIPE_CHANGE_WDI1
endif
cppflags-$(CONFIG_FEATURE_STA_MODE_VOTE_LINK) += -DFEATURE_STA_MODE_VOTE_LINK
cppflags-$(CONFIG_WLAN_ENABLE_GPIO_WAKEUP) += -DWLAN_ENABLE_GPIO_WAKEUP
KBUILD_CPPFLAGS += $(cppflags-y)

View File

@@ -171,6 +171,24 @@ static void wlan_pmo_ra_filtering_init_cfg(struct wlan_objmgr_psoc *psoc,
}
#endif
#ifdef WLAN_ENABLE_GPIO_WAKEUP
static void wlan_pmo_gpio_wakeup_init_cfg(struct wlan_objmgr_psoc *psoc,
struct pmo_psoc_cfg *psoc_cfg)
{
psoc_cfg->enable_gpio_wakeup =
cfg_get(psoc, CFG_PMO_ENABLE_GPIO_WAKEUP);
psoc_cfg->gpio_wakeup_pin =
cfg_get(psoc, CFG_PMO_GPIO_WAKEUP_PIN);
psoc_cfg->gpio_wakeup_mode =
cfg_get(psoc, CFG_PMO_GPIO_WAKEUP_MODE);
}
#else
static void wlan_pmo_gpio_wakeup_init_cfg(struct wlan_objmgr_psoc *psoc,
struct pmo_psoc_cfg *psoc_cfg)
{
}
#endif
static void wlan_pmo_init_cfg(struct wlan_objmgr_psoc *psoc,
struct pmo_psoc_cfg *psoc_cfg)
{
@@ -212,6 +230,7 @@ static void wlan_pmo_init_cfg(struct wlan_objmgr_psoc *psoc,
cfg_get(psoc, CFG_ACTIVE_MC_BC_APF_MODE);
psoc_cfg->ito_repeat_count = cfg_get(psoc, CFG_ITO_REPEAT_COUNT);
wlan_pmo_ra_filtering_init_cfg(psoc, psoc_cfg);
wlan_pmo_gpio_wakeup_init_cfg(psoc, psoc_cfg);
}
QDF_STATUS pmo_psoc_open(struct wlan_objmgr_psoc *psoc)

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 2012-2018 The Linux Foundation. All rights reserved.
* Copyright (c) 2012-2018, 2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
@@ -25,6 +25,7 @@
#include "wlan_pmo_pkt_filter_cfg.h"
#include "wlan_pmo_runtime_pm_cfg.h"
#include "wlan_pmo_wow_pulse_cfg.h"
#include "wlan_pmo_gpio_wakeup_cfg.h"
#define CFG_PMO_ALL \
CFG_EXTWOW_ALL \
@@ -32,6 +33,7 @@
CFG_PMO_APF_ALL \
CFG_PMO_COMMON_ALL \
CFG_RUNTIME_PM_ALL \
CFG_WOW_PULSE_ALL
CFG_WOW_PULSE_ALL \
CFG_GPIO_WAKEUP_ALL
#endif /* WLAN_PMO_CFG_H__ */

View File

@@ -250,6 +250,22 @@ enum active_apf_mode {
ACTIVE_APF_MODE_COUNT
};
/**
* enum pmo_gpio_wakeup_mode - gpio wakeup mode
* @PMO_GPIO_WAKEUP_MODE_INVALID: gpio wakeup trigger invalid
* @PMO_GPIO_WAKEUP_MODE_RISING: gpio wakeup trigger rising
* @PMO_GPIO_WAKEUP_MODE_FALLING: gpio wakeup trigger failing
* @PMO_GPIO_WAKEUP_MODE_HIGH: gpio wakeup trigger high
* @PMO_GPIO_WAKEUP_MODE_LOW: gpio wakeup trigger low
*/
enum pmo_gpio_wakeup_mode {
PMO_GPIO_WAKEUP_MODE_INVALID,
PMO_GPIO_WAKEUP_MODE_RISING,
PMO_GPIO_WAKEUP_MODE_FALLING,
PMO_GPIO_WAKEUP_MODE_HIGH,
PMO_GPIO_WAKEUP_MODE_LOW,
};
/**
* struct pmo_psoc_cfg - user configuration required for pmo
* @ptrn_match_enable_all_vdev: true when pattern match is enable for all vdev
@@ -307,6 +323,9 @@ enum active_apf_mode {
* @ito_repeat_count: Indicates ito repeated count
* @is_mod_dtim_on_sys_suspend_enabled: true when mod dtim is enabled for
* system suspend wow else false
* @enable_gpio_wakeup: enable gpio wakeup
* @gpio_wakeup_pin: gpio wakeup pin
* @gpio_wakeup_mode: gpio wakeup mode
*/
struct pmo_psoc_cfg {
bool ptrn_match_enable_all_vdev;
@@ -371,6 +390,11 @@ struct pmo_psoc_cfg {
enum active_apf_mode active_mc_bc_apf_mode;
uint8_t ito_repeat_count;
bool is_mod_dtim_on_sys_suspend_enabled;
#ifdef WLAN_ENABLE_GPIO_WAKEUP
bool enable_gpio_wakeup;
uint32_t gpio_wakeup_pin;
enum pmo_gpio_wakeup_mode gpio_wakeup_mode;
#endif
};
/**

View File

@@ -0,0 +1,93 @@
/*
* Copyright (c) 2020 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef WLAN_PMO_GPIO_WAKEUP_CFG_H__
#define WLAN_PMO_GPIO_WAKEUP_CFG_H__
#ifdef WLAN_ENABLE_GPIO_WAKEUP
/*
* <ini>
* genable_gpio_wakeup - Enable gpio wakeup
* @Min: 0
* @Max: 1
* @Default: 0
*
* Enable gpio wakeup
*
* Supported Feature: gpio wakeup
*
* Usage: External
*
* </ini>
*/
#define CFG_PMO_ENABLE_GPIO_WAKEUP CFG_INI_BOOL("genable_gpio_wakeup", \
0, \
"Enable gpio wakeup")
/*
* <ini>
* ggpio_wakeup_pin - Wakeup gpio pin of host platform
* @Min: 0
* @Max: 255
* @Default: 255
*
* Wakeup gpio pin of host platform
*
* Supported Feature: gpio wakeup
*
* Usage: External
*
* </ini>
*/
#define CFG_PMO_GPIO_WAKEUP_PIN CFG_INI_UINT("ggpio_wakeup_pin", \
0, 255, 255, \
CFG_VALUE_OR_DEFAULT, \
"Wakeup gpio pin of host platform")
/*
* <ini>
* ggpio_wakeup_mode - Wakeup gpio mode
* @Min: 0
* @Max: 4
* @Default: 0
*
* Wakeup gpio mode
* 1 indicates rising trigger
* 2 indicates failing trigger
* 3 indicates high trigger
* 4 indicates low trigger
*
* Supported Feature: gpio wakeup
*
* Usage: External
*
* </ini>
*/
#define CFG_PMO_GPIO_WAKEUP_MODE CFG_INI_UINT("ggpio_wakeup_mode", \
0, 4, 0, \
CFG_VALUE_OR_DEFAULT, \
"Wakeup gpio mode")
#define CFG_GPIO_WAKEUP_ALL \
CFG(CFG_PMO_ENABLE_GPIO_WAKEUP) \
CFG(CFG_PMO_GPIO_WAKEUP_PIN) \
CFG(CFG_PMO_GPIO_WAKEUP_MODE)
#else
#define CFG_GPIO_WAKEUP_ALL
#endif /* WLAN_ENABLE_GPIO_WAKEUP */
#endif /* WLAN_PMO_GPIO_WAKEUP_CFG_H__ */

View File

@@ -1138,6 +1138,51 @@ static inline bool ucfg_pmo_is_apf_enabled(struct wlan_objmgr_psoc *psoc)
}
#endif
#ifdef WLAN_ENABLE_GPIO_WAKEUP
/**
* ucfg_pmo_get_enable_gpio_wakeup() - to get gpio wakeup enable configuration
* @psoc: objmgr psoc handle
*
* Return: gpio wakeup enable configuration
*/
bool ucfg_pmo_is_gpio_wakeup_enabled(struct wlan_objmgr_psoc *psoc);
/**
* ucfg_pmo_get_gpio_wakeup_pin() - to get gpio wakeup pin number
* @psoc: objmgr psoc handle
*
* Return: gpio wakeup pin number
*/
uint32_t ucfg_pmo_get_gpio_wakeup_pin(struct wlan_objmgr_psoc *psoc);
/**
* ucfg_pmo_get_gpio_wakeup_mode() - to get gpio wakeup interrupt mode
* @psoc: objmgr psoc handle
*
* Return: gpio wakeup mode
*/
enum pmo_gpio_wakeup_mode
ucfg_pmo_get_gpio_wakeup_mode(struct wlan_objmgr_psoc *psoc);
#else
static inline bool
ucfg_pmo_is_gpio_wakeup_enabled(struct wlan_objmgr_psoc *psoc)
{
return false;
}
static inline uint32_t
ucfg_pmo_get_gpio_wakeup_pin(struct wlan_objmgr_psoc *psoc)
{
return 0;
}
static inline enum pmo_gpio_wakeup_mode
ucfg_pmo_get_gpio_wakeup_mode(struct wlan_objmgr_psoc *psoc)
{
return PMO_GPIO_WAKEUP_MODE_INVALID;
}
#endif
#else /* WLAN_POWER_MANAGEMENT_OFFLOAD */
static inline QDF_STATUS
ucfg_pmo_psoc_open(struct wlan_objmgr_psoc *psoc)

View File

@@ -869,3 +869,27 @@ ucfg_pmo_get_active_mc_bc_apf_mode(struct wlan_objmgr_psoc *psoc)
return pmo_psoc_ctx->psoc_cfg.active_mc_bc_apf_mode;
}
#ifdef WLAN_ENABLE_GPIO_WAKEUP
bool ucfg_pmo_is_gpio_wakeup_enabled(struct wlan_objmgr_psoc *psoc)
{
struct pmo_psoc_priv_obj *pmo_psoc_ctx = pmo_psoc_get_priv(psoc);
return pmo_psoc_ctx->psoc_cfg.enable_gpio_wakeup;
}
uint32_t ucfg_pmo_get_gpio_wakeup_pin(struct wlan_objmgr_psoc *psoc)
{
struct pmo_psoc_priv_obj *pmo_psoc_ctx = pmo_psoc_get_priv(psoc);
return pmo_psoc_ctx->psoc_cfg.gpio_wakeup_pin;
}
enum pmo_gpio_wakeup_mode
ucfg_pmo_get_gpio_wakeup_mode(struct wlan_objmgr_psoc *psoc)
{
struct pmo_psoc_priv_obj *pmo_psoc_ctx = pmo_psoc_get_priv(psoc);
return pmo_psoc_ctx->psoc_cfg.gpio_wakeup_mode;
}
#endif

View File

@@ -0,0 +1,52 @@
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __WLAN_HDD_GPIO_WAKEUP_H__
#define __WLAN_HDD_GPIO_WAKEUP_H__
#ifdef WLAN_ENABLE_GPIO_WAKEUP
/**
* wlan_hdd_gpio_wakeup_init() - Init gpio wakeup
* @hdd_ctx: pointer to the struct hdd_context
*
* Init gpio wakeup
*
* Return: success or not
*/
int wlan_hdd_gpio_wakeup_init(struct hdd_context *hdd_ctx);
/**
* wlan_hdd_gpio_wakeup_deinit() - Deinit gpio wakeup
* @hdd_ctx: pointer to the struct hdd_context
*
* Deinit gpio wakeup
*
* Return: success or not
*/
int wlan_hdd_gpio_wakeup_deinit(struct hdd_context *hdd_ctx);
#else
static inline int wlan_hdd_gpio_wakeup_init(struct hdd_context *hdd_ctx)
{
return 0;
}
static inline int wlan_hdd_gpio_wakeup_deinit(struct hdd_context *hdd_ctx)
{
return 0;
}
#endif
#endif

View File

@@ -0,0 +1,142 @@
/*
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "wlan_hdd_main.h"
#include <linux/gpio.h>
#include "wlan_hdd_gpio_wakeup.h"
static int32_t gpio_wakeup_irq_num = -1;
static uint32_t
hdd_gpio_wakeup_mode_pmo_to_linux(enum pmo_gpio_wakeup_mode mode)
{
uint32_t irq_flag;
switch (mode) {
case PMO_GPIO_WAKEUP_MODE_RISING:
irq_flag = IRQF_TRIGGER_RISING;
break;
case PMO_GPIO_WAKEUP_MODE_FALLING:
irq_flag = IRQF_TRIGGER_FALLING;
break;
case PMO_GPIO_WAKEUP_MODE_HIGH:
irq_flag = IRQF_TRIGGER_HIGH;
break;
case PMO_GPIO_WAKEUP_MODE_LOW:
irq_flag = IRQF_TRIGGER_LOW;
break;
default:
irq_flag = IRQF_TRIGGER_NONE;
break;
}
return irq_flag;
}
static irqreturn_t hdd_gpio_wakeup_isr(int irq, void *dev)
{
hdd_debug("gpio_wakeup_isr");
return IRQ_HANDLED;
}
int wlan_hdd_gpio_wakeup_init(struct hdd_context *hdd_ctx)
{
uint32_t gpio_wakeup_pin;
enum pmo_gpio_wakeup_mode gpio_wakeup_mode;
int32_t ret;
uint32_t irq_flag;
if (!ucfg_pmo_is_gpio_wakeup_enabled(hdd_ctx->psoc)) {
hdd_debug("gpio wakeup is not enabled");
return 0;
}
gpio_wakeup_pin = ucfg_pmo_get_gpio_wakeup_pin(hdd_ctx->psoc);
ret = gpio_request(gpio_wakeup_pin, "gpio_wakeup");
if (ret) {
hdd_err("failed to request gpio%d", gpio_wakeup_pin);
return -EIO;
}
ret = gpio_direction_input(gpio_wakeup_pin);
if (ret) {
hdd_err("failed to set input direction");
goto fail_free_gpio;
}
gpio_wakeup_irq_num = gpio_to_irq(gpio_wakeup_pin);
if (gpio_wakeup_irq_num < 0) {
hdd_err("failed to get irq num");
goto fail_free_gpio;
}
gpio_wakeup_mode = ucfg_pmo_get_gpio_wakeup_mode(hdd_ctx->psoc);
if (gpio_wakeup_mode == PMO_GPIO_WAKEUP_MODE_INVALID) {
hdd_err("failed to get invalid wakeup mode");
goto fail_free_gpio;
}
irq_flag = hdd_gpio_wakeup_mode_pmo_to_linux(gpio_wakeup_mode);
ret = request_irq(gpio_wakeup_irq_num, hdd_gpio_wakeup_isr, irq_flag,
"gpio_wakeup_irq", hdd_ctx);
if (ret) {
hdd_err("failed to request irq %d", ret);
goto fail_free_gpio;
}
ret = enable_irq_wake(gpio_wakeup_irq_num);
if (ret) {
hdd_err("failed to enable irq wake %d", ret);
goto fail_free_irq;
}
hdd_debug("succeed to set gpio wakeup");
return 0;
fail_free_irq:
free_irq(gpio_wakeup_irq_num, hdd_ctx);
gpio_wakeup_irq_num = -1;
fail_free_gpio:
gpio_free(gpio_wakeup_pin);
return -EIO;
}
int wlan_hdd_gpio_wakeup_deinit(struct hdd_context *hdd_ctx)
{
uint32_t gpio_wakeup_pin;
if (!ucfg_pmo_is_gpio_wakeup_enabled(hdd_ctx->psoc)) {
hdd_debug("gpio wakeup is not enabled");
return 0;
}
if (gpio_wakeup_irq_num < 0) {
hdd_debug("gpio wakeup irq is not enabled");
return 0;
}
free_irq(gpio_wakeup_irq_num, hdd_ctx);
gpio_wakeup_irq_num = -1;
gpio_wakeup_pin = ucfg_pmo_get_gpio_wakeup_pin(hdd_ctx->psoc);
gpio_free(gpio_wakeup_pin);
return 0;
}

View File

@@ -197,6 +197,7 @@
#include "qdf_lock.h"
#include "wlan_hdd_thermal.h"
#include "osif_cm_util.h"
#include "wlan_hdd_gpio_wakeup.h"
#ifdef MODULE
#define WLAN_MODULE_NAME module_name(THIS_MODULE)
@@ -13489,6 +13490,7 @@ static int hdd_features_init(struct hdd_context *hdd_ctx)
wlan_hdd_init_chan_info(hdd_ctx);
wlan_hdd_twt_init(hdd_ctx);
wlan_hdd_gpio_wakeup_init(hdd_ctx);
hdd_exit();
return 0;
@@ -13504,6 +13506,7 @@ static int hdd_features_init(struct hdd_context *hdd_ctx)
*/
static void hdd_features_deinit(struct hdd_context *hdd_ctx)
{
wlan_hdd_gpio_wakeup_deinit(hdd_ctx);
wlan_hdd_twt_deinit(hdd_ctx);
wlan_hdd_deinit_chan_info(hdd_ctx);
wlan_hdd_tsf_deinit(hdd_ctx);