From fb3b78d7d2b5934d934edd85dc4dcabf9585f3ee Mon Sep 17 00:00:00 2001 From: Yue Ma Date: Wed, 8 Aug 2018 11:51:21 -0700 Subject: [PATCH] qcacld-3.0: Add force wake APIs support in PLD As part of PCIe power management for new WLAN devices, it requires asserting WAKE register before accessing any MMIO registers outside first 4K range. Add the APIs support in PLD for WLAN host driver. Change-Id: I307cc6688fca58a52a6eaf3982d675c7a85a6965 CRs-fixed: 2326459 --- core/pld/inc/pld_common.h | 4 +- core/pld/src/pld_common.c | 88 +++++++++++++++++++++++++++++++++++++++ core/pld/src/pld_pcie.h | 30 +++++++++++++ 3 files changed, 121 insertions(+), 1 deletion(-) diff --git a/core/pld/inc/pld_common.h b/core/pld/inc/pld_common.h index 7dab6cb5f907..c2ed1b5ac7a9 100644 --- a/core/pld/inc/pld_common.h +++ b/core/pld/inc/pld_common.h @@ -513,7 +513,9 @@ int pld_get_sha_hash(struct device *dev, const u8 *data, void *pld_get_fw_ptr(struct device *dev); int pld_auto_suspend(struct device *dev); int pld_auto_resume(struct device *dev); - +int pld_force_wake_request(struct device *dev); +int pld_is_device_awake(struct device *dev); +int pld_force_wake_release(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); diff --git a/core/pld/src/pld_common.c b/core/pld/src/pld_common.c index e4b4b60efda9..a2b29724ef85 100644 --- a/core/pld/src/pld_common.c +++ b/core/pld/src/pld_common.c @@ -895,6 +895,94 @@ int pld_auto_resume(struct device *dev) return ret; } +/** + * pld_force_wake_request() - Request vote to assert WAKE register + * @dev: device + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_force_wake_request(struct device *dev) +{ + int ret = 0; + enum pld_bus_type type = pld_get_bus_type(dev); + + switch (type) { + case PLD_BUS_TYPE_PCIE: + ret = pld_pcie_force_wake_request(dev); + break; + case PLD_BUS_TYPE_SNOC: + case PLD_BUS_TYPE_SDIO: + case PLD_BUS_TYPE_USB: + break; + default: + pr_err("Invalid device type %d\n", type); + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * pld_is_device_awake() - Check if it's ready to access MMIO registers + * @dev: device + * + * Return: True for device awake + * False for device not awake + * Negative failure code for errors + */ +int pld_is_device_awake(struct device *dev) +{ + int ret = true; + enum pld_bus_type type = pld_get_bus_type(dev); + + switch (type) { + case PLD_BUS_TYPE_PCIE: + ret = pld_pcie_is_device_awake(dev); + break; + case PLD_BUS_TYPE_SNOC: + case PLD_BUS_TYPE_SDIO: + case PLD_BUS_TYPE_USB: + break; + default: + pr_err("Invalid device type %d\n", type); + ret = -EINVAL; + break; + } + + return ret; +} + +/** + * pld_force_wake_release() - Release vote to assert WAKE register + * @dev: device + * + * Return: 0 for success + * Non zero failure code for errors + */ +int pld_force_wake_release(struct device *dev) +{ + int ret = 0; + enum pld_bus_type type = pld_get_bus_type(dev); + + switch (type) { + case PLD_BUS_TYPE_PCIE: + ret = pld_pcie_force_wake_release(dev); + break; + case PLD_BUS_TYPE_SNOC: + case PLD_BUS_TYPE_SDIO: + case PLD_BUS_TYPE_USB: + break; + default: + pr_err("Invalid device type %d\n", type); + ret = -EINVAL; + break; + } + + return ret; +} + /** * pld_ce_request_irq() - Register IRQ for CE * @dev: device diff --git a/core/pld/src/pld_pcie.h b/core/pld/src/pld_pcie.h index d6263d55a1ca..6d5a4ab3b534 100644 --- a/core/pld/src/pld_pcie.h +++ b/core/pld/src/pld_pcie.h @@ -216,6 +216,21 @@ static inline int pld_pcie_auto_resume(struct device *dev) return 0; } +static inline int pld_pcie_force_wake_request(struct device *dev) +{ + return 0; +} + +static inline int pld_pcie_is_device_awake(struct device *dev) +{ + return true; +} + +static inline int pld_pcie_force_wake_release(struct device *dev) +{ + return 0; +} + static inline void pld_pcie_lock_pm_sem(struct device *dev) { } @@ -331,6 +346,21 @@ static inline int pld_pcie_auto_resume(struct device *dev) return cnss_auto_resume(dev); } +static inline int pld_pcie_force_wake_request(struct device *dev) +{ + return cnss_pci_force_wake_request(dev); +} + +static inline int pld_pcie_is_device_awake(struct device *dev) +{ + return cnss_pci_is_device_awake(dev); +} + +static inline int pld_pcie_force_wake_release(struct device *dev) +{ + return cnss_pci_force_wake_release(dev); +} + static inline void pld_pcie_lock_pm_sem(struct device *dev) { cnss_lock_pm_sem(dev);