mirror of
https://github.com/nxp-imx/linux-imx.git
synced 2025-09-03 02:16:09 +02:00
phy: lynx-28g: truly power the lanes up or down
The current procedure for power_off() and power_on() is the same as the one used for major lane reconfiguration, aka halting. But one can observe that a halted lane does not cause, for example, the CDR of the link partner to lose lock. Implement the procedure mentioned in the block guide for powering down a lane, and then back on. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
This commit is contained in:
parent
8b4638742d
commit
375b57c1a9
|
@ -63,6 +63,8 @@
|
|||
|
||||
/* Lane a Tx Reset Control Register */
|
||||
#define LYNX_28G_LNaTRSTCTL(lane) (0x800 + (lane) * 0x100 + 0x20)
|
||||
#define LYNX_28G_LNaTRSTCTL_DIS BIT(24)
|
||||
#define LYNX_28G_LNaTRSTCTL_STP_REQ BIT(26)
|
||||
#define LYNX_28G_LNaTRSTCTL_HLT_REQ BIT(27)
|
||||
#define LYNX_28G_LNaTRSTCTL_RST_DONE BIT(30)
|
||||
#define LYNX_28G_LNaTRSTCTL_RST_REQ BIT(31)
|
||||
|
@ -82,6 +84,8 @@
|
|||
|
||||
/* Lane a Rx Reset Control Register */
|
||||
#define LYNX_28G_LNaRRSTCTL(lane) (0x800 + (lane) * 0x100 + 0x40)
|
||||
#define LYNX_28G_LNaRRSTCTL_DIS BIT(24)
|
||||
#define LYNX_28G_LNaRRSTCTL_STP_REQ BIT(26)
|
||||
#define LYNX_28G_LNaRRSTCTL_HLT_REQ BIT(27)
|
||||
#define LYNX_28G_LNaRRSTCTL_RST_DONE BIT(30)
|
||||
#define LYNX_28G_LNaRRSTCTL_RST_REQ BIT(31)
|
||||
|
@ -428,14 +432,12 @@ static void lynx_28g_lane_set_25gbaser(struct lynx_28g_lane *lane)
|
|||
iowrite32(0x00008001, priv->base + LYNX_28G_LNaTTLCR0(lane->id));
|
||||
}
|
||||
|
||||
static int lynx_28g_power_off(struct phy *phy)
|
||||
/* Halting puts the lane in a mode in which it can be reconfigured */
|
||||
static void lynx_28g_lane_halt(struct phy *phy)
|
||||
{
|
||||
struct lynx_28g_lane *lane = phy_get_drvdata(phy);
|
||||
u32 trstctl, rrstctl;
|
||||
|
||||
if (!lane->powered_up)
|
||||
return 0;
|
||||
|
||||
/* Issue a halt request */
|
||||
lynx_28g_lane_rmw(lane, LNaTRSTCTL, LYNX_28G_LNaTRSTCTL_HLT_REQ,
|
||||
LYNX_28G_LNaTRSTCTL_HLT_REQ);
|
||||
|
@ -448,20 +450,13 @@ static int lynx_28g_power_off(struct phy *phy)
|
|||
rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL);
|
||||
} while ((trstctl & LYNX_28G_LNaTRSTCTL_HLT_REQ) ||
|
||||
(rrstctl & LYNX_28G_LNaRRSTCTL_HLT_REQ));
|
||||
|
||||
lane->powered_up = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lynx_28g_power_on(struct phy *phy)
|
||||
static void lynx_28g_lane_reset(struct phy *phy)
|
||||
{
|
||||
struct lynx_28g_lane *lane = phy_get_drvdata(phy);
|
||||
u32 trstctl, rrstctl;
|
||||
|
||||
if (lane->powered_up)
|
||||
return 0;
|
||||
|
||||
/* Issue a reset request on the lane */
|
||||
lynx_28g_lane_rmw(lane, LNaTRSTCTL, LYNX_28G_LNaTRSTCTL_RST_REQ,
|
||||
LYNX_28G_LNaTRSTCTL_RST_REQ);
|
||||
|
@ -474,6 +469,52 @@ static int lynx_28g_power_on(struct phy *phy)
|
|||
rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL);
|
||||
} while (!(trstctl & LYNX_28G_LNaTRSTCTL_RST_DONE) ||
|
||||
!(rrstctl & LYNX_28G_LNaRRSTCTL_RST_DONE));
|
||||
}
|
||||
|
||||
static int lynx_28g_power_off(struct phy *phy)
|
||||
{
|
||||
struct lynx_28g_lane *lane = phy_get_drvdata(phy);
|
||||
u32 trstctl, rrstctl;
|
||||
|
||||
if (!lane->powered_up)
|
||||
return 0;
|
||||
|
||||
/* Issue a stop request */
|
||||
lynx_28g_lane_rmw(lane, LNaTRSTCTL, LYNX_28G_LNaTRSTCTL_STP_REQ,
|
||||
LYNX_28G_LNaTRSTCTL_STP_REQ);
|
||||
lynx_28g_lane_rmw(lane, LNaRRSTCTL, LYNX_28G_LNaRRSTCTL_STP_REQ,
|
||||
LYNX_28G_LNaRRSTCTL_STP_REQ);
|
||||
|
||||
/* Wait until the stop process is complete */
|
||||
do {
|
||||
trstctl = lynx_28g_lane_read(lane, LNaTRSTCTL);
|
||||
rrstctl = lynx_28g_lane_read(lane, LNaRRSTCTL);
|
||||
} while ((trstctl & LYNX_28G_LNaTRSTCTL_STP_REQ) ||
|
||||
(rrstctl & LYNX_28G_LNaRRSTCTL_STP_REQ));
|
||||
|
||||
/* Power down the RX and TX portions of the lane */
|
||||
lynx_28g_lane_rmw(lane, LNaRRSTCTL, LYNX_28G_LNaRRSTCTL_DIS,
|
||||
LYNX_28G_LNaRRSTCTL_DIS);
|
||||
lynx_28g_lane_rmw(lane, LNaTRSTCTL, LYNX_28G_LNaTRSTCTL_DIS,
|
||||
LYNX_28G_LNaTRSTCTL_DIS);
|
||||
|
||||
lane->powered_up = false;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lynx_28g_power_on(struct phy *phy)
|
||||
{
|
||||
struct lynx_28g_lane *lane = phy_get_drvdata(phy);
|
||||
|
||||
if (lane->powered_up)
|
||||
return 0;
|
||||
|
||||
/* Power up the RX and TX portions of the lane */
|
||||
lynx_28g_lane_rmw(lane, LNaRRSTCTL, 0, LYNX_28G_LNaRRSTCTL_DIS);
|
||||
lynx_28g_lane_rmw(lane, LNaTRSTCTL, 0, LYNX_28G_LNaTRSTCTL_DIS);
|
||||
|
||||
lynx_28g_lane_reset(phy);
|
||||
|
||||
lane->powered_up = true;
|
||||
|
||||
|
@ -500,7 +541,7 @@ static int lynx_28g_set_mode(struct phy *phy, enum phy_mode mode, int submode)
|
|||
* the reconfiguration is being done.
|
||||
*/
|
||||
if (powered_up)
|
||||
lynx_28g_power_off(phy);
|
||||
lynx_28g_lane_halt(phy);
|
||||
|
||||
spin_lock(&priv->pcc_lock);
|
||||
|
||||
|
@ -525,9 +566,9 @@ static int lynx_28g_set_mode(struct phy *phy, enum phy_mode mode, int submode)
|
|||
out:
|
||||
spin_unlock(&priv->pcc_lock);
|
||||
|
||||
/* Power up the lane if necessary */
|
||||
/* Reset the lane if necessary */
|
||||
if (powered_up)
|
||||
lynx_28g_power_on(phy);
|
||||
lynx_28g_lane_reset(phy);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user