static int ad9523_setup()

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;
}