Skip to content

Commit 065d588

Browse files
MikeLooijmansvinodkoul
authored andcommitted
phy-zynqmp: Postpone getting clock rate until actually needed
At probe time the driver would display the following error and abort: xilinx-psgtr fd400000.phy: Invalid rate 0 for reference clock 0 At probe time, the associated GTR driver (e.g. SATA or PCIe) hasn't initialized the clock yet, so clk_get_rate() likely returns 0 if the clock is programmable. So this driver only works if the clock is fixed. The PHY driver doesn't need to know the clock frequency at probe yet, so wait until the associated driver initializes the lane before requesting the clock rate setting. In addition to allowing the driver to be used with programmable clocks, this also reduces the driver's runtime memory footprint by removing an array of pointers from struct xpsgtr_phy. Signed-off-by: Mike Looijmans <[email protected]> Acked-by: Michal Simek <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Vinod Koul <[email protected]>
1 parent 1b1e949 commit 065d588

File tree

1 file changed

+37
-33
lines changed

1 file changed

+37
-33
lines changed

drivers/phy/xilinx/phy-zynqmp.c

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,6 @@ struct xpsgtr_phy {
222222
* @siou: siou base address
223223
* @gtr_mutex: mutex for locking
224224
* @phys: PHY lanes
225-
* @refclk_sscs: spread spectrum settings for the reference clocks
226225
* @clk: reference clocks
227226
* @tx_term_fix: fix for GT issue
228227
* @saved_icm_cfg0: stored value of ICM CFG0 register
@@ -235,7 +234,6 @@ struct xpsgtr_dev {
235234
void __iomem *siou;
236235
struct mutex gtr_mutex; /* mutex for locking */
237236
struct xpsgtr_phy phys[NUM_LANES];
238-
const struct xpsgtr_ssc *refclk_sscs[NUM_LANES];
239237
struct clk *clk[NUM_LANES];
240238
bool tx_term_fix;
241239
unsigned int saved_icm_cfg0;
@@ -398,13 +396,40 @@ static int xpsgtr_wait_pll_lock(struct phy *phy)
398396
return ret;
399397
}
400398

399+
/* Get the spread spectrum (SSC) settings for the reference clock rate */
400+
static const struct xpsgtr_ssc *xpsgtr_find_sscs(struct xpsgtr_phy *gtr_phy)
401+
{
402+
unsigned long rate;
403+
struct clk *clk;
404+
unsigned int i;
405+
406+
clk = gtr_phy->dev->clk[gtr_phy->refclk];
407+
rate = clk_get_rate(clk);
408+
409+
for (i = 0 ; i < ARRAY_SIZE(ssc_lookup); i++) {
410+
/* Allow an error of 100 ppm */
411+
unsigned long error = ssc_lookup[i].refclk_rate / 10000;
412+
413+
if (abs(rate - ssc_lookup[i].refclk_rate) < error)
414+
return &ssc_lookup[i];
415+
}
416+
417+
dev_err(gtr_phy->dev->dev, "Invalid rate %lu for reference clock %u\n",
418+
rate, gtr_phy->refclk);
419+
420+
return NULL;
421+
}
422+
401423
/* Configure PLL and spread-sprectrum clock. */
402-
static void xpsgtr_configure_pll(struct xpsgtr_phy *gtr_phy)
424+
static int xpsgtr_configure_pll(struct xpsgtr_phy *gtr_phy)
403425
{
404426
const struct xpsgtr_ssc *ssc;
405427
u32 step_size;
406428

407-
ssc = gtr_phy->dev->refclk_sscs[gtr_phy->refclk];
429+
ssc = xpsgtr_find_sscs(gtr_phy);
430+
if (!ssc)
431+
return -EINVAL;
432+
408433
step_size = ssc->step_size;
409434

410435
xpsgtr_clr_set(gtr_phy->dev, PLL_REF_SEL(gtr_phy->lane),
@@ -446,6 +471,8 @@ static void xpsgtr_configure_pll(struct xpsgtr_phy *gtr_phy)
446471
xpsgtr_clr_set_phy(gtr_phy, L0_PLL_SS_STEP_SIZE_3_MSB,
447472
STEP_SIZE_3_MASK, (step_size & STEP_SIZE_3_MASK) |
448473
FORCE_STEP_SIZE | FORCE_STEPS);
474+
475+
return 0;
449476
}
450477

451478
/* Configure the lane protocol. */
@@ -658,7 +685,10 @@ static int xpsgtr_phy_init(struct phy *phy)
658685
* Configure the PLL, the lane protocol, and perform protocol-specific
659686
* initialization.
660687
*/
661-
xpsgtr_configure_pll(gtr_phy);
688+
ret = xpsgtr_configure_pll(gtr_phy);
689+
if (ret)
690+
goto out;
691+
662692
xpsgtr_lane_set_protocol(gtr_phy);
663693

664694
switch (gtr_phy->protocol) {
@@ -823,8 +853,7 @@ static struct phy *xpsgtr_xlate(struct device *dev,
823853
}
824854

825855
refclk = args->args[3];
826-
if (refclk >= ARRAY_SIZE(gtr_dev->refclk_sscs) ||
827-
!gtr_dev->refclk_sscs[refclk]) {
856+
if (refclk >= ARRAY_SIZE(gtr_dev->clk)) {
828857
dev_err(dev, "Invalid reference clock number %u\n", refclk);
829858
return ERR_PTR(-EINVAL);
830859
}
@@ -928,9 +957,7 @@ static int xpsgtr_get_ref_clocks(struct xpsgtr_dev *gtr_dev)
928957
{
929958
unsigned int refclk;
930959

931-
for (refclk = 0; refclk < ARRAY_SIZE(gtr_dev->refclk_sscs); ++refclk) {
932-
unsigned long rate;
933-
unsigned int i;
960+
for (refclk = 0; refclk < ARRAY_SIZE(gtr_dev->clk); ++refclk) {
934961
struct clk *clk;
935962
char name[8];
936963

@@ -946,29 +973,6 @@ static int xpsgtr_get_ref_clocks(struct xpsgtr_dev *gtr_dev)
946973
continue;
947974

948975
gtr_dev->clk[refclk] = clk;
949-
950-
/*
951-
* Get the spread spectrum (SSC) settings for the reference
952-
* clock rate.
953-
*/
954-
rate = clk_get_rate(clk);
955-
956-
for (i = 0 ; i < ARRAY_SIZE(ssc_lookup); i++) {
957-
/* Allow an error of 100 ppm */
958-
unsigned long error = ssc_lookup[i].refclk_rate / 10000;
959-
960-
if (abs(rate - ssc_lookup[i].refclk_rate) < error) {
961-
gtr_dev->refclk_sscs[refclk] = &ssc_lookup[i];
962-
break;
963-
}
964-
}
965-
966-
if (i == ARRAY_SIZE(ssc_lookup)) {
967-
dev_err(gtr_dev->dev,
968-
"Invalid rate %lu for reference clock %u\n",
969-
rate, refclk);
970-
return -EINVAL;
971-
}
972976
}
973977

974978
return 0;

0 commit comments

Comments
 (0)