Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 61 additions & 33 deletions drivers/iio/frequency/adf4030.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,8 @@
u32 bsync_autoalign_iter;
u32 bsync_autoalign_theshold_fs;
u32 bsync_autoalign_ref_chan;
u32 bsync_freq_odiv_a;
u32 bsync_freq_odiv_b;
u64 bsync_freq_odiv_a_uhz;
u64 bsync_freq_odiv_b_uhz;
u32 avgexp;
bool bsync_autoalign_theshold_en;
unsigned int num_channels;
Expand Down Expand Up @@ -280,17 +280,16 @@
int ret;

ret = adf4030_compute_odiv(st->vco_freq, bsync_out_freq_uhz, &odiv);
fract = do_div(bsync_out_freq_uhz, MICROHZ_PER_HZ);
if (ret) {

fract = do_div(bsync_out_freq_uhz, MICROHZ_PER_HZ);
dev_err(&st->spi->dev,
"Failed to compute ODIVA for Fvco=%u Hz and Fbsync=%llu.%06u uHz\n",
st->vco_freq, bsync_out_freq_uhz, fract);

return ret;
}

st->bsync_freq_odiv_a = bsync_out_freq_uhz;
st->bsync_freq_odiv_a_uhz = bsync_out_freq_uhz;

ret = regmap_write(st->regmap, ADF4030_REG(0x53), odiv);
if (ret)
Expand Down Expand Up @@ -362,12 +361,14 @@
}

static int adf4030_tdc_measure(struct adf4030_state *st, u32 channel,
u32 source_channel, u32 source_out_freq_hz,
u32 source_channel, u64 source_out_freq_uhz,
s64 *result)
{
u32 raw_time_diff, m_time, regval;
int ret, time_diff;
s64 res_in_fs = 0;
u64 abs_time_diff;
bool is_negative;

ret = regmap_update_bits(st->regmap, ADF4030_REG(0x11),
ADF4030_TDC_SOURCE_MSK,
Expand Down Expand Up @@ -396,7 +397,7 @@
return ret;

m_time = DIV_ROUND_UP_ULL(1000000ULL * (1 << (st->avgexp + 6)),
source_out_freq_hz);
div_u64(source_out_freq_uhz, MICROHZ_PER_HZ));

fsleep(m_time);

Expand All @@ -406,7 +407,9 @@
ADF4030_MATH_BUSY_MSK)),
2000, 10000);
if (ret) {
dev_err(&st->spi->dev, "TDC measurement failed TDC_BUSY\n");
dev_err(&st->spi->dev,
"TDC measurement channel %d to channel %d failed TDC_BUSY\n",
channel, source_channel);
return ret;
}

Expand All @@ -421,16 +424,23 @@

raw_time_diff = (st->vals[2] << 16) | (st->vals[1] << 8) | st->vals[0];
time_diff = sign_extend32(raw_time_diff, 23);
res_in_fs = div_s64(time_diff * 1000000000LL, 1 << 24);
res_in_fs = div_s64(res_in_fs * 1000000LL, source_out_freq_hz);
is_negative = (time_diff < 0);
abs_time_diff = (u64)abs(time_diff);

/* Step 1: (abs_time_diff * 10^12) / 2^24 */
res_in_fs = mul_u64_u64_div_u64(abs_time_diff, 1000000000000ULL, 1ULL << 24);
/* Step 2: (res_in_fs * 10^9) / freq_uhz */
res_in_fs = mul_u64_u64_div_u64(res_in_fs, 1000000000ULL, source_out_freq_uhz);
if (is_negative)
res_in_fs = -res_in_fs;

*result = res_in_fs;

return 0;
}

static int adf4030_duty_cycle_measure(struct adf4030_state *st, u32 channel,
u32 source_out_freq_hz, u64 *result)
u64 source_out_freq_uhz, u64 *result)
{
u32 raw_time_diff, m_time, regval;
int ret;
Expand Down Expand Up @@ -462,7 +472,7 @@
return ret;

m_time = DIV_ROUND_UP_ULL(1000000ULL * (1 << (st->avgexp + 6)),
source_out_freq_hz);
div_u64(source_out_freq_uhz, MICROHZ_PER_HZ));

