mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-07 04:12:04 -04:00
msm: pcie: add support to manage PCIe PHY PLL block
Some chipsets require PCIe root complex driver to manually control PCIe PHY PLL block. Add support to power on PCIe PHY PLL block if it has been manually powered down. Change-Id: Iee2b7e9fd80e537a0b2983827261297c8642a3b7 Signed-off-by: Tony Truong <truong@codeaurora.org>
This commit is contained in:
parent
53e78f9f25
commit
3d5f6ea3f4
1 changed files with 104 additions and 14 deletions
|
|
@ -160,6 +160,8 @@
|
|||
|
||||
#define IPC_TIMEOUT_MS (250)
|
||||
|
||||
#define PHY_C_READY (BIT(0))
|
||||
|
||||
#define PHY_READY_TIMEOUT_COUNT (10)
|
||||
#define XMLH_LINK_UP (0x400)
|
||||
#define MAX_PROP_SIZE (32)
|
||||
|
|
@ -608,20 +610,6 @@ struct __packed msm_pcie_drv_msg {
|
|||
struct msm_pcie_drv_tre pkt;
|
||||
};
|
||||
|
||||
struct msm_pcie_drv_info {
|
||||
bool ep_connected; /* drv supports only one endpoint (no switch) */
|
||||
struct msm_pcie_drv_msg drv_enable; /* hand off payload */
|
||||
struct msm_pcie_drv_msg drv_disable; /* payload to request back */
|
||||
struct msm_pcie_drv_msg drv_enable_l1ss_sleep; /* enable l1ss sleep */
|
||||
struct msm_pcie_drv_msg drv_disable_l1ss_sleep; /* disable l1ss sleep */
|
||||
int dev_id;
|
||||
u16 seq;
|
||||
u16 reply_seq;
|
||||
u32 timeout_ms; /* IPC command timeout */
|
||||
u32 l1ss_timeout_us;
|
||||
struct completion completion;
|
||||
};
|
||||
|
||||
/* msm pcie device structure */
|
||||
struct msm_pcie_dev_t {
|
||||
struct platform_device *pdev;
|
||||
|
|
@ -766,6 +754,27 @@ struct msm_root_dev_t {
|
|||
struct pci_dev *pci_dev;
|
||||
};
|
||||
|
||||
struct msm_pcie_drv_info {
|
||||
bool ep_connected; /* drv supports only one endpoint (no switch) */
|
||||
struct msm_pcie_drv_msg drv_enable; /* hand off payload */
|
||||
struct msm_pcie_drv_msg drv_disable; /* payload to request back */
|
||||
struct msm_pcie_drv_msg drv_enable_l1ss_sleep; /* enable l1ss sleep */
|
||||
struct msm_pcie_drv_msg drv_disable_l1ss_sleep; /* disable l1ss sleep */
|
||||
int dev_id;
|
||||
u16 seq;
|
||||
u16 reply_seq;
|
||||
u32 timeout_ms; /* IPC command timeout */
|
||||
u32 l1ss_timeout_us;
|
||||
struct completion completion;
|
||||
|
||||
/* for DRV SSR */
|
||||
void (*manage_pll_power_on)(struct msm_pcie_dev_t *pcie_dev,
|
||||
struct msm_pcie_drv_info *drv_info);
|
||||
u32 phy_resetsm_cntrl2;
|
||||
u32 phy_core_pll_en_mux;
|
||||
u32 phy_c_ready_status;
|
||||
};
|
||||
|
||||
static u32 msm_pcie_keep_resources_on;
|
||||
|
||||
/* debugfs values */
|
||||
|
|
@ -5552,6 +5561,74 @@ static void msm_pcie_check_l1ss_support_all(struct msm_pcie_dev_t *dev)
|
|||
pci_walk_bus(dev->dev->bus, msm_pcie_check_l1ss_support, dev);
|
||||
}
|
||||
|
||||
static void msm_pcie_drv_manage_pll_power_on(struct msm_pcie_dev_t *pcie_dev,
|
||||
struct msm_pcie_drv_info *drv_info)
|
||||
{
|
||||
u32 cnt = 0;
|
||||
u32 cnt_max = 20; /* 1ms */
|
||||
|
||||
PCIE_DBG(pcie_dev, "PCIe: RC%d: manually power on PHY PLL\n",
|
||||
pcie_dev->rc_idx);
|
||||
|
||||
msm_pcie_write_mask(pcie_dev->phy + drv_info->phy_resetsm_cntrl2,
|
||||
BIT(drv_info->phy_core_pll_en_mux), 0);
|
||||
|
||||
while (!(readl_relaxed(pcie_dev->phy + drv_info->phy_c_ready_status) &
|
||||
PHY_C_READY)) {
|
||||
if (unlikely(cnt++ >= cnt_max)) {
|
||||
PCIE_ERR(pcie_dev,
|
||||
"PCIe: RC%d: failed to manually power on PHY PLL\n",
|
||||
pcie_dev->rc_idx);
|
||||
return;
|
||||
}
|
||||
|
||||
usleep_range(50, 55);
|
||||
}
|
||||
|
||||
PCIE_DBG(pcie_dev, "PCIe: RC%d: successfully powered on PHY PLL\n",
|
||||
pcie_dev->rc_idx);
|
||||
}
|
||||
|
||||
static int msm_pcie_setup_drv_manage_pll(struct msm_pcie_dev_t *pcie_dev,
|
||||
struct device_node *of_node,
|
||||
struct msm_pcie_drv_info *drv_info)
|
||||
{
|
||||
int ret;
|
||||
|
||||
PCIE_DBG(pcie_dev, "PCIe: RC%d: enter\n", pcie_dev->rc_idx);
|
||||
|
||||
ret = of_property_read_u32(of_node, "qcom,phy-resetsm-cntrl2",
|
||||
&drv_info->phy_resetsm_cntrl2);
|
||||
if (ret) {
|
||||
PCIE_ERR(pcie_dev,
|
||||
"PCIe: RC%d failed to get qcom,phy-resetsm-cntrl2\n",
|
||||
pcie_dev->rc_idx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(of_node, "qcom,phy-core-pll-en-mux",
|
||||
&drv_info->phy_core_pll_en_mux);
|
||||
if (ret) {
|
||||
PCIE_ERR(pcie_dev,
|
||||
"PCIe: RC%d failed to get qcom,phy-core-pll-en-mux\n",
|
||||
pcie_dev->rc_idx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = of_property_read_u32(of_node, "qcom,phy-c-ready-status",
|
||||
&drv_info->phy_c_ready_status);
|
||||
if (ret) {
|
||||
PCIE_ERR(pcie_dev,
|
||||
"PCIe: RC%d failed to get qcom,phy-c-ready-status\n",
|
||||
pcie_dev->rc_idx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
drv_info->manage_pll_power_on = msm_pcie_drv_manage_pll_power_on;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void msm_pcie_setup_drv_msg(struct msm_pcie_drv_msg *msg, u32 dev_id,
|
||||
enum msm_pcie_drv_cmds cmd)
|
||||
{
|
||||
|
|
@ -5573,6 +5650,7 @@ static int msm_pcie_setup_drv(struct msm_pcie_dev_t *pcie_dev,
|
|||
{
|
||||
struct msm_pcie_drv_info *drv_info;
|
||||
int ret;
|
||||
u32 phy_manage_pll = 0;
|
||||
|
||||
drv_info = devm_kzalloc(&pcie_dev->pdev->dev, sizeof(*drv_info),
|
||||
GFP_KERNEL);
|
||||
|
|
@ -5589,6 +5667,15 @@ static int msm_pcie_setup_drv(struct msm_pcie_dev_t *pcie_dev,
|
|||
|
||||
drv_info->dev_id = pcie_dev->rc_idx;
|
||||
|
||||
ret = of_property_read_u32(of_node, "qcom,phy-manage-pll",
|
||||
&phy_manage_pll);
|
||||
if (!ret && phy_manage_pll) {
|
||||
ret = msm_pcie_setup_drv_manage_pll(pcie_dev, of_node,
|
||||
drv_info);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
msm_pcie_setup_drv_msg(&drv_info->drv_enable, drv_info->dev_id,
|
||||
MSM_PCIE_DRV_CMD_ENABLE);
|
||||
|
||||
|
|
@ -6954,6 +7041,9 @@ static int msm_pcie_drv_resume(struct msm_pcie_dev_t *pcie_dev)
|
|||
clk_prepare_enable(clk_info->hdl);
|
||||
|
||||
if (clkreq_override_en) {
|
||||
if (drv_info->manage_pll_power_on)
|
||||
drv_info->manage_pll_power_on(pcie_dev, drv_info);
|
||||
|
||||
/* remove CLKREQ override */
|
||||
msm_pcie_write_reg_field(pcie_dev->parf,
|
||||
PCIE20_PARF_CLKREQ_OVERRIDE,
|
||||
|
|
|
|||
Loading…
Reference in a new issue