mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 13:49:24 -04:00
cnss2: Use CONFIG_PCI_MSM to protect MSM PCIe APIs
This can ease the complexity to port CNSS2 driver to non-MSM platforms while still be able to maintain the compatibility. Change-Id: I268cdd90c59085b34aa2fe3c3b845d60c4e2a417 Signed-off-by: Yue Ma <yuem@codeaurora.org>
This commit is contained in:
parent
dc0ecaca75
commit
2dc22bc62d
2 changed files with 281 additions and 45 deletions
|
|
@ -370,6 +370,232 @@ static struct cnss_misc_reg wlaon_reg_access_seq[] = {
|
|||
#define PCIE_REG_SIZE ARRAY_SIZE(pcie_reg_access_seq)
|
||||
#define WLAON_REG_SIZE ARRAY_SIZE(wlaon_reg_access_seq)
|
||||
|
||||
#if IS_ENABLED(CONFIG_PCI_MSM)
|
||||
/**
|
||||
* cnss_pci_enumerate() - Enumerate PCIe endpoints
|
||||
* @plat_priv: driver platform context pointer
|
||||
* @rc_num: root complex index that an endpoint connects to
|
||||
*
|
||||
* This function shall call corresponding PCIe root complex driver APIs
|
||||
* to power on root complex and enumerate the endpoint connected to it.
|
||||
*
|
||||
* Return: 0 for success, negative value for error
|
||||
*/
|
||||
static int cnss_pci_enumerate(struct cnss_plat_data *plat_priv, int rc_num)
|
||||
{
|
||||
return msm_pcie_enumerate(rc_num);
|
||||
}
|
||||
|
||||
/**
|
||||
* cnss_pci_assert_perst() - Assert PCIe PERST GPIO
|
||||
* @pci_priv: driver PCI bus context pointer
|
||||
*
|
||||
* This function shall call corresponding PCIe root complex driver APIs
|
||||
* to assert PCIe PERST GPIO.
|
||||
*
|
||||
* Return: 0 for success, negative value for error
|
||||
*/
|
||||
static int cnss_pci_assert_perst(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
struct pci_dev *pci_dev = pci_priv->pci_dev;
|
||||
|
||||
return msm_pcie_pm_control(MSM_PCIE_HANDLE_LINKDOWN,
|
||||
pci_dev->bus->number, pci_dev, NULL,
|
||||
PM_OPTIONS_DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* cnss_pci_disable_pc() - Disable PCIe link power collapse from RC driver
|
||||
* @pci_priv: driver PCI bus context pointer
|
||||
* @vote: value to indicate disable (true) or enable (false)
|
||||
*
|
||||
* This function shall call corresponding PCIe root complex driver APIs
|
||||
* to disable PCIe power collapse. The purpose of this API is to avoid
|
||||
* root complex driver still controlling PCIe link from callbacks of
|
||||
* system suspend/resume. Device driver itself should take full control
|
||||
* of the link in such cases.
|
||||
*
|
||||
* Return: 0 for success, negative value for error
|
||||
*/
|
||||
static int cnss_pci_disable_pc(struct cnss_pci_data *pci_priv, bool vote)
|
||||
{
|
||||
struct pci_dev *pci_dev = pci_priv->pci_dev;
|
||||
|
||||
return msm_pcie_pm_control(vote ? MSM_PCIE_DISABLE_PC :
|
||||
MSM_PCIE_ENABLE_PC,
|
||||
pci_dev->bus->number, pci_dev, NULL,
|
||||
PM_OPTIONS_DEFAULT);
|
||||
}
|
||||
|
||||
/**
|
||||
* cnss_pci_set_link_bandwidth() - Update number of lanes and speed of
|
||||
* PCIe link
|
||||
* @pci_priv: driver PCI bus context pointer
|
||||
* @link_speed: PCIe link gen speed
|
||||
* @link_width: number of lanes for PCIe link
|
||||
*
|
||||
* This function shall call corresponding PCIe root complex driver APIs
|
||||
* to update number of lanes and speed of the link.
|
||||
*
|
||||
* Return: 0 for success, negative value for error
|
||||
*/
|
||||
static int cnss_pci_set_link_bandwidth(struct cnss_pci_data *pci_priv,
|
||||
u16 link_speed, u16 link_width)
|
||||
{
|
||||
return msm_pcie_set_link_bandwidth(pci_priv->pci_dev,
|
||||
link_speed, link_width);
|
||||
}
|
||||
|
||||
/**
|
||||
* cnss_pci_set_max_link_speed() - Set the maximum speed PCIe can link up with
|
||||
* @pci_priv: driver PCI bus context pointer
|
||||
* @rc_num: root complex index that an endpoint connects to
|
||||
* @link_speed: PCIe link gen speed
|
||||
*
|
||||
* This function shall call corresponding PCIe root complex driver APIs
|
||||
* to update the maximum speed that PCIe can link up with.
|
||||
*
|
||||
* Return: 0 for success, negative value for error
|
||||
*/
|
||||
static int cnss_pci_set_max_link_speed(struct cnss_pci_data *pci_priv,
|
||||
u32 rc_num, u16 link_speed)
|
||||
{
|
||||
return msm_pcie_set_target_link_speed(rc_num, link_speed);
|
||||
}
|
||||
|
||||
/**
|
||||
* _cnss_pci_prevent_l1() - Prevent PCIe L1 and L1 sub-states
|
||||
* @pci_priv: driver PCI bus context pointer
|
||||
*
|
||||
* This function shall call corresponding PCIe root complex driver APIs
|
||||
* to prevent PCIe link enter L1 and L1 sub-states. The APIs should also
|
||||
* bring link out of L1 or L1 sub-states if any and avoid synchronization
|
||||
* issues if any.
|
||||
*
|
||||
* Return: 0 for success, negative value for error
|
||||
*/
|
||||
static int _cnss_pci_prevent_l1(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
return msm_pcie_prevent_l1(pci_priv->pci_dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* _cnss_pci_allow_l1() - Allow PCIe L1 and L1 sub-states
|
||||
* @pci_priv: driver PCI bus context pointer
|
||||
*
|
||||
* This function shall call corresponding PCIe root complex driver APIs
|
||||
* to allow PCIe link enter L1 and L1 sub-states. The APIs should avoid
|
||||
* synchronization issues if any.
|
||||
*
|
||||
* Return: 0 for success, negative value for error
|
||||
*/
|
||||
static void _cnss_pci_allow_l1(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
msm_pcie_allow_l1(pci_priv->pci_dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* cnss_pci_set_link_up() - Power on or resume PCIe link
|
||||
* @pci_priv: driver PCI bus context pointer
|
||||
*
|
||||
* This function shall call corresponding PCIe root complex driver APIs
|
||||
* to Power on or resume PCIe link.
|
||||
*
|
||||
* Return: 0 for success, negative value for error
|
||||
*/
|
||||
static int cnss_pci_set_link_up(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
struct pci_dev *pci_dev = pci_priv->pci_dev;
|
||||
enum msm_pcie_pm_opt pm_ops = MSM_PCIE_RESUME;
|
||||
u32 pm_options = PM_OPTIONS_DEFAULT;
|
||||
int ret;
|
||||
|
||||
ret = msm_pcie_pm_control(pm_ops, pci_dev->bus->number, pci_dev,
|
||||
NULL, pm_options);
|
||||
if (ret)
|
||||
cnss_pr_err("Failed to resume PCI link with default option, err = %d\n",
|
||||
ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* cnss_pci_set_link_down() - Power off or suspend PCIe link
|
||||
* @pci_priv: driver PCI bus context pointer
|
||||
*
|
||||
* This function shall call corresponding PCIe root complex driver APIs
|
||||
* to power off or suspend PCIe link.
|
||||
*
|
||||
* Return: 0 for success, negative value for error
|
||||
*/
|
||||
static int cnss_pci_set_link_down(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
struct pci_dev *pci_dev = pci_priv->pci_dev;
|
||||
enum msm_pcie_pm_opt pm_ops;
|
||||
u32 pm_options = PM_OPTIONS_DEFAULT;
|
||||
int ret;
|
||||
|
||||
if (pci_priv->drv_connected_last) {
|
||||
cnss_pr_vdbg("Use PCIe DRV suspend\n");
|
||||
pm_ops = MSM_PCIE_DRV_SUSPEND;
|
||||
} else {
|
||||
pm_ops = MSM_PCIE_SUSPEND;
|
||||
}
|
||||
|
||||
ret = msm_pcie_pm_control(pm_ops, pci_dev->bus->number, pci_dev,
|
||||
NULL, pm_options);
|
||||
if (ret)
|
||||
cnss_pr_err("Failed to suspend PCI link with default option, err = %d\n",
|
||||
ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
static int cnss_pci_enumerate(struct cnss_plat_data *plat_priv, int rc_num)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int cnss_pci_assert_perst(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static int cnss_pci_disable_pc(struct cnss_pci_data *pci_priv, bool vote)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cnss_pci_set_link_bandwidth(struct cnss_pci_data *pci_priv,
|
||||
u16 link_speed, u16 link_width)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cnss_pci_set_max_link_speed(struct cnss_pci_data *pci_priv,
|
||||
u32 rc_num, u16 link_speed)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _cnss_pci_prevent_l1(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _cnss_pci_allow_l1(struct cnss_pci_data *pci_priv) {}
|
||||
|
||||
static int cnss_pci_set_link_up(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cnss_pci_set_link_down(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_PCI_MSM */
|
||||
|
||||
int cnss_pci_check_link_status(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
u16 device_id;
|
||||
|
|
@ -738,8 +964,7 @@ static int cnss_set_pci_link_status(struct cnss_pci_data *pci_priv,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = msm_pcie_set_link_bandwidth(pci_priv->pci_dev,
|
||||
link_speed, link_width);
|
||||
ret = cnss_pci_set_link_bandwidth(pci_priv, link_speed, link_width);
|
||||
if (!ret)
|
||||
pci_priv->cur_link_speed = link_speed;
|
||||
|
||||
|
|
@ -748,43 +973,28 @@ static int cnss_set_pci_link_status(struct cnss_pci_data *pci_priv,
|
|||
|
||||
static int cnss_set_pci_link(struct cnss_pci_data *pci_priv, bool link_up)
|
||||
{
|
||||
int ret = 0;
|
||||
struct pci_dev *pci_dev = pci_priv->pci_dev;
|
||||
enum msm_pcie_pm_opt pm_ops;
|
||||
int retry = 0;
|
||||
u32 pm_options = PM_OPTIONS_DEFAULT;
|
||||
int ret = 0, retry = 0;
|
||||
|
||||
cnss_pr_vdbg("%s PCI link\n", link_up ? "Resuming" : "Suspending");
|
||||
|
||||
if (link_up) {
|
||||
pm_ops = MSM_PCIE_RESUME;
|
||||
} else {
|
||||
if (pci_priv->drv_connected_last) {
|
||||
cnss_pr_vdbg("Use PCIe DRV suspend\n");
|
||||
pm_ops = MSM_PCIE_DRV_SUSPEND;
|
||||
/* Since DRV suspend cannot be done in Gen 3, set it to
|
||||
* Gen 2 if current link speed is larger than Gen 2.
|
||||
*/
|
||||
if (pci_priv->cur_link_speed >
|
||||
PCI_EXP_LNKSTA_CLS_5_0GB)
|
||||
cnss_set_pci_link_status(pci_priv, PCI_GEN2);
|
||||
} else {
|
||||
pm_ops = MSM_PCIE_SUSPEND;
|
||||
}
|
||||
}
|
||||
|
||||
retry:
|
||||
ret = msm_pcie_pm_control(pm_ops, pci_dev->bus->number, pci_dev,
|
||||
NULL, pm_options);
|
||||
if (ret) {
|
||||
cnss_pr_err("Failed to %s PCI link with default option, err = %d\n",
|
||||
link_up ? "resume" : "suspend", ret);
|
||||
if (link_up && retry++ < LINK_TRAINING_RETRY_MAX_TIMES) {
|
||||
ret = cnss_pci_set_link_up(pci_priv);
|
||||
if (ret && retry++ < LINK_TRAINING_RETRY_MAX_TIMES) {
|
||||
cnss_pr_dbg("Retry PCI link training #%d\n", retry);
|
||||
if (pci_priv->pci_link_down_ind)
|
||||
msleep(LINK_TRAINING_RETRY_DELAY_MS * retry);
|
||||
goto retry;
|
||||
}
|
||||
} else {
|
||||
/* Since DRV suspend cannot be done in Gen 3, set it to
|
||||
* Gen 2 if current link speed is larger than Gen 2.
|
||||
*/
|
||||
if (pci_priv->drv_connected_last &&
|
||||
pci_priv->cur_link_speed > PCI_EXP_LNKSTA_CLS_5_0GB)
|
||||
cnss_set_pci_link_status(pci_priv, PCI_GEN2);
|
||||
|
||||
ret = cnss_pci_set_link_down(pci_priv);
|
||||
}
|
||||
|
||||
if (pci_priv->drv_connected_last) {
|
||||
|
|
@ -939,7 +1149,7 @@ int cnss_pci_prevent_l1(struct device *dev)
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
ret = msm_pcie_prevent_l1(pci_dev);
|
||||
ret = _cnss_pci_prevent_l1(pci_priv);
|
||||
if (ret == -EIO) {
|
||||
cnss_pr_err("Failed to prevent PCIe L1, considered as link down\n");
|
||||
cnss_pci_link_down(dev);
|
||||
|
|
@ -969,7 +1179,7 @@ void cnss_pci_allow_l1(struct device *dev)
|
|||
return;
|
||||
}
|
||||
|
||||
msm_pcie_allow_l1(pci_dev);
|
||||
_cnss_pci_allow_l1(pci_priv);
|
||||
}
|
||||
EXPORT_SYMBOL(cnss_pci_allow_l1);
|
||||
|
||||
|
|
@ -1026,9 +1236,7 @@ int cnss_pci_link_down(struct device *dev)
|
|||
|
||||
cnss_pr_err("PCI link down is detected by drivers\n");
|
||||
|
||||
ret = msm_pcie_pm_control(MSM_PCIE_HANDLE_LINKDOWN,
|
||||
pci_dev->bus->number, pci_dev, NULL,
|
||||
PM_OPTIONS_DEFAULT);
|
||||
ret = cnss_pci_assert_perst(pci_priv);
|
||||
if (ret)
|
||||
cnss_pci_handle_linkdown(pci_priv);
|
||||
|
||||
|
|
@ -1461,6 +1669,7 @@ out:
|
|||
return ret;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_PCI_MSM)
|
||||
/**
|
||||
* cnss_wlan_adsp_pc_enable: Control ADSP power collapse setup
|
||||
* @dev: Platform driver pci private data structure
|
||||
|
|
@ -1494,6 +1703,13 @@ static int cnss_wlan_adsp_pc_enable(struct cnss_pci_data *pci_priv,
|
|||
cnss_pr_dbg("%s ADSP power collapse\n", control ? "Enable" : "Disable");
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static int cnss_wlan_adsp_pc_enable(struct cnss_pci_data *pci_priv,
|
||||
bool control)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int cnss_pci_start_mhi(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
|
|
@ -2615,6 +2831,7 @@ int cnss_pci_unregister_driver_hdlr(struct cnss_pci_data *pci_priv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#if IS_ENABLED(CONFIG_PCI_MSM)
|
||||
static bool cnss_pci_is_drv_supported(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
struct pci_dev *root_port = pci_find_pcie_root_port(pci_priv->pci_dev);
|
||||
|
|
@ -2691,6 +2908,16 @@ static void cnss_pci_event_cb(struct msm_pcie_notify *notify)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* cnss_reg_pci_event() - Register for PCIe events
|
||||
* @pci_priv: driver PCI bus context pointer
|
||||
*
|
||||
* This function shall call corresponding PCIe root complex driver APIs
|
||||
* to register for PCIe events like link down or WAKE GPIO toggling etc.
|
||||
* The events should be based on PCIe root complex driver's capability.
|
||||
*
|
||||
* Return: 0 for success, negative value for error
|
||||
*/
|
||||
static int cnss_reg_pci_event(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
int ret = 0;
|
||||
|
|
@ -2722,6 +2949,14 @@ static void cnss_dereg_pci_event(struct cnss_pci_data *pci_priv)
|
|||
{
|
||||
msm_pcie_deregister_event(&pci_priv->msm_pci_event);
|
||||
}
|
||||
#else
|
||||
static int cnss_reg_pci_event(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cnss_dereg_pci_event(struct cnss_pci_data *pci_priv) {}
|
||||
#endif
|
||||
|
||||
static int cnss_pci_suspend_driver(struct cnss_pci_data *pci_priv)
|
||||
{
|
||||
|
|
@ -3081,10 +3316,7 @@ int cnss_wlan_pm_control(struct device *dev, bool vote)
|
|||
if (!pci_priv)
|
||||
return -ENODEV;
|
||||
|
||||
ret = msm_pcie_pm_control(vote ? MSM_PCIE_DISABLE_PC :
|
||||
MSM_PCIE_ENABLE_PC,
|
||||
pci_dev->bus->number, pci_dev,
|
||||
NULL, PM_OPTIONS_DEFAULT);
|
||||
ret = cnss_pci_disable_pc(pci_priv, vote);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
|
|
@ -4907,13 +5139,13 @@ static int cnss_mhi_bw_scale(struct mhi_controller *mhi_ctrl,
|
|||
* bandwidth getting rejected if requested link speed is higher than
|
||||
* current one.
|
||||
*/
|
||||
ret = msm_pcie_set_target_link_speed(plat_priv->rc_num,
|
||||
link_info->target_link_speed);
|
||||
ret = cnss_pci_set_max_link_speed(pci_priv, plat_priv->rc_num,
|
||||
link_info->target_link_speed);
|
||||
if (ret)
|
||||
cnss_pr_err("Failed to set target link speed to 0x%x, err = %d\n",
|
||||
link_info->target_link_speed, ret);
|
||||
|
||||
ret = msm_pcie_set_link_bandwidth(pci_priv->pci_dev,
|
||||
ret = cnss_pci_set_link_bandwidth(pci_priv,
|
||||
link_info->target_link_speed,
|
||||
link_info->target_link_width);
|
||||
|
||||
|
|
@ -5295,15 +5527,15 @@ int cnss_pci_init(struct cnss_plat_data *plat_priv)
|
|||
* if requested speed is higher than the one specified in PCIe DT.
|
||||
*/
|
||||
if (plat_priv->device_id == QCA6490_DEVICE_ID) {
|
||||
ret = msm_pcie_set_target_link_speed(rc_num,
|
||||
PCI_EXP_LNKSTA_CLS_5_0GB);
|
||||
ret = cnss_pci_set_max_link_speed(plat_priv->bus_priv, rc_num,
|
||||
PCI_EXP_LNKSTA_CLS_5_0GB);
|
||||
if (ret)
|
||||
cnss_pr_err("Failed to set target PCIe link speed to Gen2, err = %d\n",
|
||||
ret);
|
||||
}
|
||||
|
||||
retry:
|
||||
ret = msm_pcie_enumerate(rc_num);
|
||||
ret = cnss_pci_enumerate(plat_priv, rc_num);
|
||||
if (ret) {
|
||||
cnss_pr_err("Failed to enable PCIe RC%x, err = %d\n",
|
||||
rc_num, ret);
|
||||
|
|
|
|||
|
|
@ -1,12 +1,14 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/* Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */
|
||||
/* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */
|
||||
|
||||
#ifndef _CNSS_PCI_H
|
||||
#define _CNSS_PCI_H
|
||||
|
||||
#include <linux/iommu.h>
|
||||
#include <linux/mhi.h>
|
||||
#if IS_ENABLED(CONFIG_PCI_MSM)
|
||||
#include <linux/msm_pcie.h>
|
||||
#endif
|
||||
#include <linux/pci.h>
|
||||
|
||||
#include "main.h"
|
||||
|
|
@ -86,7 +88,9 @@ struct cnss_pci_data {
|
|||
u8 pci_link_down_ind;
|
||||
struct pci_saved_state *saved_state;
|
||||
struct pci_saved_state *default_state;
|
||||
#if IS_ENABLED(CONFIG_PCI_MSM)
|
||||
struct msm_pcie_register_event msm_pci_event;
|
||||
#endif
|
||||
struct cnss_pm_stats pm_stats;
|
||||
atomic_t auto_suspended;
|
||||
atomic_t drv_connected;
|
||||
|
|
|
|||
Loading…
Reference in a new issue