Message ID | 20231127-refclk_always_on-v3-3-26d969fa8f1d@quicinc.com (mailing list archive) |
---|---|
State | Not Applicable |
Headers | show |
Series | phy: qcom-qmp-pcie: Add support to keep refclk always on | expand |
On Mon, Nov 27, 2023 at 05:43:51PM +0530, Krishna chaitanya chundru wrote: > In PCIe low power states like L1.1 or L1.2 the phy will stop > supplying refclk to endpoint. If endpoint asserts clkreq to bring > back link L0, then RC needs to provide refclk to endpoint. > > Some platforms with pcie switch fail to drive the clkreq signal to > the host from the endpoints because of the switch board design. > Due to that refclk needs to supplied to the endpoint always. > > Add a flag to keep refclk always supplied to endpoint. > > Signed-off-by: Krishna chaitanya chundru <quic_krichai@quicinc.com> > Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> > --- > drivers/phy/qualcomm/phy-qcom-qmp-pcie.c | 14 ++++++++++++++ > 1 file changed, 14 insertions(+) > > diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c > index 7fdf9b2596b6..e95f677817f7 100644 > --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c > +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c > @@ -43,6 +43,8 @@ > /* QPHY_PCS_STATUS bit */ > #define PHYSTATUS BIT(6) > #define PHYSTATUS_4_20 BIT(7) > +/* PCS_PCIE_ENDPOINT_REFCLK_CNTRL */ > +#define EPCLK_ALWAYS_ON_EN BIT(6) > > #define PHY_INIT_COMPLETE_TIMEOUT 10000 > > @@ -2264,6 +2266,8 @@ struct qmp_pcie { > struct phy *phy; > int mode; > > + bool refclk_always_on; > + > struct clk_fixed_rate pipe_clk_fixed; > }; > > @@ -3179,6 +3183,10 @@ static void qmp_pcie_init_registers(struct qmp_pcie *qmp, const struct qmp_phy_c > qmp_pcie_configure(pcs, tbls->pcs, tbls->pcs_num); > qmp_pcie_configure(pcs_misc, tbls->pcs_misc, tbls->pcs_misc_num); > > + if (qmp->refclk_always_on && cfg->regs[QPHY_PCS_ENDPOINT_REFCLK_CNTRL]) > + qphy_setbits(pcs_misc, cfg->regs[QPHY_PCS_ENDPOINT_REFCLK_CNTRL], > + EPCLK_ALWAYS_ON_EN); > + > if (cfg->lanes >= 4 && qmp->tcsr_4ln_config) { > qmp_pcie_configure(serdes, cfg->serdes_4ln_tbl, cfg->serdes_4ln_num); > qmp_pcie_init_port_b(qmp, tbls); > @@ -3701,6 +3709,12 @@ static int qmp_pcie_probe(struct platform_device *pdev) > if (ret) > goto err_node_put; > > + qmp->refclk_always_on = of_property_read_bool(dev->of_node, "qcom,refclk-always-on"); > + if (qmp->refclk_always_on && !qmp->cfg->regs[QPHY_PCS_ENDPOINT_REFCLK_CNTRL]) { > + dev_err(dev, "refclk is always on is present but refclk cntrl offset is not present\n"); "Firmware requested to keep REFCLK always ON, but driver missing offset\n" - Mani > + goto err_node_put; > + } > + > ret = phy_pipe_clk_register(qmp, np); > if (ret) > goto err_node_put; > > -- > 2.42.0 > >
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c index 7fdf9b2596b6..e95f677817f7 100644 --- a/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c +++ b/drivers/phy/qualcomm/phy-qcom-qmp-pcie.c @@ -43,6 +43,8 @@ /* QPHY_PCS_STATUS bit */ #define PHYSTATUS BIT(6) #define PHYSTATUS_4_20 BIT(7) +/* PCS_PCIE_ENDPOINT_REFCLK_CNTRL */ +#define EPCLK_ALWAYS_ON_EN BIT(6) #define PHY_INIT_COMPLETE_TIMEOUT 10000 @@ -2264,6 +2266,8 @@ struct qmp_pcie { struct phy *phy; int mode; + bool refclk_always_on; + struct clk_fixed_rate pipe_clk_fixed; }; @@ -3179,6 +3183,10 @@ static void qmp_pcie_init_registers(struct qmp_pcie *qmp, const struct qmp_phy_c qmp_pcie_configure(pcs, tbls->pcs, tbls->pcs_num); qmp_pcie_configure(pcs_misc, tbls->pcs_misc, tbls->pcs_misc_num); + if (qmp->refclk_always_on && cfg->regs[QPHY_PCS_ENDPOINT_REFCLK_CNTRL]) + qphy_setbits(pcs_misc, cfg->regs[QPHY_PCS_ENDPOINT_REFCLK_CNTRL], + EPCLK_ALWAYS_ON_EN); + if (cfg->lanes >= 4 && qmp->tcsr_4ln_config) { qmp_pcie_configure(serdes, cfg->serdes_4ln_tbl, cfg->serdes_4ln_num); qmp_pcie_init_port_b(qmp, tbls); @@ -3701,6 +3709,12 @@ static int qmp_pcie_probe(struct platform_device *pdev) if (ret) goto err_node_put; + qmp->refclk_always_on = of_property_read_bool(dev->of_node, "qcom,refclk-always-on"); + if (qmp->refclk_always_on && !qmp->cfg->regs[QPHY_PCS_ENDPOINT_REFCLK_CNTRL]) { + dev_err(dev, "refclk is always on is present but refclk cntrl offset is not present\n"); + goto err_node_put; + } + ret = phy_pipe_clk_register(qmp, np); if (ret) goto err_node_put;