mirror of
https://github.com/torvalds/linux.git
synced 2026-09-24 06:24:02 +02:00
phy: qcom: qmp-pcie: Skip PHY reset if already up
If the bootloader has already powered up the PCIe PHY, performing a full reset and waiting for the PHY to come up again adds unnecessary delay during boot. Extend the existing skip_init handling by introducing a skip_reset condition. When skip_init is active and the PHY status indicates that the PHY is already operational, skip asserting and deasserting the no-csr reset while still enabling the required resources during power-on. This allows reusing the bootloader-initialized PHY state and avoids redundant PHY reinitialization and PCIe link retraining, which can add hundred's of milliseconds of delay. This relies on the assumption that when skip_init is enabled and the PHY is reported as up, the bootloader has already configured the PHY correctly and the link is in a usable state. Reviewed-by: Abel Vesa <abel.vesa@oss.qualcomm.com> Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com> Tested-by: Qiang Yu <qiang.yu@oss.qualcomm.com> Signed-off-by: Krishna Chaitanya Chundru <krishna.chundru@oss.qualcomm.com> Link: https://patch.msgid.link/20260709-link_retain-v3-1-81a9d187bb61@oss.qualcomm.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
This commit is contained in:
parent
2ec9c210c1
commit
910b828b22
|
|
@ -5231,6 +5231,7 @@ static int qmp_pcie_init(struct phy *phy)
|
|||
struct qmp_pcie *qmp = phy_get_drvdata(phy);
|
||||
const struct qmp_phy_cfg *cfg = qmp->cfg;
|
||||
void __iomem *pcs = qmp->pcs;
|
||||
bool skip_reset;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
|
|
@ -5246,6 +5247,9 @@ static int qmp_pcie_init(struct phy *phy)
|
|||
qphy_checkbits(pcs, cfg->regs[QPHY_START_CTRL], SERDES_START | PCS_START) &&
|
||||
qphy_checkbits(pcs, cfg->regs[QPHY_PCS_POWER_DOWN_CONTROL], cfg->pwrdn_ctrl);
|
||||
|
||||
skip_reset = qmp->skip_init && !qphy_checkbits(pcs, cfg->regs[QPHY_PCS_STATUS],
|
||||
cfg->phy_status);
|
||||
|
||||
if (!qmp->skip_init && !cfg->tbls.serdes_num) {
|
||||
dev_err(qmp->dev, "Init sequence not available\n");
|
||||
return -ENODATA;
|
||||
|
|
@ -5269,13 +5273,15 @@ static int qmp_pcie_init(struct phy *phy)
|
|||
}
|
||||
}
|
||||
|
||||
ret = reset_control_assert(qmp->nocsr_reset);
|
||||
if (ret) {
|
||||
dev_err(qmp->dev, "no-csr reset assert failed\n");
|
||||
goto err_assert_reset;
|
||||
}
|
||||
if (!skip_reset) {
|
||||
ret = reset_control_assert(qmp->nocsr_reset);
|
||||
if (ret) {
|
||||
dev_err(qmp->dev, "no-csr reset assert failed\n");
|
||||
goto err_assert_reset;
|
||||
}
|
||||
|
||||
usleep_range(200, 300);
|
||||
usleep_range(200, 300);
|
||||
}
|
||||
|
||||
if (!qmp->skip_init) {
|
||||
ret = reset_control_bulk_deassert(cfg->num_resets, qmp->resets);
|
||||
|
|
@ -5325,8 +5331,11 @@ static int qmp_pcie_power_on(struct phy *phy)
|
|||
void __iomem *pcs = qmp->pcs;
|
||||
void __iomem *status;
|
||||
unsigned int mask, val;
|
||||
bool skip_reset;
|
||||
int ret;
|
||||
|
||||
skip_reset = qmp->skip_init && !qphy_checkbits(pcs, cfg->regs[QPHY_PCS_STATUS],
|
||||
cfg->phy_status);
|
||||
/*
|
||||
* Write CSR register for PHY that doesn't support no_csr reset or has not
|
||||
* been initialized.
|
||||
|
|
@ -5350,10 +5359,12 @@ static int qmp_pcie_power_on(struct phy *phy)
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = reset_control_deassert(qmp->nocsr_reset);
|
||||
if (ret) {
|
||||
dev_err(qmp->dev, "no-csr reset deassert failed\n");
|
||||
goto err_disable_pipe_clk;
|
||||
if (!skip_reset) {
|
||||
ret = reset_control_deassert(qmp->nocsr_reset);
|
||||
if (ret) {
|
||||
dev_err(qmp->dev, "no-csr reset deassert failed\n");
|
||||
goto err_disable_pipe_clk;
|
||||
}
|
||||
}
|
||||
|
||||
if (qmp->skip_init)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user