@@ -3033,6 +3033,7 @@ struct qmp_pcie {
30333033
30343034 const struct qmp_phy_cfg * cfg ;
30353035 bool tcsr_4ln_config ;
3036+ bool skip_init ;
30363037
30373038 void __iomem * serdes ;
30383039 void __iomem * pcs ;
@@ -4330,18 +4331,38 @@ static int qmp_pcie_init(struct phy *phy)
43304331{
43314332 struct qmp_pcie * qmp = phy_get_drvdata (phy );
43324333 const struct qmp_phy_cfg * cfg = qmp -> cfg ;
4334+ void __iomem * pcs = qmp -> pcs ;
4335+ bool phy_initialized = !!(readl (pcs + cfg -> regs [QPHY_START_CTRL ]));
43334336 int ret ;
43344337
4338+ qmp -> skip_init = qmp -> nocsr_reset && phy_initialized ;
4339+ /*
4340+ * We need to check the existence of init sequences in two cases:
4341+ * 1. The PHY doesn't support no_csr reset.
4342+ * 2. The PHY supports no_csr reset but isn't initialized by bootloader.
4343+ * As we can't skip init in these two cases.
4344+ */
4345+ if (!qmp -> skip_init && !cfg -> tbls .serdes_num ) {
4346+ dev_err (qmp -> dev , "Init sequence not available\n" );
4347+ return - ENODATA ;
4348+ }
4349+
43354350 ret = regulator_bulk_enable (cfg -> num_vregs , qmp -> vregs );
43364351 if (ret ) {
43374352 dev_err (qmp -> dev , "failed to enable regulators, err=%d\n" , ret );
43384353 return ret ;
43394354 }
43404355
4341- ret = reset_control_bulk_assert (cfg -> num_resets , qmp -> resets );
4342- if (ret ) {
4343- dev_err (qmp -> dev , "reset assert failed\n" );
4344- goto err_disable_regulators ;
4356+ /*
4357+ * Toggle BCR reset for PHY that doesn't support no_csr reset or has not
4358+ * been initialized.
4359+ */
4360+ if (!qmp -> skip_init ) {
4361+ ret = reset_control_bulk_assert (cfg -> num_resets , qmp -> resets );
4362+ if (ret ) {
4363+ dev_err (qmp -> dev , "reset assert failed\n" );
4364+ goto err_disable_regulators ;
4365+ }
43454366 }
43464367
43474368 ret = reset_control_assert (qmp -> nocsr_reset );
@@ -4352,10 +4373,12 @@ static int qmp_pcie_init(struct phy *phy)
43524373
43534374 usleep_range (200 , 300 );
43544375
4355- ret = reset_control_bulk_deassert (cfg -> num_resets , qmp -> resets );
4356- if (ret ) {
4357- dev_err (qmp -> dev , "reset deassert failed\n" );
4358- goto err_assert_reset ;
4376+ if (!qmp -> skip_init ) {
4377+ ret = reset_control_bulk_deassert (cfg -> num_resets , qmp -> resets );
4378+ if (ret ) {
4379+ dev_err (qmp -> dev , "reset deassert failed\n" );
4380+ goto err_assert_reset ;
4381+ }
43594382 }
43604383
43614384 ret = clk_bulk_prepare_enable (ARRAY_SIZE (qmp_pciephy_clk_l ), qmp -> clks );
@@ -4365,7 +4388,8 @@ static int qmp_pcie_init(struct phy *phy)
43654388 return 0 ;
43664389
43674390err_assert_reset :
4368- reset_control_bulk_assert (cfg -> num_resets , qmp -> resets );
4391+ if (!qmp -> skip_init )
4392+ reset_control_bulk_assert (cfg -> num_resets , qmp -> resets );
43694393err_disable_regulators :
43704394 regulator_bulk_disable (cfg -> num_vregs , qmp -> vregs );
43714395
@@ -4377,7 +4401,10 @@ static int qmp_pcie_exit(struct phy *phy)
43774401 struct qmp_pcie * qmp = phy_get_drvdata (phy );
43784402 const struct qmp_phy_cfg * cfg = qmp -> cfg ;
43794403
4380- reset_control_bulk_assert (cfg -> num_resets , qmp -> resets );
4404+ if (qmp -> nocsr_reset )
4405+ reset_control_assert (qmp -> nocsr_reset );
4406+ else
4407+ reset_control_bulk_assert (cfg -> num_resets , qmp -> resets );
43814408
43824409 clk_bulk_disable_unprepare (ARRAY_SIZE (qmp_pciephy_clk_l ), qmp -> clks );
43834410
@@ -4396,6 +4423,13 @@ static int qmp_pcie_power_on(struct phy *phy)
43964423 unsigned int mask , val ;
43974424 int ret ;
43984425
4426+ /*
4427+ * Write CSR register for PHY that doesn't support no_csr reset or has not
4428+ * been initialized.
4429+ */
4430+ if (qmp -> skip_init )
4431+ goto skip_tbls_init ;
4432+
43994433 qphy_setbits (pcs , cfg -> regs [QPHY_PCS_POWER_DOWN_CONTROL ],
44004434 cfg -> pwrdn_ctrl );
44014435
@@ -4407,6 +4441,7 @@ static int qmp_pcie_power_on(struct phy *phy)
44074441 qmp_pcie_init_registers (qmp , & cfg -> tbls );
44084442 qmp_pcie_init_registers (qmp , mode_tbls );
44094443
4444+ skip_tbls_init :
44104445 ret = clk_bulk_prepare_enable (qmp -> num_pipe_clks , qmp -> pipe_clks );
44114446 if (ret )
44124447 return ret ;
@@ -4417,6 +4452,9 @@ static int qmp_pcie_power_on(struct phy *phy)
44174452 goto err_disable_pipe_clk ;
44184453 }
44194454
4455+ if (qmp -> skip_init )
4456+ goto skip_serdes_start ;
4457+
44204458 /* Pull PHY out of reset state */
44214459 qphy_clrbits (pcs , cfg -> regs [QPHY_SW_RESET ], SW_RESET );
44224460
@@ -4426,6 +4464,7 @@ static int qmp_pcie_power_on(struct phy *phy)
44264464 if (!cfg -> skip_start_delay )
44274465 usleep_range (1000 , 1200 );
44284466
4467+ skip_serdes_start :
44294468 status = pcs + cfg -> regs [QPHY_PCS_STATUS ];
44304469 mask = cfg -> phy_status ;
44314470 ret = readl_poll_timeout (status , val , !(val & mask ), 200 ,
@@ -4450,6 +4489,15 @@ static int qmp_pcie_power_off(struct phy *phy)
44504489
44514490 clk_bulk_disable_unprepare (qmp -> num_pipe_clks , qmp -> pipe_clks );
44524491
4492+ /*
4493+ * While powering off the PHY, only qmp->nocsr_reset needs to be checked. In
4494+ * this way, no matter whether the PHY settings were initially programmed by
4495+ * bootloader or PHY driver itself, we can reuse them when PHY is powered on
4496+ * next time.
4497+ */
4498+ if (qmp -> nocsr_reset )
4499+ goto skip_phy_deinit ;
4500+
44534501 /* PHY reset */
44544502 qphy_setbits (qmp -> pcs , cfg -> regs [QPHY_SW_RESET ], SW_RESET );
44554503
@@ -4461,6 +4509,7 @@ static int qmp_pcie_power_off(struct phy *phy)
44614509 qphy_clrbits (qmp -> pcs , cfg -> regs [QPHY_PCS_POWER_DOWN_CONTROL ],
44624510 cfg -> pwrdn_ctrl );
44634511
4512+ skip_phy_deinit :
44644513 return 0 ;
44654514}
44664515
0 commit comments