fsleep(m_time);

Expand All @@ -472,7 +482,9 @@
ADF4030_MATH_BUSY_MSK)),
2000, 10000);
if (ret) {
dev_err(&st->spi->dev, "TDC measurement failed TDC_BUSY\n");
dev_err(&st->spi->dev,
"TDC measurement channel %d failed TDC_BUSY\n",
channel);
return ret;
}

Expand Down Expand Up @@ -577,7 +589,9 @@
regval, !(regval & ADF4030_FSM_BUSY_MSK),
4000, 3000000);
if (ret) {
dev_err(&st->spi->dev, "Autoalign failed FSM_BUSY\n");
dev_err(&st->spi->dev,
"Autoalign channel %d to channel %d failed FSM_BUSY\n",
channel, source_channel);
return ret;
}
ret = regmap_read(st->regmap, ADF4030_REG(0x90), &regval);
Expand Down Expand Up @@ -666,7 +680,7 @@
case BSYNC_ALIGN_ITER:
return sysfs_emit(buf, "%u\n", st->bsync_autoalign_iter);
case BSYNC_DUTY_CYCLE:
ret = adf4030_duty_cycle_measure(st, ch->num, st->bsync_freq_odiv_a, &tdc_result);
ret = adf4030_duty_cycle_measure(st, ch->num, st->bsync_freq_odiv_a_uhz, &tdc_result);
if (ret)
return ret;

Expand Down Expand Up @@ -796,6 +810,7 @@
struct adf4030_state *st = iio_priv(indio_dev);
struct adf4030_chan_spec *ch;
s64 tdc_result;
u64 val_u64;
int ret;

ch = &st->channels[chan->address];
Expand All @@ -804,11 +819,12 @@

switch (mask) {
case IIO_CHAN_INFO_FREQUENCY:
*val = ch->odivb_en ? st->bsync_freq_odiv_b : st->bsync_freq_odiv_a;
val_u64 = ch->odivb_en ? st->bsync_freq_odiv_b_uhz : st->bsync_freq_odiv_a_uhz;
*val = div_u64(val_u64, MICROHZ_PER_HZ);
return IIO_VAL_INT;
case IIO_CHAN_INFO_PHASE:
ret = adf4030_tdc_measure(st, ch->num, ch->reference_chan,
st->bsync_freq_odiv_a, &tdc_result);
st->bsync_freq_odiv_a_uhz, &tdc_result);
if (ret)
return ret;

Expand Down Expand Up @@ -923,15 +939,17 @@
struct iio_chan_spec *chan;
struct adf4030_chan_spec *ch;
unsigned int address;
u64 val_u64;

address = clkout->address;
if (address >= st->num_channels)
return -EINVAL;

chan = &st->iio_channels[address];
ch = &st->channels[chan->address];
val_u64 = ch->odivb_en ? st->bsync_freq_odiv_b_uhz : st->bsync_freq_odiv_a_uhz;

return ch->odivb_en ? st->bsync_freq_odiv_b : st->bsync_freq_odiv_a;
return div_u64(val_u64, MICROHZ_PER_HZ);
}

