Skip to content

Commit

Permalink
phy: xilinx: phy-zynqmp: Fix SGMII linkup failure on resume
Browse files Browse the repository at this point in the history
[ Upstream commit 5af9b30 ]

On a few Kria KR260 Robotics Starter Kit the PS-GEM SGMII linkup is not
happening after the resume. This is because serdes registers are reset
when FPD is off (in suspend state) and needs to be reprogrammed in the
resume path with the same default initialization as done in the first
stage bootloader psu_init routine.

To address the failure introduce a set of serdes registers to be saved in
the suspend path and then restore it on resume.

Fixes: 4a33bea ("phy: zynqmp: Add PHY driver for the Xilinx ZynqMP Gigabit Transceiver")
Signed-off-by: Piyush Mehta <[email protected]>
Signed-off-by: Radhey Shyam Pandey <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Vinod Koul <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
  • Loading branch information
PiyushXilinx authored and gregkh committed Sep 4, 2024
1 parent c401845 commit e144fc9
Showing 1 changed file with 56 additions and 0 deletions.
56 changes: 56 additions & 0 deletions drivers/phy/xilinx/phy-zynqmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,24 @@
/* Timeout values */
#define TIMEOUT_US 1000

/* Lane 0/1/2/3 offset */
#define DIG_8(n) ((0x4000 * (n)) + 0x1074)
#define ILL13(n) ((0x4000 * (n)) + 0x1994)
#define DIG_10(n) ((0x4000 * (n)) + 0x107c)
#define RST_DLY(n) ((0x4000 * (n)) + 0x19a4)
#define BYP_15(n) ((0x4000 * (n)) + 0x1038)
#define BYP_12(n) ((0x4000 * (n)) + 0x102c)
#define MISC3(n) ((0x4000 * (n)) + 0x19ac)
#define EQ11(n) ((0x4000 * (n)) + 0x1978)

static u32 save_reg_address[] = {
/* Lane 0/1/2/3 Register */
DIG_8(0), ILL13(0), DIG_10(0), RST_DLY(0), BYP_15(0), BYP_12(0), MISC3(0), EQ11(0),
DIG_8(1), ILL13(1), DIG_10(1), RST_DLY(1), BYP_15(1), BYP_12(1), MISC3(1), EQ11(1),
DIG_8(2), ILL13(2), DIG_10(2), RST_DLY(2), BYP_15(2), BYP_12(2), MISC3(2), EQ11(2),
DIG_8(3), ILL13(3), DIG_10(3), RST_DLY(3), BYP_15(3), BYP_12(3), MISC3(3), EQ11(3),
};

struct xpsgtr_dev;

/**
Expand Down Expand Up @@ -214,6 +232,7 @@ struct xpsgtr_phy {
* @tx_term_fix: fix for GT issue
* @saved_icm_cfg0: stored value of ICM CFG0 register
* @saved_icm_cfg1: stored value of ICM CFG1 register
* @saved_regs: registers to be saved/restored during suspend/resume
*/
struct xpsgtr_dev {
struct device *dev;
Expand All @@ -226,6 +245,7 @@ struct xpsgtr_dev {
bool tx_term_fix;
unsigned int saved_icm_cfg0;
unsigned int saved_icm_cfg1;
u32 *saved_regs;
};

/*
Expand Down Expand Up @@ -299,6 +319,32 @@ static inline void xpsgtr_clr_set_phy(struct xpsgtr_phy *gtr_phy,
writel((readl(addr) & ~clr) | set, addr);
}

/**
* xpsgtr_save_lane_regs - Saves registers on suspend
* @gtr_dev: pointer to phy controller context structure
*/
static void xpsgtr_save_lane_regs(struct xpsgtr_dev *gtr_dev)
{
int i;

for (i = 0; i < ARRAY_SIZE(save_reg_address); i++)
gtr_dev->saved_regs[i] = xpsgtr_read(gtr_dev,
save_reg_address[i]);
}

/**
* xpsgtr_restore_lane_regs - Restores registers on resume
* @gtr_dev: pointer to phy controller context structure
*/
static void xpsgtr_restore_lane_regs(struct xpsgtr_dev *gtr_dev)
{
int i;

for (i = 0; i < ARRAY_SIZE(save_reg_address); i++)
xpsgtr_write(gtr_dev, save_reg_address[i],
gtr_dev->saved_regs[i]);
}

/*
* Hardware Configuration
*/
Expand Down Expand Up @@ -838,6 +884,8 @@ static int xpsgtr_runtime_suspend(struct device *dev)
gtr_dev->saved_icm_cfg0 = xpsgtr_read(gtr_dev, ICM_CFG0);
gtr_dev->saved_icm_cfg1 = xpsgtr_read(gtr_dev, ICM_CFG1);

xpsgtr_save_lane_regs(gtr_dev);

return 0;
}

Expand All @@ -848,6 +896,8 @@ static int xpsgtr_runtime_resume(struct device *dev)
unsigned int i;
bool skip_phy_init;

xpsgtr_restore_lane_regs(gtr_dev);

icm_cfg0 = xpsgtr_read(gtr_dev, ICM_CFG0);
icm_cfg1 = xpsgtr_read(gtr_dev, ICM_CFG1);

Expand Down Expand Up @@ -990,6 +1040,12 @@ static int xpsgtr_probe(struct platform_device *pdev)
return ret;
}

gtr_dev->saved_regs = devm_kmalloc(gtr_dev->dev,
sizeof(save_reg_address),
GFP_KERNEL);
if (!gtr_dev->saved_regs)
return -ENOMEM;

return 0;
}

Expand Down

0 comments on commit e144fc9

Please sign in to comment.