in frequency/ad9523.c [758:970]
static int ad9523_setup(struct iio_dev *indio_dev)
{
struct ad9523_state *st = iio_priv(indio_dev);
struct ad9523_platform_data *pdata = st->pdata;
struct ad9523_channel_spec *chan;
unsigned long active_mask = 0;
int ret, i;
ret = ad9523_write(indio_dev, AD9523_SERIAL_PORT_CONFIG,
AD9523_SER_CONF_SOFT_RESET |
(st->spi->mode & SPI_3WIRE ? 0 :
AD9523_SER_CONF_SDO_ACTIVE));
if (ret < 0)
return ret;
ret = ad9523_write(indio_dev, AD9523_READBACK_CTRL,
AD9523_READBACK_CTRL_READ_BUFFERED);
if (ret < 0)
return ret;
ret = ad9523_io_update(indio_dev);
if (ret < 0)
return ret;
/*
* PLL1 Setup
*/
ret = ad9523_write(indio_dev, AD9523_PLL1_REF_A_DIVIDER,
pdata->refa_r_div);
if (ret < 0)
return ret;
ret = ad9523_write(indio_dev, AD9523_PLL1_REF_B_DIVIDER,
pdata->refb_r_div);
if (ret < 0)
return ret;
ret = ad9523_write(indio_dev, AD9523_PLL1_FEEDBACK_DIVIDER,
pdata->pll1_feedback_div);
if (ret < 0)
return ret;
ret = ad9523_write(indio_dev, AD9523_PLL1_CHARGE_PUMP_CTRL,
AD9523_PLL1_CHARGE_PUMP_CURRENT_nA(pdata->
pll1_charge_pump_current_nA) |
AD9523_PLL1_CHARGE_PUMP_MODE_NORMAL |
AD9523_PLL1_BACKLASH_PW_MIN);
if (ret < 0)
return ret;
ret = ad9523_write(indio_dev, AD9523_PLL1_INPUT_RECEIVERS_CTRL,
AD_IF(refa_diff_rcv_en, AD9523_PLL1_REFA_RCV_EN) |
AD_IF(refb_diff_rcv_en, AD9523_PLL1_REFB_RCV_EN) |
AD_IF(osc_in_diff_en, AD9523_PLL1_OSC_IN_DIFF_EN) |
AD_IF(osc_in_cmos_neg_inp_en,
AD9523_PLL1_OSC_IN_CMOS_NEG_INP_EN) |
AD_IF(refa_diff_rcv_en, AD9523_PLL1_REFA_DIFF_RCV_EN) |
AD_IF(refb_diff_rcv_en, AD9523_PLL1_REFB_DIFF_RCV_EN));
if (ret < 0)
return ret;
ret = ad9523_write(indio_dev, AD9523_PLL1_REF_CTRL,
AD_IF(zd_in_diff_en, AD9523_PLL1_ZD_IN_DIFF_EN) |
AD_IF(zd_in_cmos_neg_inp_en,
AD9523_PLL1_ZD_IN_CMOS_NEG_INP_EN) |
AD_IF(zero_delay_mode_internal_en,
AD9523_PLL1_ZERO_DELAY_MODE_INT) |
AD_IF(osc_in_feedback_en, AD9523_PLL1_OSC_IN_PLL_FEEDBACK_EN) |
AD_IF(refa_cmos_neg_inp_en, AD9523_PLL1_REFA_CMOS_NEG_INP_EN) |
AD_IF(refb_cmos_neg_inp_en, AD9523_PLL1_REFB_CMOS_NEG_INP_EN));
if (ret < 0)
return ret;
ret = ad9523_write(indio_dev, AD9523_PLL1_MISC_CTRL,
AD9523_PLL1_REFB_INDEP_DIV_CTRL_EN |
AD9523_PLL1_REF_MODE(pdata->ref_mode));
if (ret < 0)
return ret;
ret = ad9523_write(indio_dev, AD9523_PLL1_LOOP_FILTER_CTRL,
AD9523_PLL1_LOOP_FILTER_RZERO(pdata->pll1_loop_filter_rzero));
if (ret < 0)
return ret;
/*
* PLL2 Setup
*/
ret = ad9523_write(indio_dev, AD9523_PLL2_CHARGE_PUMP,
AD9523_PLL2_CHARGE_PUMP_CURRENT_nA(pdata->
pll2_charge_pump_current_nA));
if (ret < 0)
return ret;
ret = ad9523_write(indio_dev, AD9523_PLL2_FEEDBACK_DIVIDER_AB,
AD9523_PLL2_FB_NDIV_A_CNT(pdata->pll2_ndiv_a_cnt) |
AD9523_PLL2_FB_NDIV_B_CNT(pdata->pll2_ndiv_b_cnt));
if (ret < 0)
return ret;
ret = ad9523_write(indio_dev, AD9523_PLL2_CTRL,
AD9523_PLL2_CHARGE_PUMP_MODE_NORMAL |
AD9523_PLL2_BACKLASH_CTRL_EN |
AD_IF(pll2_freq_doubler_en, AD9523_PLL2_FREQ_DOUBLER_EN));
if (ret < 0)
return ret;
st->vco_freq = div_u64((unsigned long long)pdata->vcxo_freq *
(pdata->pll2_freq_doubler_en ? 2 : 1) *
AD9523_PLL2_FB_NDIV(pdata->pll2_ndiv_a_cnt,
pdata->pll2_ndiv_b_cnt),
pdata->pll2_r2_div);
ret = ad9523_write(indio_dev, AD9523_PLL2_VCO_CTRL,
AD9523_PLL2_VCO_CALIBRATE);
if (ret < 0)
return ret;
ret = ad9523_write(indio_dev, AD9523_PLL2_VCO_DIVIDER,
AD9523_PLL2_VCO_DIV_M1(pdata->pll2_vco_div_m1) |
AD9523_PLL2_VCO_DIV_M2(pdata->pll2_vco_div_m2) |
AD_IFE(pll2_vco_div_m1, 0,
AD9523_PLL2_VCO_DIV_M1_PWR_DOWN_EN) |
AD_IFE(pll2_vco_div_m2, 0,
AD9523_PLL2_VCO_DIV_M2_PWR_DOWN_EN));
if (ret < 0)
return ret;
if (pdata->pll2_vco_div_m1)
st->vco_out_freq[AD9523_VCO1] =
st->vco_freq / pdata->pll2_vco_div_m1;
if (pdata->pll2_vco_div_m2)
st->vco_out_freq[AD9523_VCO2] =
st->vco_freq / pdata->pll2_vco_div_m2;
st->vco_out_freq[AD9523_VCXO] = pdata->vcxo_freq;
ret = ad9523_write(indio_dev, AD9523_PLL2_R2_DIVIDER,
AD9523_PLL2_R2_DIVIDER_VAL(pdata->pll2_r2_div));
if (ret < 0)
return ret;
ret = ad9523_write(indio_dev, AD9523_PLL2_LOOP_FILTER_CTRL,
AD9523_PLL2_LOOP_FILTER_CPOLE1(pdata->cpole1) |
AD9523_PLL2_LOOP_FILTER_RZERO(pdata->rzero) |
AD9523_PLL2_LOOP_FILTER_RPOLE2(pdata->rpole2) |
AD_IF(rzero_bypass_en,
AD9523_PLL2_LOOP_FILTER_RZERO_BYPASS_EN));
if (ret < 0)
return ret;
for (i = 0; i < pdata->num_channels; i++) {
chan = &pdata->channels[i];
if (chan->channel_num < AD9523_NUM_CHAN) {
__set_bit(chan->channel_num, &active_mask);
ret = ad9523_write(indio_dev,
AD9523_CHANNEL_CLOCK_DIST(chan->channel_num),
AD9523_CLK_DIST_DRIVER_MODE(chan->driver_mode) |
AD9523_CLK_DIST_DIV(chan->channel_divider) |
AD9523_CLK_DIST_DIV_PHASE(chan->divider_phase) |
(chan->sync_ignore_en ?
AD9523_CLK_DIST_IGNORE_SYNC_EN : 0) |
(chan->divider_output_invert_en ?
AD9523_CLK_DIST_INV_DIV_OUTPUT_EN : 0) |
(chan->low_power_mode_en ?
AD9523_CLK_DIST_LOW_PWR_MODE_EN : 0) |
(chan->output_dis ?
AD9523_CLK_DIST_PWR_DOWN_EN : 0));
if (ret < 0)
return ret;
ret = ad9523_vco_out_map(indio_dev, chan->channel_num,
chan->use_alt_clock_src);
if (ret < 0)
return ret;
st->ad9523_channels[i].type = IIO_ALTVOLTAGE;
st->ad9523_channels[i].output = 1;
st->ad9523_channels[i].indexed = 1;
st->ad9523_channels[i].channel = chan->channel_num;
st->ad9523_channels[i].extend_name =
chan->extended_name;
st->ad9523_channels[i].info_mask_separate =
BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_PHASE) |
BIT(IIO_CHAN_INFO_FREQUENCY);
}
}
for_each_clear_bit(i, &active_mask, AD9523_NUM_CHAN) {
ret = ad9523_write(indio_dev,
AD9523_CHANNEL_CLOCK_DIST(i),
AD9523_CLK_DIST_DRIVER_MODE(TRISTATE) |
AD9523_CLK_DIST_PWR_DOWN_EN);
if (ret < 0)
return ret;
}
ret = ad9523_write(indio_dev, AD9523_POWER_DOWN_CTRL, 0);
if (ret < 0)
return ret;
ret = ad9523_write(indio_dev, AD9523_STATUS_SIGNALS,
AD9523_STATUS_MONITOR_01_PLL12_LOCKED);
if (ret < 0)
return ret;
ret = ad9523_io_update(indio_dev);
if (ret < 0)
return ret;
return 0;
}