Skip to content

Commit

Permalink
Merge pull request torvalds#744 from analogdevicesinc/rework-qpll-conf
Browse files Browse the repository at this point in the history
iio: jesd204: axi_adxvcri,xilinx_transceiver: pass QPLL selection directly from the state struct
  • Loading branch information
mhennerich authored Dec 13, 2019
2 parents 4646497 + 7755910 commit a335704
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 71 deletions.
35 changes: 10 additions & 25 deletions drivers/iio/jesd204/axi_adxcvr.c
Original file line number Diff line number Diff line change
Expand Up @@ -289,18 +289,10 @@ static unsigned long adxcvr_clk_recalc_rate(struct clk_hw *hw,
} else {
struct xilinx_xcvr_qpll_config qpll_conf;

if ((st->xcvr.type == XILINX_XCVR_TYPE_US_GTH3) ||
(st->xcvr.type == XILINX_XCVR_TYPE_US_GTH4)) {
if (st->sys_clk_sel == ADXCVR_GTH_SYSCLK_QPLL1)
qpll_conf.qpll = 1;
else
qpll_conf.qpll = 0;
}

xilinx_xcvr_qpll_read_config(&st->xcvr, ADXCVR_DRP_PORT_COMMON(0),
&qpll_conf);
return xilinx_xcvr_qpll_calc_lane_rate(&st->xcvr, parent_rate,
&qpll_conf, out_div);
xilinx_xcvr_qpll_read_config(&st->xcvr, st->sys_clk_sel,
ADXCVR_DRP_PORT_COMMON(0), &qpll_conf);
return xilinx_xcvr_qpll_calc_lane_rate(&st->xcvr,
st->sys_clk_sel, parent_rate, &qpll_conf, out_div);
}
}

Expand All @@ -323,8 +315,8 @@ static long adxcvr_clk_round_rate(struct clk_hw *hw,
ret = xilinx_xcvr_calc_cpll_config(&st->xcvr, *prate, rate,
NULL, NULL);
else
ret = xilinx_xcvr_calc_qpll_config(&st->xcvr, *prate, rate,
NULL, NULL);
ret = xilinx_xcvr_calc_qpll_config(&st->xcvr,
st->sys_clk_sel, *prate, rate, NULL, NULL);

return ret < 0 ? ret : rate;
}
Expand All @@ -344,22 +336,14 @@ static int adxcvr_clk_set_rate(struct clk_hw *hw,
dev_dbg(st->dev, "%s: Rate %lu Hz Parent Rate %lu Hz",
__func__, rate, parent_rate);

if ((st->xcvr.type == XILINX_XCVR_TYPE_US_GTH3) ||
(st->xcvr.type == XILINX_XCVR_TYPE_US_GTH4)) {
if (st->sys_clk_sel == ADXCVR_GTH_SYSCLK_QPLL1)
qpll_conf.qpll = 1;
else
qpll_conf.qpll = 0;
}

clk25_div = DIV_ROUND_CLOSEST(parent_rate, 25000000);

if (st->cpll_enable)
ret = xilinx_xcvr_calc_cpll_config(&st->xcvr, parent_rate, rate,
&cpll_conf, &out_div);
else
ret = xilinx_xcvr_calc_qpll_config(&st->xcvr, parent_rate, rate,
&qpll_conf, &out_div);
ret = xilinx_xcvr_calc_qpll_config(&st->xcvr, st->sys_clk_sel,
parent_rate, rate, &qpll_conf, &out_div);
if (ret < 0)
return ret;

Expand All @@ -371,7 +355,8 @@ static int adxcvr_clk_set_rate(struct clk_hw *hw,
ADXCVR_DRP_PORT_CHANNEL(i), &cpll_conf);
else if (i % 4 == 0)
ret = xilinx_xcvr_qpll_write_config(&st->xcvr,
ADXCVR_DRP_PORT_COMMON(i), &qpll_conf);
st->sys_clk_sel,
ADXCVR_DRP_PORT_COMMON(i), &qpll_conf);
if (ret < 0)
return ret;