static const struct clk_ops adf4030_clk_ops = {
Expand Down Expand Up @@ -1039,7 +1057,7 @@

bsync_freq_uHz = (u64)rate * MICROHZ_PER_HZ + ret;

if (rate != st->bsync_freq_odiv_a) {
if (bsync_freq_uHz != st->bsync_freq_odiv_a_uhz) {
ret = adf4030_set_odiva_freq(st, bsync_freq_uHz);
if (ret)
return ret;
Expand Down Expand Up @@ -1211,17 +1229,16 @@
if (ret)
return dev_err_probe(&st->spi->dev, ret, "PLL failed to lock\n");

ret = adf4030_set_odiva_freq(st, (u64)st->bsync_freq_odiv_a * MICROHZ_PER_HZ);
ret = adf4030_set_odiva_freq(st, (u64)st->bsync_freq_odiv_a_uhz);
if (ret)
return ret;

if (st->bsync_freq_odiv_b) {
ret = adf4030_compute_odiv(vco_out_freq_hz,
(u64)st->bsync_freq_odiv_b * MICROHZ_PER_HZ, &odiv);
if (st->bsync_freq_odiv_b_uhz) {
ret = adf4030_compute_odiv(vco_out_freq_hz, st->bsync_freq_odiv_b_uhz, &odiv);
if (ret)
return dev_err_probe(&st->spi->dev, ret,
"Failed to compute ODIVB for Fvco=%u Hz and Fbsync=%u Hz\n",
vco_out_freq_hz, st->bsync_freq_odiv_b);
"Failed to compute ODIVB for Fvco=%u Hz and Fbsync=%llu uHz\n",
vco_out_freq_hz, st->bsync_freq_odiv_b_uhz);

ret = regmap_write(st->regmap, ADF4030_REG(0x55), odiv >> 4);
if (ret)
Expand All @@ -1235,7 +1252,7 @@
}

/* Set some defaults based datasheets limits */
if (st->bsync_freq_odiv_a > 2000000U)
if (st->bsync_freq_odiv_a_uhz > 2000000000000ULL)
st->avgexp = 15;
else
st->avgexp = 13;
Expand All @@ -1254,6 +1271,7 @@
struct device *dev = &st->spi->dev;
unsigned int i, cnt = 0;
int ret;
u32 val;

st->spi_3wire_en = device_property_read_bool(dev,
"adi,spi-3wire-enable");
Expand All @@ -1264,14 +1282,24 @@
return dev_err_probe(dev, -EINVAL,
"Missing mandatoy adi,vco-frequency-hz property");

ret = device_property_read_u32(dev, "adi,bsync-frequency-hz",
&st->bsync_freq_odiv_a);
if (ret)
return dev_err_probe(dev, -EINVAL,
"Missing mandatoy adi,bsync-frequency-hz property");
ret = device_property_read_u64(dev, "adi,bsync-frequency-uhz",
&st->bsync_freq_odiv_a_uhz);
if (ret) {

Check warning on line 1287 in drivers/iio/frequency/adf4030.c

View workflow job for this annotation

GitHub Actions / checks / checks

checkpatch: No space is necessary after a cast + st->bsync_freq_odiv_a_uhz = (u64) val * MICROHZ_PER_HZ;
ret = device_property_read_u32(dev, "adi,bsync-frequency-hz", &val);
if (ret)
return dev_err_probe(dev, -EINVAL,
"Missing mandatoy adi,bsync-frequency-hz property");

st->bsync_freq_odiv_a_uhz = (u64) val * MICROHZ_PER_HZ;
}

Check warning on line 1295 in drivers/iio/frequency/adf4030.c

View workflow job for this annotation

GitHub Actions / checks / checks

checkpatch: No space is necessary after a cast + st->bsync_freq_odiv_b_uhz = (u64) val * MICROHZ_PER_HZ;
device_property_read_u32(dev, "adi,bsync-secondary-frequency-hz",
&st->bsync_freq_odiv_b);
ret = device_property_read_u64(dev, "adi,bsync-secondary-frequency-uhz",
&st->bsync_freq_odiv_b_uhz);
if (ret) {
ret = device_property_read_u32(dev, "adi,bsync-secondary-frequency-hz", &val);
if (!ret)
st->bsync_freq_odiv_b_uhz = (u64) val * MICROHZ_PER_HZ;
}

ret = device_property_read_u32(dev, "adi,bsync-autoalign-reference-channel",
&st->bsync_autoalign_ref_chan);
Expand Down
Loading