Skip to content

Commit 5af9b30

Browse files
PiyushXilinxvinodkoul
authored andcommitted
phy: xilinx: phy-zynqmp: Fix SGMII linkup failure on resume
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]>
1 parent 3a07703 commit 5af9b30

File tree

1 file changed

+56
-0
lines changed

1 file changed

+56
-0
lines changed

drivers/phy/xilinx/phy-zynqmp.c

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,24 @@ static const char *const xpsgtr_icm_str[] = {
160160
/* Timeout values */
161161
#define TIMEOUT_US 1000
162162

163+
/* Lane 0/1/2/3 offset */
164+
#define DIG_8(n) ((0x4000 * (n)) + 0x1074)
165+
#define ILL13(n) ((0x4000 * (n)) + 0x1994)
166+
#define DIG_10(n) ((0x4000 * (n)) + 0x107c)
167+
#define RST_DLY(n) ((0x4000 * (n)) + 0x19a4)
168+
#define BYP_15(n) ((0x4000 * (n)) + 0x1038)
169+
#define BYP_12(n) ((0x4000 * (n)) + 0x102c)
170+
#define MISC3(n) ((0x4000 * (n)) + 0x19ac)
171+
#define EQ11(n) ((0x4000 * (n)) + 0x1978)
172+
173+
static u32 save_reg_address[] = {
174+
/* Lane 0/1/2/3 Register */
175+
DIG_8(0), ILL13(0), DIG_10(0), RST_DLY(0), BYP_15(0), BYP_12(0), MISC3(0), EQ11(0),
176+
DIG_8(1), ILL13(1), DIG_10(1), RST_DLY(1), BYP_15(1), BYP_12(1), MISC3(1), EQ11(1),
177+
DIG_8(2), ILL13(2), DIG_10(2), RST_DLY(2), BYP_15(2), BYP_12(2), MISC3(2), EQ11(2),
178+
DIG_8(3), ILL13(3), DIG_10(3), RST_DLY(3), BYP_15(3), BYP_12(3), MISC3(3), EQ11(3),
179+
};
180+
163181
struct xpsgtr_dev;
164182

165183
/**
@@ -209,6 +227,7 @@ struct xpsgtr_phy {
209227
* @tx_term_fix: fix for GT issue
210228
* @saved_icm_cfg0: stored value of ICM CFG0 register
211229
* @saved_icm_cfg1: stored value of ICM CFG1 register
230+
* @saved_regs: registers to be saved/restored during suspend/resume
212231
*/
213232
struct xpsgtr_dev {
214233
struct device *dev;
@@ -221,6 +240,7 @@ struct xpsgtr_dev {
221240
bool tx_term_fix;
222241
unsigned int saved_icm_cfg0;
223242
unsigned int saved_icm_cfg1;
243+
u32 *saved_regs;
224244
};
225245

226246
/*
@@ -294,6 +314,32 @@ static inline void xpsgtr_clr_set_phy(struct xpsgtr_phy *gtr_phy,
294314
writel((readl(addr) & ~clr) | set, addr);
295315
}
296316

317+
/**
318+
* xpsgtr_save_lane_regs - Saves registers on suspend
319+
* @gtr_dev: pointer to phy controller context structure
320+
*/
321+
static void xpsgtr_save_lane_regs(struct xpsgtr_dev *gtr_dev)
322+
{
323+
int i;
324+
325+
for (i = 0; i < ARRAY_SIZE(save_reg_address); i++)
326+
gtr_dev->saved_regs[i] = xpsgtr_read(gtr_dev,
327+
save_reg_address[i]);
328+
}
329+
330+
/**
331+
* xpsgtr_restore_lane_regs - Restores registers on resume
332+
* @gtr_dev: pointer to phy controller context structure
333+
*/
334+
static void xpsgtr_restore_lane_regs(struct xpsgtr_dev *gtr_dev)
335+
{
336+
int i;
337+
338+
for (i = 0; i < ARRAY_SIZE(save_reg_address); i++)
339+
xpsgtr_write(gtr_dev, save_reg_address[i],
340+
gtr_dev->saved_regs[i]);
341+
}
342+
297343
/*
298344
* Hardware Configuration
299345
*/
@@ -837,6 +883,8 @@ static int xpsgtr_runtime_suspend(struct device *dev)
837883
gtr_dev->saved_icm_cfg0 = xpsgtr_read(gtr_dev, ICM_CFG0);
838884
gtr_dev->saved_icm_cfg1 = xpsgtr_read(gtr_dev, ICM_CFG1);
839885

886+
xpsgtr_save_lane_regs(gtr_dev);
887+
840888
return 0;
841889
}
842890

@@ -847,6 +895,8 @@ static int xpsgtr_runtime_resume(struct device *dev)
847895
unsigned int i;
848896
bool skip_phy_init;
849897

898+
xpsgtr_restore_lane_regs(gtr_dev);
899+
850900
icm_cfg0 = xpsgtr_read(gtr_dev, ICM_CFG0);
851901
icm_cfg1 = xpsgtr_read(gtr_dev, ICM_CFG1);
852902

@@ -994,6 +1044,12 @@ static int xpsgtr_probe(struct platform_device *pdev)
9941044
return ret;
9951045
}
9961046

1047+
gtr_dev->saved_regs = devm_kmalloc(gtr_dev->dev,
1048+
sizeof(save_reg_address),
1049+
GFP_KERNEL);
1050+
if (!gtr_dev->saved_regs)
1051+
return -ENOMEM;
1052+
9971053
return 0;
9981054
}
9991055

0 commit comments

Comments
 (0)