Expand Down
4 changes: 0 additions & 4 deletions drivers/iio/jesd204/axi_adxcvr.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,6 @@
#define ADXCVR_DRP_PORT_COMMON(x) (x)
#define ADXCVR_DRP_PORT_CHANNEL(x) (0x100 + (x))

#define ADXCVR_GTH_SYSCLK_CPLL 0
#define ADXCVR_GTH_SYSCLK_QPLL1 2
#define ADXCVR_GTH_SYSCLK_QPLL0 3

struct adxcvr_state {
struct device *dev;
void __iomem *regs;
Expand Down
10 changes: 7 additions & 3 deletions drivers/iio/jesd204/axi_jesd204b_gt.c
Original file line number Diff line number Diff line change
Expand Up @@ -652,12 +652,13 @@ static unsigned long jesd204b_gt_clk_recalc_rate(struct clk_hw *hw,
struct xilinx_xcvr_qpll_config qpll_conf;

ret = xilinx_xcvr_qpll_read_config(&st->xcvr,
gt_link->sys_clk_sel,
JESD204B_GT_DRP_PORT_COMMON, &qpll_conf);
if (ret < 0)
return ret;

lane_rate = xilinx_xcvr_qpll_calc_lane_rate(&st->xcvr, parent_rate,
&qpll_conf, out_div);
gt_link->sys_clk_sel, &qpll_conf, out_div);

dev_dbg(st->dev, "%s QPLL %lu %lu\n", __func__,
gt_link->lane_rate, lane_rate);
Expand All @@ -684,7 +685,8 @@ static long jesd204b_gt_clk_round_rate(struct clk_hw *hw, unsigned long rate,
ret = xilinx_xcvr_calc_cpll_config(&st->xcvr, *prate / 1000, rate,
NULL, NULL);
else
ret = xilinx_xcvr_calc_qpll_config(&st->xcvr, *prate / 1000, rate,
ret = xilinx_xcvr_calc_qpll_config(&st->xcvr,
gt_link->sys_clk_sel, *prate / 1000, rate,
NULL, NULL);

if (ret < 0)
Expand Down Expand Up @@ -713,7 +715,8 @@ static int jesd204b_gt_clk_set_rate(struct clk_hw *hw, unsigned long rate,
ret = xilinx_xcvr_calc_cpll_config(&st->xcvr, parent_rate, rate,
&cpll_conf, &out_div);
else
ret = xilinx_xcvr_calc_qpll_config(&st->xcvr, parent_rate, rate,
ret = xilinx_xcvr_calc_qpll_config(&st->xcvr,
gt_link->sys_clk_sel, parent_rate, rate,
&qpll_conf, &out_div);


Expand All @@ -734,6 +737,7 @@ static int jesd204b_gt_clk_set_rate(struct clk_hw *hw, unsigned long rate,
} else {
if (!pll_done) {
xilinx_xcvr_qpll_write_config(&st->xcvr,
gt_link->sys_clk_sel,
JESD204B_GT_DRP_PORT_COMMON, &qpll_conf);
pll_done = 1;
}
Expand Down
95 changes: 62 additions & 33 deletions drivers/iio/jesd204/xilinx_transceiver.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,20 @@
#define TX_CLK25_DIV 0x6a
#define TX_CLK25_DIV_MASK 0x1f

#define GTH34_SYSCLK_CPLL 0
#define GTH34_SYSCLK_QPLL1 2
#define GTH34_SYSCLK_QPLL0 3

#define GTH34_QPLL0_FBDIV_DIV 0x14
#define GTH34_QPLL0_REFCLK_DIV 0x18
#define GTH34_QPLL1_FBDIV 0x94
#define GTH34_QPLL1_REFCLK_DIV 0x98

#define GTH34_QPLL_FBDIV(xcvr, x) \
(0x14 + xilinx_xcvr_qpll_sel((xcvr), (x)) * 0x80)
#define GTH34_QPLL_REFCLK_DIV(xcvr, x) \
(0x18 + xilinx_xcvr_qpll_sel((xcvr), (x)) * 0x80)

static int xilinx_xcvr_drp_read(struct xilinx_xcvr *xcvr,
unsigned int drp_port, unsigned int reg)
{
Expand Down Expand Up @@ -274,6 +288,21 @@ int xilinx_xcvr_configure_lpm_dfe_mode(struct xilinx_xcvr *xcvr,
}
EXPORT_SYMBOL_GPL(xilinx_xcvr_configure_lpm_dfe_mode);

static unsigned int xilinx_xcvr_qpll_sel(struct xilinx_xcvr *xcvr,
unsigned int sys_clk_sel)
{
switch (xcvr->type) {
case XILINX_XCVR_TYPE_US_GTH3:
case XILINX_XCVR_TYPE_US_GTH4:
case XILINX_XCVR_TYPE_US_GTY4:
if (sys_clk_sel == GTH34_SYSCLK_QPLL1)
return 1;
/* fall-through */
default:
return 0;
}
}

static void xilinx_xcvr_setup_cpll_vco_range(struct xilinx_xcvr *xcvr,
unsigned int *vco_max)
{
Expand Down Expand Up @@ -403,7 +432,7 @@ int xilinx_xcvr_calc_cpll_config(struct xilinx_xcvr *xcvr,
EXPORT_SYMBOL_GPL(xilinx_xcvr_calc_cpll_config);

static int xilinx_xcvr_get_qpll_vco_ranges(struct xilinx_xcvr *xcvr,
struct xilinx_xcvr_qpll_config *conf,
unsigned int sys_clk_sel,
unsigned int *vco0_min, unsigned int *vco0_max,
unsigned int *vco1_min, unsigned int *vco1_max)
{
Expand All @@ -417,16 +446,11 @@ static int xilinx_xcvr_get_qpll_vco_ranges(struct xilinx_xcvr *xcvr,
case XILINX_XCVR_TYPE_US_GTH3:
case XILINX_XCVR_TYPE_US_GTH4:
case XILINX_XCVR_TYPE_US_GTY4:
if (conf != NULL) {
if (conf->qpll) {
*vco0_min = 8000000;
*vco0_max = 13000000;
} else {
*vco0_min = 9800000;
*vco0_max = 16375000;
}
} else {
if (xilinx_xcvr_qpll_sel(xcvr, sys_clk_sel)) {
*vco0_min = 8000000;
*vco0_max = 13000000;
} else {
*vco0_min = 9800000;
*vco0_max = 16375000;
}
*vco1_min = *vco0_min;
Expand Down Expand Up @@ -457,7 +481,8 @@ static int xilinx_xcvr_get_qpll_vco_ranges(struct xilinx_xcvr *xcvr,
}

int xilinx_xcvr_calc_qpll_config(struct xilinx_xcvr *xcvr,
unsigned int refclk_hz, unsigned int lane_rate_khz,
unsigned int sys_clk_sel, unsigned int refclk_hz,
unsigned int lane_rate_khz,
struct xilinx_xcvr_qpll_config *conf,
unsigned int *out_div)
{
Expand Down Expand Up @@ -489,7 +514,7 @@ int xilinx_xcvr_calc_qpll_config(struct xilinx_xcvr *xcvr,
return -EINVAL;
}

ret = xilinx_xcvr_get_qpll_vco_ranges(xcvr, conf,
ret = xilinx_xcvr_get_qpll_vco_ranges(xcvr, sys_clk_sel,
&vco0_min, &vco0_max,
&vco1_min, &vco1_max);
if (ret)
Expand Down Expand Up @@ -779,19 +804,13 @@ int xilinx_xcvr_cpll_calc_lane_rate(struct xilinx_xcvr *xcvr,
EXPORT_SYMBOL_GPL(xilinx_xcvr_cpll_calc_lane_rate);

static int xilinx_xcvr_gth34_qpll_read_config(struct xilinx_xcvr *xcvr,
unsigned int drp_port, struct xilinx_xcvr_qpll_config *conf)
unsigned int sys_clk_sel, unsigned int drp_port,
struct xilinx_xcvr_qpll_config *conf)
{
int val;

#define QPLL0_FBDIV_DIV 0x14
#define QPLL0_REFCLK_DIV 0x18
#define QPLL1_FBDIV 0x94
#define QPLL1_REFCLK_DIV 0x98

#define QPLL_FBDIV(x) (0x14 + (x) * 0x80)
#define QPLL_REFCLK_DIV(x) (0x18 + (x) * 0x80)

val = xilinx_xcvr_drp_read(xcvr, drp_port, QPLL_REFCLK_DIV(conf->qpll));
val = xilinx_xcvr_drp_read(xcvr, drp_port,
GTH34_QPLL_REFCLK_DIV(xcvr, sys_clk_sel));
if (val < 0)
return val;

Expand All @@ -813,7 +832,8 @@ static int xilinx_xcvr_gth34_qpll_read_config(struct xilinx_xcvr *xcvr,
break;
}

val = xilinx_xcvr_drp_read(xcvr, drp_port, QPLL_FBDIV(conf->qpll));
val = xilinx_xcvr_drp_read(xcvr, drp_port,
GTH34_QPLL_FBDIV(xcvr, sys_clk_sel));
if (val < 0)
return val;

Expand Down Expand Up @@ -896,23 +916,26 @@ static int xilinx_xcvr_gtx2_qpll_read_config(struct xilinx_xcvr *xcvr,
}

int xilinx_xcvr_qpll_read_config(struct xilinx_xcvr *xcvr,
unsigned int drp_port, struct xilinx_xcvr_qpll_config *conf)
unsigned int sys_clk_sel, unsigned int drp_port,
struct xilinx_xcvr_qpll_config *conf)
{
switch (xcvr->type) {
case XILINX_XCVR_TYPE_S7_GTX2:
return xilinx_xcvr_gtx2_qpll_read_config(xcvr, drp_port, conf);
case XILINX_XCVR_TYPE_US_GTH3:
case XILINX_XCVR_TYPE_US_GTH4:
case XILINX_XCVR_TYPE_US_GTY4:
return xilinx_xcvr_gth34_qpll_read_config(xcvr, drp_port, conf);
return xilinx_xcvr_gth34_qpll_read_config(xcvr, sys_clk_sel,
drp_port, conf);
default:
return -EINVAL;
}
}
EXPORT_SYMBOL_GPL(xilinx_xcvr_qpll_read_config);

static int xilinx_xcvr_gth34_qpll_write_config(struct xilinx_xcvr *xcvr,
unsigned int drp_port, const struct xilinx_xcvr_qpll_config *conf)
unsigned int sys_clk_sel, unsigned int drp_port,
const struct xilinx_xcvr_qpll_config *conf)
{
unsigned int refclk, fbdiv;
int ret;
Expand All @@ -938,13 +961,14 @@ static int xilinx_xcvr_gth34_qpll_write_config(struct xilinx_xcvr *xcvr,
return -EINVAL;
}

ret = xilinx_xcvr_drp_update(xcvr, drp_port, QPLL_FBDIV(conf->qpll),
0xff, fbdiv);
ret = xilinx_xcvr_drp_update(xcvr, drp_port,
GTH34_QPLL_FBDIV(xcvr, sys_clk_sel), 0xff, fbdiv);
if (ret < 0)
return ret;

return xilinx_xcvr_drp_update(xcvr, drp_port, QPLL_REFCLK_DIV(conf->qpll),
0xf80, refclk << 7);
return xilinx_xcvr_drp_update(xcvr, drp_port,
GTH34_QPLL_REFCLK_DIV(xcvr, sys_clk_sel),
0xf80, refclk << 7);
}

static int xilinx_xcvr_gtx2_qpll_write_config(struct xilinx_xcvr *xcvr,
Expand Down Expand Up @@ -1035,28 +1059,33 @@ static int xilinx_xcvr_gtx2_qpll_write_config(struct xilinx_xcvr *xcvr,
}

int xilinx_xcvr_qpll_write_config(struct xilinx_xcvr *xcvr,
unsigned int drp_port, const struct xilinx_xcvr_qpll_config *conf)
unsigned int sys_clk_sel, unsigned int drp_port,
const struct xilinx_xcvr_qpll_config *conf)
{
switch (xcvr->type) {
case XILINX_XCVR_TYPE_S7_GTX2:
return xilinx_xcvr_gtx2_qpll_write_config(xcvr, drp_port, conf);
case XILINX_XCVR_TYPE_US_GTH3:
case XILINX_XCVR_TYPE_US_GTH4:
case XILINX_XCVR_TYPE_US_GTY4:
return xilinx_xcvr_gth34_qpll_write_config(xcvr, drp_port, conf);
return xilinx_xcvr_gth34_qpll_write_config(xcvr, sys_clk_sel,
drp_port, conf);
default:
return -EINVAL;
}
}
EXPORT_SYMBOL_GPL(xilinx_xcvr_qpll_write_config);

int xilinx_xcvr_qpll_calc_lane_rate(struct xilinx_xcvr *xcvr,
unsigned int refclk_hz, const struct xilinx_xcvr_qpll_config *conf,
unsigned int sys_clk_sel, unsigned int refclk_hz,
const struct xilinx_xcvr_qpll_config *conf,
unsigned int out_div)
{
if (conf->refclk_div == 0 || out_div == 0)
return 0;

/* FIXME: do we need to use sys_clk_sel here ? */

return DIV_ROUND_CLOSEST_ULL((unsigned long long)refclk_hz * conf->fb_div,
conf->refclk_div * out_div * 1000);
}
Expand Down
14 changes: 8 additions & 6 deletions drivers/iio/jesd204/xilinx_transceiver.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ struct xilinx_xcvr_qpll_config {
unsigned int refclk_div;
unsigned int fb_div;
unsigned int band;
unsigned int qpll;
};

int xilinx_xcvr_configure_cdr(struct xilinx_xcvr *xcvr, unsigned int drp_port,
Expand All @@ -96,15 +95,18 @@ int xilinx_xcvr_cpll_calc_lane_rate(struct xilinx_xcvr *xcvr,
unsigned int out_div);

int xilinx_xcvr_calc_qpll_config(struct xilinx_xcvr *xcvr,
unsigned int refclk_hz, unsigned int lanerate_khz,
struct xilinx_xcvr_qpll_config *conf,
unsigned int sys_clk_sel, unsigned int refclk_hz,
unsigned int lanerate_khz, struct xilinx_xcvr_qpll_config *conf,
unsigned int *out_div);
int xilinx_xcvr_qpll_read_config(struct xilinx_xcvr *xcvr,
unsigned int drp_port, struct xilinx_xcvr_qpll_config *conf);
unsigned int drp_port, unsigned int sys_clk_sel,
struct xilinx_xcvr_qpll_config *conf);
int xilinx_xcvr_qpll_write_config(struct xilinx_xcvr *xcvr,
unsigned int drp_port, const struct xilinx_xcvr_qpll_config *conf);
unsigned int sys_clk_sell, unsigned int drp_port,
const struct xilinx_xcvr_qpll_config *conf);
int xilinx_xcvr_qpll_calc_lane_rate(struct xilinx_xcvr *xcvr,
unsigned int ref_clk_hz, const struct xilinx_xcvr_qpll_config *conf,
unsigned int sys_clk_sel, unsigned int ref_clk_hz,
const struct xilinx_xcvr_qpll_config *conf,
unsigned int out_div);

int xilinx_xcvr_read_out_div(struct xilinx_xcvr *xcvr, unsigned int drp_port,
Expand Down

0 comments on commit a335704

Please sign in to comment.