/** * Setup the AD9361 device. * @param phy The AD9361 state structure. * @return 0 in case of success, negative error code otherwise. */ int32_t ad9361_post_setup(struct ad9361_rf_phy *phy) { struct axiadc_converter *conv = phy->adc_conv; struct axiadc_state *st = phy->adc_state; int32_t rx2tx2 = phy->pdata->rx2tx2; int32_t tmp, num_chan, flags; int32_t i, ret; num_chan = (conv->chip_info->num_channels > 4) ? 4 : conv->chip_info->num_channels; axiadc_write(st, ADI_REG_CNTRL, rx2tx2 ? 0 : ADI_R1_MODE); tmp = axiadc_read(st, 0x4048); if (!rx2tx2) { axiadc_write(st, 0x4048, tmp | BIT(5)); /* R1_MODE */ axiadc_write(st, 0x404c, (phy->pdata->port_ctrl.pp_conf[2] & LVDS_MODE) ? 1 : 0); /* RATE */ } else { tmp &= ~BIT(5); axiadc_write(st, 0x4048, tmp); axiadc_write(st, 0x404c, (phy->pdata->port_ctrl.pp_conf[2] & LVDS_MODE) ? 3 : 1); /* RATE */ } #ifdef ALTERA_PLATFORM axiadc_write(st, 0x404c, 1); #endif for (i = 0; i < num_chan; i++) { axiadc_write(st, ADI_REG_CHAN_CNTRL_1(i), ADI_DCFILT_OFFSET(0)); axiadc_write(st, ADI_REG_CHAN_CNTRL_2(i), (i & 1) ? 0x00004000 : 0x40000000); axiadc_write(st, ADI_REG_CHAN_CNTRL(i), ADI_FORMAT_SIGNEXT | ADI_FORMAT_ENABLE | ADI_ENABLE | ADI_IQCOR_ENB); } flags = 0x0; ret = ad9361_dig_tune(phy, ((conv->chip_info->num_channels > 4) || axiadc_read(st, 0x0004)) ? 0 : 61440000, flags); if (ret < 0) return ret; if (flags & (DO_IDELAY | DO_ODELAY)) { ret = ad9361_dig_tune(phy, (axiadc_read(st, ADI_REG_ID)) ? 0 : 61440000, flags & BE_VERBOSE); if (ret < 0) return ret; } ret = ad9361_set_trx_clock_chain(phy, phy->pdata->rx_path_clks, phy->pdata->tx_path_clks); ad9361_ensm_force_state(phy, ENSM_STATE_ALERT); ad9361_ensm_restore_prev_state(phy); return ret; }
static int axiadc_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan, int *val, int *val2, long m) { struct axiadc_state *st = iio_priv(indio_dev); struct axiadc_converter *conv = to_converter(st->dev_spi); int ret, sign; unsigned tmp, phase = 0; unsigned long long llval; switch (m) { case IIO_CHAN_INFO_CALIBPHASE: phase = 1; case IIO_CHAN_INFO_CALIBSCALE: tmp = axiadc_read(st, ADI_REG_CHAN_CNTRL_2(chan->channel)); /* format is 1.1.14 (sign, integer and fractional bits) */ if (!((phase + chan->channel) % 2)) { tmp = ADI_TO_IQCOR_COEFF_1(tmp); } else { tmp = ADI_TO_IQCOR_COEFF_2(tmp); } if (tmp & 0x8000) sign = -1; else sign = 1; if (tmp & 0x4000) *val = 1 * sign; else *val = 0; tmp &= ~0xC000; llval = tmp * 1000000ULL + (0x4000 / 2); do_div(llval, 0x4000); if (*val == 0) *val2 = llval * sign; else *val2 = llval; return IIO_VAL_INT_PLUS_MICRO; case IIO_CHAN_INFO_CALIBBIAS: tmp = axiadc_read(st, ADI_REG_CHAN_CNTRL_1(chan->channel)); *val = (short)ADI_TO_DCFILT_OFFSET(tmp); return IIO_VAL_INT; case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY: /* * approx: F_cut = C * Fsample / (2 * pi) */ tmp = axiadc_read(st, ADI_REG_CHAN_CNTRL(chan->channel)); if (!(tmp & ADI_DCFILT_ENB)) { *val = 0; return IIO_VAL_INT; } tmp = axiadc_read(st, ADI_REG_CHAN_CNTRL_1(chan->channel)); llval = ADI_TO_DCFILT_COEFF(tmp) * (unsigned long long)conv->adc_clk; do_div(llval, 102944); /* 2 * pi * 0x4000 */ *val = llval; return IIO_VAL_INT; case IIO_CHAN_INFO_SAMP_FREQ: ret = conv->read_raw(indio_dev, chan, val, val2, m); if (ret < 0 || !*val) { tmp = ADI_TO_CLK_FREQ(axiadc_read(st, ADI_REG_CLK_FREQ)); llval = tmp * 100000000ULL /* FIXME */ * ADI_TO_CLK_RATIO(axiadc_read(st, ADI_REG_CLK_RATIO)); *val = llval >> 16; } if (chan->extend_name) { tmp = axiadc_read(st, ADI_REG_CHAN_USR_CNTRL_2(chan->channel)); llval = ADI_TO_USR_DECIMATION_M(tmp) * conv->adc_clk; do_div(llval, ADI_TO_USR_DECIMATION_N(tmp)); *val = llval; } return IIO_VAL_INT; default: return conv->read_raw(indio_dev, chan, val, val2, m); }