msm: pcie: aggregate PCIe rate change clock vote
PCIe rate change clock is shared among all PCIe ports. Based on use case, each PCIe will vote for either 19.2MHz or 100HMz. Only the last vote counts. Therefore, add support to aggregate all votes and set the clock rate to meet all PCIe requirements. Change-Id: Iaf6aa0ef667e4f89ce8653ed6958c76367d2dd2a Signed-off-by: Tony Truong <truong@codeaurora.org>
This commit is contained in:
@@ -668,6 +668,7 @@ struct msm_pcie_dev_t {
|
||||
unsigned long irqsave_flags;
|
||||
struct mutex enumerate_lock;
|
||||
struct mutex setup_lock;
|
||||
struct mutex clk_lock;
|
||||
|
||||
struct irq_domain *irq_domain;
|
||||
DECLARE_BITMAP(msi_irq_in_use, PCIE_MSI_NR_IRQS);
|
||||
@@ -836,6 +837,7 @@ static struct pcie_drv_sta {
|
||||
struct msm_pcie_dev_t *msm_pcie_dev;
|
||||
struct rpmsg_device *rpdev;
|
||||
struct work_struct drv_connect; /* connect worker */
|
||||
u32 rate_change_vote; /* each bit corresponds to RC vote for 100MHz */
|
||||
struct mutex drv_lock;
|
||||
} pcie_drv;
|
||||
|
||||
@@ -3171,6 +3173,12 @@ static int msm_pcie_clk_init(struct msm_pcie_dev_t *dev)
|
||||
msm_pcie_config_clock_mem(dev, info);
|
||||
|
||||
if (info->freq) {
|
||||
if (!strcmp(info->name, "pcie_phy_refgen_clk")) {
|
||||
mutex_lock(&dev->clk_lock);
|
||||
pcie_drv.rate_change_vote |= BIT(dev->rc_idx);
|
||||
mutex_unlock(&dev->clk_lock);
|
||||
}
|
||||
|
||||
rc = clk_set_rate(info->hdl, info->freq);
|
||||
if (rc) {
|
||||
PCIE_ERR(dev,
|
||||
@@ -3251,6 +3259,17 @@ static void msm_pcie_clk_deinit(struct msm_pcie_dev_t *dev)
|
||||
if (dev->clk[i].hdl)
|
||||
clk_disable_unprepare(dev->clk[i].hdl);
|
||||
|
||||
if (dev->rate_change_clk) {
|
||||
mutex_lock(&dev->clk_lock);
|
||||
|
||||
pcie_drv.rate_change_vote &= ~BIT(dev->rc_idx);
|
||||
if (!pcie_drv.rate_change_vote)
|
||||
clk_set_rate(dev->rate_change_clk->hdl,
|
||||
RATE_CHANGE_19P2MHZ);
|
||||
|
||||
mutex_unlock(&dev->clk_lock);
|
||||
}
|
||||
|
||||
if (dev->bus_client) {
|
||||
PCIE_DBG(dev, "PCIe: removing bus vote for RC%d\n",
|
||||
dev->rc_idx);
|
||||
@@ -6253,9 +6272,15 @@ int msm_pcie_set_link_bandwidth(struct pci_dev *pci_dev, u16 target_link_speed,
|
||||
RPMH_REGULATOR_LEVEL_NOM,
|
||||
pcie_dev->cx_vreg->max_v);
|
||||
|
||||
if (pcie_dev->rate_change_clk)
|
||||
if (pcie_dev->rate_change_clk) {
|
||||
mutex_lock(&pcie_dev->clk_lock);
|
||||
|
||||
pcie_drv.rate_change_vote |= BIT(pcie_dev->rc_idx);
|
||||
clk_set_rate(pcie_dev->rate_change_clk->hdl,
|
||||
RATE_CHANGE_100MHZ);
|
||||
|
||||
mutex_unlock(&pcie_dev->clk_lock);
|
||||
}
|
||||
}
|
||||
|
||||
ret = msm_pcie_link_retrain(pcie_dev, root_pci_dev);
|
||||
@@ -6270,9 +6295,18 @@ int msm_pcie_set_link_bandwidth(struct pci_dev *pci_dev, u16 target_link_speed,
|
||||
RPMH_REGULATOR_LEVEL_LOW_SVS,
|
||||
pcie_dev->cx_vreg->max_v);
|
||||
|
||||
if (pcie_dev->rate_change_clk)
|
||||
clk_set_rate(pcie_dev->rate_change_clk->hdl,
|
||||
RATE_CHANGE_19P2MHZ);
|
||||
if (pcie_dev->rate_change_clk) {
|
||||
mutex_lock(&pcie_dev->clk_lock);
|
||||
|
||||
pcie_drv.rate_change_vote &= ~BIT(pcie_dev->rc_idx);
|
||||
|
||||
/* only switch to 19.2MHz if no one needs 100MHz */
|
||||
if (!pcie_drv.rate_change_vote)
|
||||
clk_set_rate(pcie_dev->rate_change_clk->hdl,
|
||||
RATE_CHANGE_19P2MHZ);
|
||||
|
||||
mutex_unlock(&pcie_dev->clk_lock);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -6561,6 +6595,7 @@ static int __init pcie_init(void)
|
||||
msm_pcie_dev[i].cfg_access = true;
|
||||
mutex_init(&msm_pcie_dev[i].enumerate_lock);
|
||||
mutex_init(&msm_pcie_dev[i].setup_lock);
|
||||
mutex_init(&msm_pcie_dev[i].clk_lock);
|
||||
mutex_init(&msm_pcie_dev[i].recovery_lock);
|
||||
spin_lock_init(&msm_pcie_dev[i].wakeup_lock);
|
||||
spin_lock_init(&msm_pcie_dev[i].irq_lock);
|
||||
|
||||
Reference in New Issue
Block a user