cnss2: Set WLAON_QFPROM_PWR_CTRL_REG during power on and off

After device power on and link config, clear VDD4BLOW_EN bit
of WLAON_QFPROM_PWR_CTRL_REG register to disable OTP write.
Before device link suspend and power off, clear VDD4BLOW_EN bit
and set SHUTDOWN_EN bit. Also add a 1ms sleep after writing
WLAON_QFPROM_PWR_CTRL_REG register.

Add a DTSI entry to control above operations.

Change-Id: Icb307a85bb5d283b78bdd7615f9a4757867c8075
CRs-Fixed: 2601850
Signed-off-by: Yue Ma <yuem@codeaurora.org>
This commit is contained in:
Yue Ma 2020-01-13 15:13:43 +08:00
commit f628a32c05
4 changed files with 87 additions and 5 deletions

View file

@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. */
/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */
#include <linux/delay.h>
#include <linux/jiffies.h>
@ -2070,6 +2070,17 @@ static void cnss_init_control_params(struct cnss_plat_data *plat_priv)
plat_priv->ctrl_params.time_sync_period = CNSS_TIME_SYNC_PERIOD_DEFAULT;
}
static void cnss_get_wlaon_pwr_ctrl_info(struct cnss_plat_data *plat_priv)
{
struct device *dev = &plat_priv->plat_dev->dev;
plat_priv->set_wlaon_pwr_ctrl =
of_property_read_bool(dev->of_node, "qcom,set-wlaon-pwr-ctrl");
cnss_pr_dbg("set_wlaon_pwr_ctrl is %d\n",
plat_priv->set_wlaon_pwr_ctrl);
}
static const struct platform_device_id cnss_platform_id_table[] = {
{ .name = "qca6174", .driver_data = QCA6174_DEVICE_ID, },
{ .name = "qca6290", .driver_data = QCA6290_DEVICE_ID, },
@ -2140,6 +2151,7 @@ static int cnss_probe(struct platform_device *plat_dev)
INIT_LIST_HEAD(&plat_priv->vreg_list);
INIT_LIST_HEAD(&plat_priv->clk_list);
cnss_get_wlaon_pwr_ctrl_info(plat_priv);
cnss_get_cpr_info(plat_priv);
cnss_init_control_params(plat_priv);

View file

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. */
/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */
#ifndef _CNSS_MAIN_H
#define _CNSS_MAIN_H
@ -373,6 +373,7 @@ struct cnss_plat_data {
void *get_info_cb_ctx;
int (*get_info_cb)(void *ctx, void *event, int event_len);
u8 use_nv_mac;
u8 set_wlaon_pwr_ctrl;
};
#ifdef CONFIG_ARCH_QCOM

View file

@ -62,6 +62,9 @@ static DEFINE_SPINLOCK(time_sync_lock);
#define MHI_TIMEOUT_OVERWRITE_MS (plat_priv->ctrl_params.mhi_timeout)
#define MHI_M2_TIMEOUT_MS (plat_priv->ctrl_params.mhi_m2_timeout)
#define WLAON_PWR_CTRL_SHUTDOWN_DELAY_MIN_US 1000
#define WLAON_PWR_CTRL_SHUTDOWN_DELAY_MAX_US 2000
#define FORCE_WAKE_DELAY_MIN_US 4000
#define FORCE_WAKE_DELAY_MAX_US 6000
#define FORCE_WAKE_DELAY_TIMEOUT_US 60000
@ -480,6 +483,7 @@ static int cnss_pci_force_wake_get(struct cnss_pci_data *pci_priv)
if (cnss_pci_is_device_awake(dev) != true) {
cnss_pr_err("Timed out to request force wake\n");
cnss_pci_force_wake_release(dev);
return -ETIMEDOUT;
}
@ -1131,6 +1135,62 @@ static void cnss_pci_deinit_mhi(struct cnss_pci_data *pci_priv)
cnss_pci_set_mhi_state(pci_priv, CNSS_MHI_DEINIT);
}
static void cnss_pci_set_wlaon_pwr_ctrl(struct cnss_pci_data *pci_priv,
bool set_vddd4blow, bool set_shutdown,
bool do_force_wake)
{
struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
int ret;
u32 val;
if (!plat_priv->set_wlaon_pwr_ctrl)
return;
if (do_force_wake)
if (cnss_pci_force_wake_get(pci_priv))
return;
ret = cnss_pci_reg_read(pci_priv, QCA6390_WLAON_QFPROM_PWR_CTRL_REG,
&val);
if (ret) {
cnss_pr_err("Failed to read register offset 0x%x, err = %d\n",
QCA6390_WLAON_QFPROM_PWR_CTRL_REG, ret);
goto force_wake_put;
}
cnss_pr_dbg("Read register offset 0x%x, val = 0x%x\n",
QCA6390_WLAON_QFPROM_PWR_CTRL_REG, val);
if (set_vddd4blow)
val |= QFPROM_PWR_CTRL_VDD4BLOW_SW_EN_MASK;
else
val &= ~QFPROM_PWR_CTRL_VDD4BLOW_SW_EN_MASK;
if (set_shutdown)
val |= QFPROM_PWR_CTRL_SHUTDOWN_EN_MASK;
else
val &= ~QFPROM_PWR_CTRL_SHUTDOWN_EN_MASK;
ret = cnss_pci_reg_write(pci_priv, QCA6390_WLAON_QFPROM_PWR_CTRL_REG,
val);
if (ret) {
cnss_pr_err("Failed to write register offset 0x%x, err = %d\n",
QCA6390_WLAON_QFPROM_PWR_CTRL_REG, ret);
goto force_wake_put;
}
cnss_pr_dbg("Write val 0x%x to register offset 0x%x\n", val,
QCA6390_WLAON_QFPROM_PWR_CTRL_REG);
if (set_shutdown)
usleep_range(WLAON_PWR_CTRL_SHUTDOWN_DELAY_MIN_US,
WLAON_PWR_CTRL_SHUTDOWN_DELAY_MAX_US);
force_wake_put:
if (do_force_wake)
cnss_pci_force_wake_put(pci_priv);
}
static int cnss_pci_get_device_timestamp(struct cnss_pci_data *pci_priv,
u64 *time_us)
{
@ -1671,6 +1731,7 @@ retry:
goto power_off;
}
cnss_pci_set_wlaon_pwr_ctrl(pci_priv, false, false, false);
timeout = cnss_get_boot_timeout(&pci_priv->pci_dev->dev);
ret = cnss_pci_start_mhi(pci_priv);
@ -1705,6 +1766,7 @@ retry:
return 0;
stop_mhi:
cnss_pci_set_wlaon_pwr_ctrl(pci_priv, false, true, true);
cnss_pci_power_off_mhi(pci_priv);
cnss_suspend_pci_link(pci_priv);
cnss_pci_deinit_mhi(pci_priv);
@ -1718,6 +1780,7 @@ static int cnss_qca6290_shutdown(struct cnss_pci_data *pci_priv)
{
int ret = 0;
struct cnss_plat_data *plat_priv = pci_priv->plat_priv;
int do_force_wake = true;
cnss_pci_pm_runtime_resume(pci_priv);
@ -1744,6 +1807,10 @@ static int cnss_qca6290_shutdown(struct cnss_pci_data *pci_priv)
goto skip_power_off;
}
if (test_bit(CNSS_DEV_ERR_NOTIFY, &plat_priv->driver_state))
do_force_wake = false;
cnss_pci_set_wlaon_pwr_ctrl(pci_priv, false, true, do_force_wake);
cnss_pci_power_off_mhi(pci_priv);
ret = cnss_suspend_pci_link(pci_priv);
if (ret)
@ -4113,6 +4180,7 @@ static int cnss_pci_probe(struct pci_dev *pci_dev,
case QCA6290_DEVICE_ID:
case QCA6390_DEVICE_ID:
case QCA6490_DEVICE_ID:
cnss_pci_set_wlaon_pwr_ctrl(pci_priv, false, false, false);
timer_setup(&pci_priv->dev_rddm_timer,
cnss_dev_rddm_timeout_hdlr, 0);
INIT_DELAYED_WORK(&pci_priv->time_sync_work,
@ -4127,11 +4195,10 @@ static int cnss_pci_probe(struct pci_dev *pci_dev,
goto disable_bus;
}
cnss_pci_get_link_status(pci_priv);
cnss_pci_config_regs(pci_priv);
if (EMULATION_HW)
break;
cnss_pci_set_wlaon_pwr_ctrl(pci_priv, false, true, false);
ret = cnss_suspend_pci_link(pci_priv);
if (ret)
cnss_pr_err("Failed to suspend PCI link, err = %d\n",

View file

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Copyright (c) 2019, The Linux Foundation. All rights reserved. */
/* Copyright (c) 2019-2020, The Linux Foundation. All rights reserved. */
#ifndef _CNSS_REG_H
#define _CNSS_REG_H
@ -204,6 +204,8 @@
#define QCA6390_WLAON_WL_CLK_CNTL_KDF_REG 0x1F80314
#define QCA6390_WLAON_WL_CLK_CNTL_PMU_HFRC_REG 0x1F80318
#define QCA6390_WLAON_QFPROM_PWR_CTRL_REG 0x1F8031C
#define QFPROM_PWR_CTRL_VDD4BLOW_SW_EN_MASK 0x4
#define QFPROM_PWR_CTRL_SHUTDOWN_EN_MASK 0x1
#define QCA6390_WLAON_DLY_CONFIG 0x1F80400
#define QCA6390_WLAON_WLAON_Q6_IRQ_REG 0x1F80404
#define QCA6390_WLAON_PCIE_INTF_SW_CFG_REG 0x1F80408