ad9523.c
  1  /***************************************************************************//**
  2   *   @file   AD9523.c
  3   *   @brief  Implementation of AD9523 Driver.
  4   *   @author ACozma(andrei.cozma@analog.com)
  5   ********************************************************************************
  6   * Copyright 2012-2016(c) Analog Devices, Inc.
  7   *
  8   * Redistribution and use in source and binary forms, with or without
  9   * modification, are permitted provided that the following conditions are met:
 10   *
 11   * 1. Redistributions of source code must retain the above copyright notice,
 12   *    this list of conditions and the following disclaimer.
 13   *
 14   * 2. Redistributions in binary form must reproduce the above copyright notice,
 15   *    this list of conditions and the following disclaimer in the documentation
 16   *    and/or other materials provided with the distribution.
 17   *
 18   * 3. Neither the name of Analog Devices, Inc. nor the names of its
 19   *    contributors may be used to endorse or promote products derived from this
 20   *    software without specific prior written permission.
 21   *
 22   * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. “AS IS” AND ANY EXPRESS OR
 23   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 24   * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
 25   * EVENT SHALL ANALOG DEVICES, INC. BE LIABLE FOR ANY DIRECT, INDIRECT,
 26   * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 27   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 28   * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 29   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 30   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 31   * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 32   *
 33   *******************************************************************************/
 34  
 35  #include <stdlib.h>
 36  #include <stdio.h>
 37  #include "ad9523.h"
 38  #include "no_os_alloc.h"
 39  
 40  /* Helpers to avoid excess line breaks */
 41  #define AD_IFE(_pde, _a, _b) ((dev->pdata->_pde) ? _a : _b)
 42  #define AD_IF(_pde, _a) AD_IFE(_pde, _a, 0)
 43  
 44  /***************************************************************************//**
 45   * @brief Reads the value of the selected register.
 46   *
 47   * @param dev - The device structure.
 48   * @param reg_addr - The address of the register to read.
 49   * @param reg_data - Pointer to the read value.
 50  
 51   * @return Returns 0 in case of success or negative error code.
 52   *******************************************************************************/
 53  int32_t ad9523_spi_read(struct ad9523_dev *dev,
 54  			uint32_t reg_addr,
 55  			uint32_t *reg_data)
 56  {
 57  	uint8_t buf[3];
 58  
 59  	int32_t ret = 0;
 60  	uint8_t index;
 61  
 62  	*reg_data = 0;
 63  	for (index = 0; index < AD9523_TRANSF_LEN(reg_addr); index++) {
 64  		buf[0] = 0x80 | (reg_addr >> 8);
 65  		buf[1] = reg_addr & 0xFF;
 66  		buf[2] = 0x00;
 67  		ret |= no_os_spi_write_and_read(dev->spi_desc,
 68  						buf,
 69  						3);
 70  		reg_addr--;
 71  		*reg_data <<= 8;
 72  		*reg_data |= buf[2];
 73  	}
 74  
 75  	return ret;
 76  }
 77  
 78  /***************************************************************************//**
 79   * @brief Writes a value to the selected register.
 80   *
 81   * @param dev - The device structure.
 82   * @param reg_addr - The address of the register to write to.
 83   * @param reg_data - The value to write to the register.
 84   *
 85   * @return Returns 0 in case of success or negative error code.
 86   *******************************************************************************/
 87  int32_t ad9523_spi_write(struct ad9523_dev *dev,
 88  			 uint32_t reg_addr,
 89  			 uint32_t reg_data)
 90  {
 91  	uint8_t buf[3];
 92  
 93  	int32_t ret = 0;
 94  	uint8_t index;
 95  
 96  	for (index = 0; index < AD9523_TRANSF_LEN(reg_addr); index++) {
 97  		buf[0] = reg_addr >> 8;
 98  		buf[1] = reg_addr & 0xFF;
 99  		buf[2] = (reg_data >> ((AD9523_TRANSF_LEN(reg_addr) - index - 1) * 8)) & 0xFF;
100  		ret |= no_os_spi_write_and_read(dev->spi_desc,
101  						buf,
102  						3);
103  		reg_addr--;
104  	}
105  
106  	return ret;
107  }
108  
109  /***************************************************************************//**
110   * @brief Updates the AD9523 configuration
111   *
112   * @param dev - The device structure.
113   *
114   * @return Returns 0 in case of success or negative error code.
115   *******************************************************************************/
116  int32_t ad9523_io_update(struct ad9523_dev *dev)
117  {
118  	return ad9523_spi_write(dev,
119  				AD9523_IO_UPDATE,
120  				AD9523_IO_UPDATE_EN);
121  }
122  
123  /***************************************************************************//**
124   * @brief Sets the clock provider for selected channel.
125   *
126   * @param dev - The device structure.
127   * @param ch - Selected channel.
128   * @param out - Selected clock provider.
129   *
130   * @return Returns 0 in case of success or negative error code.
131   *******************************************************************************/
132  int32_t ad9523_vco_out_map(struct ad9523_dev *dev,
133  			   uint32_t ch,
134  			   uint32_t out)
135  {
136  	int32_t ret;
137  	uint32_t mask;
138  	uint32_t reg_data;
139  
140  	switch (ch) {
141  	case 0 ... 3:
142  		ret = ad9523_spi_read(dev,
143  				      AD9523_PLL1_OUTPUT_CHANNEL_CTRL,
144  				      &reg_data);
145  		if (ret < 0)
146  			break;
147  		mask = AD9523_PLL1_OUTP_CH_CTRL_VCXO_SRC_SEL_CH0 << ch;
148  		if (out) {
149  			reg_data |= mask;
150  			out = AD9523_VCXO;
151  		} else {
152  			reg_data &= ~mask;
153  		}
154  		ret = ad9523_spi_write(dev,
155  				       AD9523_PLL1_OUTPUT_CHANNEL_CTRL,
156  				       reg_data);
157  		break;
158  	case 4 ... 6:
159  		ret = ad9523_spi_read(dev,
160  				      AD9523_PLL1_OUTPUT_CTRL,
161  				      &reg_data);
162  		if (ret < 0)
163  			break;
164  		mask = AD9523_PLL1_OUTP_CTRL_VCO_DIV_SEL_CH4_M2 << (ch - 4);
165  		if (out)
166  			reg_data |= mask;
167  		else
168  			reg_data &= ~mask;
169  		ret = ad9523_spi_write(dev,
170  				       AD9523_PLL1_OUTPUT_CTRL,
171  				       reg_data);
172  		break;
173  	case 7 ... 9:
174  		ret = ad9523_spi_read(dev,
175  				      AD9523_PLL1_OUTPUT_CHANNEL_CTRL,
176  				      &reg_data);
177  		if (ret < 0)
178  			break;
179  		mask = AD9523_PLL1_OUTP_CH_CTRL_VCO_DIV_SEL_CH7_M2 << (ch - 7);
180  		if (out)
181  			reg_data |= mask;
182  		else
183  			reg_data &= ~mask;
184  		ret = ad9523_spi_write(dev,
185  				       AD9523_PLL1_OUTPUT_CHANNEL_CTRL,
186  				       reg_data);
187  		break;
188  	default:
189  		return 0;
190  	}
191  
192  	dev->ad9523_st.vco_out_map[ch] = out;
193  
194  	return ret;
195  }
196  
197  /***************************************************************************//**
198   * @brief Updates the AD9523 configuration.
199   *
200   * @return Returns 0 in case of success or negative error code.
201   *******************************************************************************/
202  
203  // vco calibration on default setup may not work (as it is a buffered write)
204  // calibration requires all registers to be written (not in hold registers) first.
205  
206  int32_t ad9523_calibrate(struct ad9523_dev *dev)
207  {
208  	uint32_t reg_data;
209  	uint32_t timeout;
210  
211  	ad9523_spi_write(dev,
212  			 AD9523_PLL2_VCO_CTRL,
213  			 AD9523_PLL2_VCO_CALIBRATE);
214  	ad9523_io_update(dev);
215  
216  	timeout = 0;
217  	while (timeout < 100) {
218  		no_os_mdelay(1);
219  		timeout = timeout + 1;
220  		ad9523_spi_read(dev,
221  				AD9523_READBACK_1,
222  				&reg_data);
223  		if ((reg_data & 0x1) == 0x0)
224  			break;
225  	}
226  	ad9523_spi_read(dev,
227  			AD9523_READBACK_1,
228  			&reg_data);
229  	if ((reg_data & 0x1) != 0x0) {
230  		printf("AD9523: VCO calibration failed (%#06lx)!\n", reg_data);
231  		return (-1);
232  	}
233  
234  	return (0);
235  }
236  
237  /***************************************************************************//**
238   * @brief Updates the AD9523 configuration.
239   *
240   * @param dev - The device structure.
241   *
242   * @return Returns 0 in case of success or negative error code.
243   *******************************************************************************/
244  
245  // status
246  // calibration requires all registers to be written (not in hold registers) first.
247  
248  int32_t ad9523_status(struct ad9523_dev *dev)
249  {
250  	int32_t ret;
251  	uint32_t reg_data;
252  	uint32_t status;
253  	uint32_t timeout;
254  
255  	status = 0;
256  
257  	// vcxo + pll2 must always be okay- (is it not?)
258  
259  	status = status | AD9523_READBACK_0_STAT_VCXO;
260  	status = status | AD9523_READBACK_0_STAT_PLL2_LD;
261  
262  	if (dev->pdata->pll1_bypass_en == 0) {
263  		status = status | AD9523_READBACK_0_STAT_PLL2_REF_CLK;
264  		status = status | AD9523_READBACK_0_STAT_PLL2_FB_CLK;
265  		status = status | AD9523_READBACK_0_STAT_REF_TEST;
266  		status = status | AD9523_READBACK_0_STAT_REFB;
267  		status = status | AD9523_READBACK_0_STAT_REFA;
268  		status = status | AD9523_READBACK_0_STAT_PLL1_LD;
269  	}
270  
271  	timeout = 0;
272  	while (timeout < 100) {
273  		no_os_mdelay(1);
274  		timeout = timeout + 1;
275  		ad9523_spi_read(dev,
276  				AD9523_READBACK_0,
277  				&reg_data);
278  		if ((reg_data & status) == status)
279  			break;
280  	}
281  
282  	ret = 0;
283  	if ((reg_data & AD9523_READBACK_0_STAT_VCXO) != AD9523_READBACK_0_STAT_VCXO) {
284  		printf("AD9523: VCXO status errors (%#06lx)!\n", reg_data);
285  		ret = -1;
286  	}
287  
288  	if ((reg_data & AD9523_READBACK_0_STAT_PLL2_LD) !=
289  	    AD9523_READBACK_0_STAT_PLL2_LD) {
290  		printf("AD9523: PLL2 NOT locked (%#06lx)!\n", reg_data);
291  		ret = -1;
292  	}
293  
294  	return (ret);
295  }
296  
297  /***************************************************************************//**
298   * @brief Updates the AD9523 configuration.
299   *
300   * @param dev - The device structure.
301   *
302   * @return Returns 0 in case of success or negative error code.
303   *******************************************************************************/
304  int32_t ad9523_sync(struct ad9523_dev *dev)
305  {
306  	int32_t ret, tmp;
307  	uint32_t reg_data;
308  
309  	ret = ad9523_spi_read(dev,
310  			      AD9523_STATUS_SIGNALS,
311  			      &reg_data);
312  	if (ret < 0)
313  		return ret;
314  
315  	tmp = reg_data;
316  	tmp |= AD9523_STATUS_SIGNALS_SYNC_MAN_CTRL;
317  
318  	ret = ad9523_spi_write(dev,
319  			       AD9523_STATUS_SIGNALS,
320  			       tmp);
321  	if (ret < 0)
322  		return ret;
323  
324  	ad9523_io_update(dev);
325  	tmp &= ~AD9523_STATUS_SIGNALS_SYNC_MAN_CTRL;
326  
327  	ret = ad9523_spi_write(dev,
328  			       AD9523_STATUS_SIGNALS,
329  			       tmp);
330  	if (ret < 0)
331  		return ret;
332  
333  	return ad9523_io_update(dev);
334  
335  }
336  
337  /***************************************************************************//**
338   * @brief Initialize the AD9523 data structure with the default register values.
339   *
340   * @param init_param - The device initial parameters.
341   *
342   * @return Always return 0.
343   *******************************************************************************/
344  int32_t ad9523_init(struct ad9523_init_param *init_param)
345  {
346  
347  	int32_t i = 0;
348  
349  	init_param->pdata->vcxo_freq = 0;
350  	init_param->pdata->spi3wire = 0;
351  
352  	/* Differential/ Single-Ended Input Configuration */
353  	init_param->pdata->refa_diff_rcv_en = 0;
354  	init_param->pdata->refb_diff_rcv_en = 0;
355  	init_param->pdata->zd_in_diff_en = 0;
356  	init_param->pdata->osc_in_diff_en = 0;
357  
358  	/*
359  	 * Valid if differential input disabled
360  	 * if not true defaults to pos input
361  	 */
362  	init_param->pdata->refa_cmos_neg_inp_en = 0;
363  	init_param->pdata->refb_cmos_neg_inp_en = 0;
364  	init_param->pdata->zd_in_cmos_neg_inp_en = 0;
365  	init_param->pdata->osc_in_cmos_neg_inp_en = 0;
366  
367  	/* PLL1 Setting */
368  	init_param->pdata->refa_r_div = 1;
369  	init_param->pdata->refb_r_div = 1;
370  	init_param->pdata->pll1_feedback_div = 1;
371  	init_param->pdata->pll1_charge_pump_current_nA = 0;
372  	init_param->pdata->zero_delay_mode_internal_en = 0;
373  	init_param->pdata->osc_in_feedback_en = 0;
374  	init_param->pdata->pll1_bypass_en = 1;
375  	init_param->pdata->pll1_loop_filter_rzero = 1;
376  
377  	/* Reference */
378  	init_param->pdata->ref_mode = 0;
379  
380  	/* PLL2 Setting */
381  	init_param->pdata->pll2_charge_pump_current_nA = 0;
382  	init_param->pdata->pll2_ndiv_a_cnt = 0;
383  	init_param->pdata->pll2_ndiv_b_cnt = 4;
384  	init_param->pdata->pll2_freq_doubler_en = 0;
385  	init_param->pdata->pll2_r2_div = 0;
386  	init_param->pdata->pll2_vco_diff_m1 = 0; /* 3..5 */
387  	init_param->pdata->pll2_vco_diff_m2 = 0; /* 3..5 */
388  
389  	/* Loop Filter PLL2 */
390  	init_param->pdata->rpole2 = 0;
391  	init_param->pdata->rzero = 0;
392  	init_param->pdata->cpole1 = 0;
393  	init_param->pdata->rzero_bypass_en = 0;
394  
395  	/* Output Channel Configuration */
396  	for (i = 0; i < init_param->pdata->num_channels; i++) {
397  		(&init_param->pdata->channels[i])->channel_num = 0;
398  		(&init_param->pdata->channels[i])->divider_output_invert_en = 0;
399  		(&init_param->pdata->channels[i])->sync_ignore_en = 0;
400  		(&init_param->pdata->channels[i])->low_power_mode_en = 0;
401  		(&init_param->pdata->channels[i])->use_alt_clock_src = 0;
402  		(&init_param->pdata->channels[i])->output_dis = 0;
403  		(&init_param->pdata->channels[i])->driver_mode = LVPECL_8mA;
404  		(&init_param->pdata->channels[i])->divider_phase = 0;
405  		(&init_param->pdata->channels[i])->channel_divider = 0;
406  	}
407  	return 0;
408  }
409  
410  
411  /***************************************************************************//**
412   * @brief Setup the AD9523 device.
413   *
414   * @param device - The device structure.
415   * @param init_param - The structure holding the device initial parameters.
416   *
417   * @return Returns 0 in case of success or negative error code.
418   *******************************************************************************/
419  int32_t ad9523_setup(struct ad9523_dev **device,
420  		     const struct ad9523_init_param *init_param)
421  
422  {
423  	struct ad9523_channel_spec *chan;
424  	uint32_t active_mask = 0;
425  	int32_t ret, i;
426  	uint32_t reg_data;
427  	uint32_t version_id;
428  	struct ad9523_dev *dev;
429  
430  	dev = (struct ad9523_dev *)no_os_malloc(sizeof(*dev));
431  	if (!dev)
432  		return -1;
433  
434  	/* SPI */
435  	ret = no_os_spi_init(&dev->spi_desc, &init_param->spi_init);
436  	if (ret < 0)
437  		return ret;
438  
439  	dev->pdata = init_param->pdata;
440  
441  	ret = ad9523_spi_write(dev,
442  			       AD9523_SERIAL_PORT_CONFIG,
443  			       AD9523_SER_CONF_SOFT_RESET |
444  			       (dev->pdata->spi3wire ? 0 :
445  				AD9523_SER_CONF_SDO_ACTIVE));
446  	if (ret < 0)
447  		return ret;
448  	no_os_mdelay(1);
449  
450  	ret = ad9523_spi_write(dev,
451  			       AD9523_READBACK_CTRL,
452  			       AD9523_READBACK_CTRL_READ_BUFFERED);
453  	if (ret < 0)
454  		return ret;
455  
456  	ret = ad9523_io_update(dev);
457  	if (ret < 0)
458  		return ret;
459  
460  	ret = ad9523_spi_read(dev,
461  			      AD9523_EEPROM_CUSTOMER_VERSION_ID,
462  			      &version_id);
463  	if (ret < 0)
464  		return ret;
465  
466  	ret = ad9523_spi_write(dev,
467  			       AD9523_EEPROM_CUSTOMER_VERSION_ID,
468  			       0xAD95);
469  	if (ret < 0)
470  		return ret;
471  
472  	ret = ad9523_spi_read(dev,
473  			      AD9523_EEPROM_CUSTOMER_VERSION_ID,
474  			      &reg_data);
475  	if (ret < 0)
476  		return ret;
477  
478  	if (reg_data != 0xAD95) {
479  		printf("AD9523: SPI write-verify failed (%#06lX)!\n\r",
480  		       reg_data);
481  		return -1;
482  	}
483  
484  	ret = ad9523_spi_write(dev,
485  			       AD9523_EEPROM_CUSTOMER_VERSION_ID,
486  			       version_id);
487  	if (ret < 0)
488  		return ret;
489  
490  	/*
491  	 * PLL1 Setup
492  	 */
493  	ret = ad9523_spi_write(dev,
494  			       AD9523_PLL1_REF_A_DIVIDER,
495  			       dev->pdata->refa_r_div);
496  	if (ret < 0)
497  		return ret;
498  
499  	ret = ad9523_spi_write(dev,
500  			       AD9523_PLL1_REF_B_DIVIDER,
501  			       dev->pdata->refb_r_div);
502  	if (ret < 0)
503  		return ret;
504  
505  	ret = ad9523_spi_write(dev,
506  			       AD9523_PLL1_FEEDBACK_DIVIDER,
507  			       dev->pdata->pll1_feedback_div);
508  	if (ret < 0)
509  		return ret;
510  
511  	ret = ad9523_spi_write(dev,
512  			       AD9523_PLL1_CHARGE_PUMP_CTRL,
513  			       AD_IFE(pll1_bypass_en, AD9523_PLL1_CHARGE_PUMP_TRISTATE,
514  				      AD9523_PLL1_CHARGE_PUMP_CURRENT_nA(dev->pdata->
515  						      pll1_charge_pump_current_nA) |
516  				      AD9523_PLL1_CHARGE_PUMP_MODE_NORMAL |
517  				      AD9523_PLL1_BACKLASH_PW_MIN));
518  	if (ret < 0)
519  		return ret;
520  
521  	ret = ad9523_spi_write(dev,
522  			       AD9523_PLL1_INPUT_RECEIVERS_CTRL,
523  			       AD_IFE(pll1_bypass_en, AD9523_PLL1_REFA_REFB_PWR_CTRL_EN |
524  				      AD_IF(osc_in_diff_en, AD9523_PLL1_OSC_IN_DIFF_EN) |
525  				      AD_IF(osc_in_cmos_neg_inp_en, AD9523_PLL1_OSC_IN_CMOS_NEG_INP_EN),
526  				      AD_IF(refa_diff_rcv_en, AD9523_PLL1_REFA_RCV_EN) |
527  				      AD_IF(refb_diff_rcv_en, AD9523_PLL1_REFB_RCV_EN) |
528  				      AD_IF(osc_in_diff_en, AD9523_PLL1_OSC_IN_DIFF_EN) |
529  				      AD_IF(osc_in_cmos_neg_inp_en,
530  					    AD9523_PLL1_OSC_IN_CMOS_NEG_INP_EN) |
531  				      AD_IF(refa_diff_rcv_en, AD9523_PLL1_REFA_DIFF_RCV_EN) |
532  				      AD_IF(refb_diff_rcv_en, AD9523_PLL1_REFB_DIFF_RCV_EN)));
533  	if (ret < 0)
534  		return ret;
535  
536  	ret = ad9523_spi_write(dev,
537  			       AD9523_PLL1_REF_CTRL,
538  			       AD_IFE(pll1_bypass_en, AD9523_PLL1_BYPASS_FEEDBACK_DIV_EN |
539  				      AD9523_PLL1_ZERO_DELAY_MODE_INT,
540  				      AD_IF(zd_in_diff_en, AD9523_PLL1_ZD_IN_DIFF_EN) |
541  				      AD_IF(zd_in_cmos_neg_inp_en,
542  					    AD9523_PLL1_ZD_IN_CMOS_NEG_INP_EN) |
543  				      AD_IF(zero_delay_mode_internal_en,
544  					    AD9523_PLL1_ZERO_DELAY_MODE_INT) |
545  				      AD_IF(osc_in_feedback_en, AD9523_PLL1_OSC_IN_PLL_FEEDBACK_EN) |
546  				      AD_IF(refa_cmos_neg_inp_en, AD9523_PLL1_REFA_CMOS_NEG_INP_EN) |
547  				      AD_IF(refb_cmos_neg_inp_en, AD9523_PLL1_REFB_CMOS_NEG_INP_EN)));
548  	if (ret < 0)
549  		return ret;
550  
551  	ret = ad9523_spi_write(dev,
552  			       AD9523_PLL1_MISC_CTRL,
553  			       AD9523_PLL1_REFB_INDEP_DIV_CTRL_EN |
554  			       AD9523_PLL1_REF_MODE(dev->pdata->ref_mode));
555  	if (ret < 0)
556  		return ret;
557  
558  	ret = ad9523_spi_write(dev,
559  			       AD9523_PLL1_LOOP_FILTER_CTRL,
560  			       AD9523_PLL1_LOOP_FILTER_RZERO(dev->pdata->
561  					       pll1_loop_filter_rzero));
562  	if (ret < 0)
563  		return ret;
564  
565  	/*
566  	 * PLL2 Setup
567  	 */
568  
569  	ret = ad9523_spi_write(dev,
570  			       AD9523_PLL2_CHARGE_PUMP,
571  			       AD9523_PLL2_CHARGE_PUMP_CURRENT_nA(dev->pdata->
572  					       pll2_charge_pump_current_nA));
573  	if (ret < 0)
574  		return ret;
575  
576  	ret = ad9523_spi_write(dev,
577  			       AD9523_PLL2_FEEDBACK_DIVIDER_AB,
578  			       AD9523_PLL2_FB_NDIV_A_CNT(dev->pdata->pll2_ndiv_a_cnt) |
579  			       AD9523_PLL2_FB_NDIV_B_CNT(dev->pdata->pll2_ndiv_b_cnt));
580  	if (ret < 0)
581  		return ret;
582  
583  	ret = ad9523_spi_write(dev,
584  			       AD9523_PLL2_CTRL,
585  			       AD9523_PLL2_CHARGE_PUMP_MODE_NORMAL |
586  			       AD9523_PLL2_BACKLASH_CTRL_EN |
587  			       AD_IF(pll2_freq_doubler_en,
588  				     AD9523_PLL2_FREQ_DOUBLER_EN));
589  	if (ret < 0)
590  		return ret;
591  
592  	dev->ad9523_st.vco_freq = (dev->pdata->vcxo_freq *
593  				   (dev->pdata->pll2_freq_doubler_en ? 2 : 1)
594  				   / dev->pdata->pll2_r2_div) * AD9523_PLL2_FB_NDIV(dev->pdata->
595  						   pll2_ndiv_a_cnt,
596  						   dev->pdata->
597  						   pll2_ndiv_b_cnt);
598  
599  	ret = ad9523_spi_write(dev,
600  			       AD9523_PLL2_VCO_CTRL,
601  			       AD9523_PLL2_VCO_CALIBRATE);
602  	if (ret < 0)
603  		return ret;
604  
605  	ret = ad9523_spi_write(dev,
606  			       AD9523_PLL2_VCO_DIVIDER,
607  			       AD9523_PLL2_VCO_DIV_M1(dev->pdata->
608  					       pll2_vco_diff_m1) |
609  			       AD9523_PLL2_VCO_DIV_M2(dev->pdata->
610  					       pll2_vco_diff_m2) |
611  			       AD_IFE(pll2_vco_diff_m1,
612  				      0,
613  				      AD9523_PLL2_VCO_DIV_M1_PWR_DOWN_EN) |
614  			       AD_IFE(pll2_vco_diff_m2,
615  				      0,
616  				      AD9523_PLL2_VCO_DIV_M2_PWR_DOWN_EN));
617  	if (ret < 0)
618  		return ret;
619  
620  	if (dev->pdata->pll2_vco_diff_m1)
621  		dev->ad9523_st.vco_out_freq[AD9523_VCO1] =
622  			dev->ad9523_st.vco_freq / dev->pdata->pll2_vco_diff_m1;
623  
624  	if (dev->pdata->pll2_vco_diff_m2)
625  		dev->ad9523_st.vco_out_freq[AD9523_VCO2] =
626  			dev->ad9523_st.vco_freq / dev->pdata->pll2_vco_diff_m2;
627  
628  	dev->ad9523_st.vco_out_freq[AD9523_VCXO] = dev->pdata->vcxo_freq;
629  
630  	ret = ad9523_spi_write(dev,
631  			       AD9523_PLL2_R2_DIVIDER,
632  			       AD9523_PLL2_R2_DIVIDER_VAL(dev->pdata->pll2_r2_div));
633  	if (ret < 0)
634  		return ret;
635  
636  	ret = ad9523_spi_write(dev,
637  			       AD9523_PLL2_LOOP_FILTER_CTRL,
638  			       AD9523_PLL2_LOOP_FILTER_CPOLE1(dev->pdata->cpole1) |
639  			       AD9523_PLL2_LOOP_FILTER_RZERO(dev->pdata->rzero) |
640  			       AD9523_PLL2_LOOP_FILTER_RPOLE2(dev->pdata->rpole2) |
641  			       AD_IF(rzero_bypass_en,
642  				     AD9523_PLL2_LOOP_FILTER_RZERO_BYPASS_EN));
643  	if (ret < 0)
644  		return ret;
645  
646  	for (i = 0; i < dev->pdata->num_channels; i++) {
647  		chan = &dev->pdata->channels[i];
648  		if (chan->channel_num < AD9523_NUM_CHAN) {
649  			active_mask |= (1 << chan->channel_num);
650  			ret = ad9523_spi_write(dev,
651  					       AD9523_CHANNEL_CLOCK_DIST(chan->channel_num),
652  					       AD9523_CLK_DIST_DRIVER_MODE(chan->driver_mode) |
653  					       AD9523_CLK_DIST_DIV(chan->channel_divider) |
654  					       AD9523_CLK_DIST_DIV_PHASE(chan->divider_phase) |
655  					       (chan->sync_ignore_en ?
656  						AD9523_CLK_DIST_IGNORE_SYNC_EN : 0) |
657  					       (chan->divider_output_invert_en ?
658  						AD9523_CLK_DIST_INV_DIV_OUTPUT_EN : 0) |
659  					       (chan->low_power_mode_en ?
660  						AD9523_CLK_DIST_LOW_PWR_MODE_EN : 0) |
661  					       (chan->output_dis ?
662  						AD9523_CLK_DIST_PWR_DOWN_EN : 0));
663  			if (ret < 0)
664  				return ret;
665  
666  			ret = ad9523_vco_out_map(dev,
667  						 chan->channel_num,
668  						 chan->use_alt_clock_src);
669  			if (ret < 0)
670  				return ret;
671  		}
672  	}
673  
674  	for (i = 0; i < AD9523_NUM_CHAN; i++) {
675  		if (!(active_mask & (1 << i))) {
676  			ad9523_spi_write(dev,
677  					 AD9523_CHANNEL_CLOCK_DIST(i),
678  					 AD9523_CLK_DIST_DRIVER_MODE(TRISTATE) |
679  					 AD9523_CLK_DIST_PWR_DOWN_EN);
680  		}
681  	}
682  
683  	ret = ad9523_spi_write(dev,
684  			       AD9523_POWER_DOWN_CTRL,
685  			       0);
686  	if (ret < 0)
687  		return ret;
688  
689  	ret = ad9523_spi_write(dev,
690  			       AD9523_STATUS_SIGNALS,
691  			       AD9523_STATUS_MONITOR_01_PLL12_LOCKED);
692  	if (ret < 0)
693  		return ret;
694  
695  	ret = ad9523_io_update(dev);
696  	if (ret < 0)
697  		return ret;
698  
699  	ret = ad9523_sync(dev);
700  	if (ret < 0)
701  		return ret;
702  
703  	ad9523_spi_write(dev,
704  			 AD9523_READBACK_CTRL,
705  			 0x0);
706  	ad9523_io_update(dev);
707  	ad9523_calibrate(dev);
708  	ad9523_sync(dev);
709  
710  	*device = dev;
711  
712  	return (ad9523_status(dev));
713  }
714  
715  /***************************************************************************//**
716   * @brief Free the resources allocated by ad9523_setup().
717   *
718   * @param dev - The device structure.
719   *
720   * @return 0 in case of success, negative error code otherwise.
721  *******************************************************************************/
722  int32_t ad9523_remove(struct ad9523_dev *dev)
723  {
724  	int32_t ret;
725  
726  	ret = no_os_spi_remove(dev->spi_desc);
727  
728  	no_os_free(dev);
729  
730  	return ret;
731  }