diff --git a/drivers/pci/controller/pci-msm.c b/drivers/pci/controller/pci-msm.c index a2b82a128000..65304cebe100 100644 --- a/drivers/pci/controller/pci-msm.c +++ b/drivers/pci/controller/pci-msm.c @@ -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);