linux/drivers/iio/frequency/ad9523.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * AD9523 SPI Low Jitter Clock Generator
 *
 * Copyright 2012 Analog Devices Inc.
 */

#include <linux/device.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
#include <linux/spi/spi.h>
#include <linux/regulator/consumer.h>
#include <linux/gpio/consumer.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/delay.h>

#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/frequency/ad9523.h>

#define AD9523_READ
#define AD9523_WRITE
#define AD9523_CNT(x)
#define AD9523_ADDR(x)

#define AD9523_R1B
#define AD9523_R2B
#define AD9523_R3B
#define AD9523_TRANSF_LEN(x)

#define AD9523_SERIAL_PORT_CONFIG
#define AD9523_VERSION_REGISTER
#define AD9523_PART_REGISTER
#define AD9523_READBACK_CTRL

#define AD9523_EEPROM_CUSTOMER_VERSION_ID

#define AD9523_PLL1_REF_A_DIVIDER
#define AD9523_PLL1_REF_B_DIVIDER
#define AD9523_PLL1_REF_TEST_DIVIDER
#define AD9523_PLL1_FEEDBACK_DIVIDER
#define AD9523_PLL1_CHARGE_PUMP_CTRL
#define AD9523_PLL1_INPUT_RECEIVERS_CTRL
#define AD9523_PLL1_REF_CTRL
#define AD9523_PLL1_MISC_CTRL
#define AD9523_PLL1_LOOP_FILTER_CTRL

#define AD9523_PLL2_CHARGE_PUMP
#define AD9523_PLL2_FEEDBACK_DIVIDER_AB
#define AD9523_PLL2_CTRL
#define AD9523_PLL2_VCO_CTRL
#define AD9523_PLL2_VCO_DIVIDER
#define AD9523_PLL2_LOOP_FILTER_CTRL
#define AD9523_PLL2_R2_DIVIDER

#define AD9523_CHANNEL_CLOCK_DIST(ch)

#define AD9523_PLL1_OUTPUT_CTRL
#define AD9523_PLL1_OUTPUT_CHANNEL_CTRL

#define AD9523_READBACK_0
#define AD9523_READBACK_1

#define AD9523_STATUS_SIGNALS
#define AD9523_POWER_DOWN_CTRL
#define AD9523_IO_UPDATE

#define AD9523_EEPROM_DATA_XFER_STATUS
#define AD9523_EEPROM_ERROR_READBACK
#define AD9523_EEPROM_CTRL1
#define AD9523_EEPROM_CTRL2

/* AD9523_SERIAL_PORT_CONFIG */

#define AD9523_SER_CONF_SDO_ACTIVE
#define AD9523_SER_CONF_SOFT_RESET

/* AD9523_READBACK_CTRL */
#define AD9523_READBACK_CTRL_READ_BUFFERED

/* AD9523_PLL1_CHARGE_PUMP_CTRL */
#define AD9523_PLL1_CHARGE_PUMP_CURRENT_nA(x)
#define AD9523_PLL1_CHARGE_PUMP_TRISTATE
#define AD9523_PLL1_CHARGE_PUMP_MODE_NORMAL
#define AD9523_PLL1_CHARGE_PUMP_MODE_PUMP_DOWN
#define AD9523_PLL1_CHARGE_PUMP_MODE_PUMP_UP
#define AD9523_PLL1_CHARGE_PUMP_MODE_TRISTATE
#define AD9523_PLL1_BACKLASH_PW_MIN
#define AD9523_PLL1_BACKLASH_PW_LOW
#define AD9523_PLL1_BACKLASH_PW_HIGH
#define AD9523_PLL1_BACKLASH_PW_MAX

/* AD9523_PLL1_INPUT_RECEIVERS_CTRL */
#define AD9523_PLL1_REF_TEST_RCV_EN
#define AD9523_PLL1_REFB_DIFF_RCV_EN
#define AD9523_PLL1_REFA_DIFF_RCV_EN
#define AD9523_PLL1_REFB_RCV_EN
#define AD9523_PLL1_REFA_RCV_EN
#define AD9523_PLL1_REFA_REFB_PWR_CTRL_EN
#define AD9523_PLL1_OSC_IN_CMOS_NEG_INP_EN
#define AD9523_PLL1_OSC_IN_DIFF_EN

/* AD9523_PLL1_REF_CTRL */
#define AD9523_PLL1_BYPASS_REF_TEST_DIV_EN
#define AD9523_PLL1_BYPASS_FEEDBACK_DIV_EN
#define AD9523_PLL1_ZERO_DELAY_MODE_INT
#define AD9523_PLL1_ZERO_DELAY_MODE_EXT
#define AD9523_PLL1_OSC_IN_PLL_FEEDBACK_EN
#define AD9523_PLL1_ZD_IN_CMOS_NEG_INP_EN
#define AD9523_PLL1_ZD_IN_DIFF_EN
#define AD9523_PLL1_REFB_CMOS_NEG_INP_EN
#define AD9523_PLL1_REFA_CMOS_NEG_INP_EN

/* AD9523_PLL1_MISC_CTRL */
#define AD9523_PLL1_REFB_INDEP_DIV_CTRL_EN
#define AD9523_PLL1_OSC_CTRL_FAIL_VCC_BY2_EN
#define AD9523_PLL1_REF_MODE(x)
#define AD9523_PLL1_BYPASS_REFB_DIV
#define AD9523_PLL1_BYPASS_REFA_DIV

/* AD9523_PLL1_LOOP_FILTER_CTRL */
#define AD9523_PLL1_LOOP_FILTER_RZERO(x)

/* AD9523_PLL2_CHARGE_PUMP */
#define AD9523_PLL2_CHARGE_PUMP_CURRENT_nA(x)

/* AD9523_PLL2_FEEDBACK_DIVIDER_AB */
#define AD9523_PLL2_FB_NDIV_A_CNT(x)
#define AD9523_PLL2_FB_NDIV_B_CNT(x)
#define AD9523_PLL2_FB_NDIV(a, b)

/* AD9523_PLL2_CTRL */
#define AD9523_PLL2_CHARGE_PUMP_MODE_NORMAL
#define AD9523_PLL2_CHARGE_PUMP_MODE_PUMP_DOWN
#define AD9523_PLL2_CHARGE_PUMP_MODE_PUMP_UP
#define AD9523_PLL2_CHARGE_PUMP_MODE_TRISTATE
#define AD9523_PLL2_BACKLASH_PW_MIN
#define AD9523_PLL2_BACKLASH_PW_LOW
#define AD9523_PLL2_BACKLASH_PW_HIGH
#define AD9523_PLL2_BACKLASH_PW_MAX
#define AD9523_PLL2_BACKLASH_CTRL_EN
#define AD9523_PLL2_FREQ_DOUBLER_EN
#define AD9523_PLL2_LOCK_DETECT_PWR_DOWN_EN

/* AD9523_PLL2_VCO_CTRL */
#define AD9523_PLL2_VCO_CALIBRATE
#define AD9523_PLL2_FORCE_VCO_MIDSCALE
#define AD9523_PLL2_FORCE_REFERENCE_VALID
#define AD9523_PLL2_FORCE_RELEASE_SYNC

/* AD9523_PLL2_VCO_DIVIDER */
#define AD9523_PLL2_VCO_DIV_M1(x)
#define AD9523_PLL2_VCO_DIV_M2(x)
#define AD9523_PLL2_VCO_DIV_M1_PWR_DOWN_EN
#define AD9523_PLL2_VCO_DIV_M2_PWR_DOWN_EN

/* AD9523_PLL2_LOOP_FILTER_CTRL */
#define AD9523_PLL2_LOOP_FILTER_CPOLE1(x)
#define AD9523_PLL2_LOOP_FILTER_RZERO(x)
#define AD9523_PLL2_LOOP_FILTER_RPOLE2(x)
#define AD9523_PLL2_LOOP_FILTER_RZERO_BYPASS_EN

/* AD9523_PLL2_R2_DIVIDER */
#define AD9523_PLL2_R2_DIVIDER_VAL(x)

/* AD9523_CHANNEL_CLOCK_DIST */
#define AD9523_CLK_DIST_DIV_PHASE(x)
#define AD9523_CLK_DIST_DIV_PHASE_REV(x)
#define AD9523_CLK_DIST_DIV(x)
#define AD9523_CLK_DIST_DIV_REV(x)
#define AD9523_CLK_DIST_INV_DIV_OUTPUT_EN
#define AD9523_CLK_DIST_IGNORE_SYNC_EN
#define AD9523_CLK_DIST_PWR_DOWN_EN
#define AD9523_CLK_DIST_LOW_PWR_MODE_EN
#define AD9523_CLK_DIST_DRIVER_MODE(x)

/* AD9523_PLL1_OUTPUT_CTRL */
#define AD9523_PLL1_OUTP_CTRL_VCO_DIV_SEL_CH6_M2
#define AD9523_PLL1_OUTP_CTRL_VCO_DIV_SEL_CH5_M2
#define AD9523_PLL1_OUTP_CTRL_VCO_DIV_SEL_CH4_M2
#define AD9523_PLL1_OUTP_CTRL_CMOS_DRV_WEAK
#define AD9523_PLL1_OUTP_CTRL_OUTPUT_DIV_1
#define AD9523_PLL1_OUTP_CTRL_OUTPUT_DIV_2
#define AD9523_PLL1_OUTP_CTRL_OUTPUT_DIV_4
#define AD9523_PLL1_OUTP_CTRL_OUTPUT_DIV_8
#define AD9523_PLL1_OUTP_CTRL_OUTPUT_DIV_16

/* AD9523_PLL1_OUTPUT_CHANNEL_CTRL */
#define AD9523_PLL1_OUTP_CH_CTRL_OUTPUT_PWR_DOWN_EN
#define AD9523_PLL1_OUTP_CH_CTRL_VCO_DIV_SEL_CH9_M2
#define AD9523_PLL1_OUTP_CH_CTRL_VCO_DIV_SEL_CH8_M2
#define AD9523_PLL1_OUTP_CH_CTRL_VCO_DIV_SEL_CH7_M2
#define AD9523_PLL1_OUTP_CH_CTRL_VCXO_SRC_SEL_CH3
#define AD9523_PLL1_OUTP_CH_CTRL_VCXO_SRC_SEL_CH2
#define AD9523_PLL1_OUTP_CH_CTRL_VCXO_SRC_SEL_CH1
#define AD9523_PLL1_OUTP_CH_CTRL_VCXO_SRC_SEL_CH0

/* AD9523_READBACK_0 */
#define AD9523_READBACK_0_STAT_PLL2_REF_CLK
#define AD9523_READBACK_0_STAT_PLL2_FB_CLK
#define AD9523_READBACK_0_STAT_VCXO
#define AD9523_READBACK_0_STAT_REF_TEST
#define AD9523_READBACK_0_STAT_REFB
#define AD9523_READBACK_0_STAT_REFA
#define AD9523_READBACK_0_STAT_PLL2_LD
#define AD9523_READBACK_0_STAT_PLL1_LD

/* AD9523_READBACK_1 */
#define AD9523_READBACK_1_HOLDOVER_ACTIVE
#define AD9523_READBACK_1_AUTOMODE_SEL_REFB
#define AD9523_READBACK_1_VCO_CALIB_IN_PROGRESS

/* AD9523_STATUS_SIGNALS */
#define AD9523_STATUS_SIGNALS_SYNC_MAN_CTRL
#define AD9523_STATUS_MONITOR_01_PLL12_LOCKED
/* AD9523_POWER_DOWN_CTRL */
#define AD9523_POWER_DOWN_CTRL_PLL1_PWR_DOWN
#define AD9523_POWER_DOWN_CTRL_PLL2_PWR_DOWN
#define AD9523_POWER_DOWN_CTRL_DIST_PWR_DOWN

/* AD9523_IO_UPDATE */
#define AD9523_IO_UPDATE_EN

/* AD9523_EEPROM_DATA_XFER_STATUS */
#define AD9523_EEPROM_DATA_XFER_IN_PROGRESS

/* AD9523_EEPROM_ERROR_READBACK */
#define AD9523_EEPROM_ERROR_READBACK_FAIL

/* AD9523_EEPROM_CTRL1 */
#define AD9523_EEPROM_CTRL1_SOFT_EEPROM
#define AD9523_EEPROM_CTRL1_EEPROM_WRITE_PROT_DIS

/* AD9523_EEPROM_CTRL2 */
#define AD9523_EEPROM_CTRL2_REG2EEPROM

#define AD9523_NUM_CHAN
#define AD9523_NUM_CHAN_ALT_CLK_SRC

/* Helpers to avoid excess line breaks */
#define AD_IFE(_pde, _a, _b)
#define AD_IF(_pde, _a)

enum {};

enum {};

struct ad9523_state {};

static int ad9523_read(struct iio_dev *indio_dev, unsigned int addr)
{
	struct ad9523_state *st = iio_priv(indio_dev);
	int ret;

	/* We encode the register size 1..3 bytes into the register address.
	 * On transfer we get the size from the register datum, and make sure
	 * the result is properly aligned.
	 */

	struct spi_transfer t[] = {
		{
			.tx_buf = &st->data[0].d8[2],
			.len = 2,
		}, {
			.rx_buf = &st->data[1].d8[4 - AD9523_TRANSF_LEN(addr)],
			.len = AD9523_TRANSF_LEN(addr),
		},
	};

	st->data[0].d32 = cpu_to_be32(AD9523_READ |
				      AD9523_CNT(AD9523_TRANSF_LEN(addr)) |
				      AD9523_ADDR(addr));

	ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t));
	if (ret < 0)
		dev_err(&indio_dev->dev, "read failed (%d)", ret);
	else
		ret = be32_to_cpu(st->data[1].d32) & (0xFFFFFF >>
				  (8 * (3 - AD9523_TRANSF_LEN(addr))));

	return ret;
};

static int ad9523_write(struct iio_dev *indio_dev,
		unsigned int addr, unsigned int val)
{}

static int ad9523_io_update(struct iio_dev *indio_dev)
{}

static int ad9523_vco_out_map(struct iio_dev *indio_dev,
			      unsigned int ch, unsigned int out)
{}

static int ad9523_set_clock_provider(struct iio_dev *indio_dev,
			      unsigned int ch, unsigned long freq)
{}

static int ad9523_store_eeprom(struct iio_dev *indio_dev)
{}

static int ad9523_sync(struct iio_dev *indio_dev)
{}

static ssize_t ad9523_store(struct device *dev,
				struct device_attribute *attr,
				const char *buf, size_t len)
{}

static ssize_t ad9523_show(struct device *dev,
			struct device_attribute *attr,
			char *buf)
{}

static IIO_DEVICE_ATTR(pll1_locked, S_IRUGO,
			ad9523_show,
			NULL,
			AD9523_STAT_PLL1_LD);

static IIO_DEVICE_ATTR(pll2_locked, S_IRUGO,
			ad9523_show,
			NULL,
			AD9523_STAT_PLL2_LD);

static IIO_DEVICE_ATTR(pll1_reference_clk_a_present, S_IRUGO,
			ad9523_show,
			NULL,
			AD9523_STAT_REFA);

static IIO_DEVICE_ATTR(pll1_reference_clk_b_present, S_IRUGO,
			ad9523_show,
			NULL,
			AD9523_STAT_REFB);

static IIO_DEVICE_ATTR(pll1_reference_clk_test_present, S_IRUGO,
			ad9523_show,
			NULL,
			AD9523_STAT_REF_TEST);

static IIO_DEVICE_ATTR(vcxo_clk_present, S_IRUGO,
			ad9523_show,
			NULL,
			AD9523_STAT_VCXO);

static IIO_DEVICE_ATTR(pll2_feedback_clk_present, S_IRUGO,
			ad9523_show,
			NULL,
			AD9523_STAT_PLL2_FB_CLK);

static IIO_DEVICE_ATTR(pll2_reference_clk_present, S_IRUGO,
			ad9523_show,
			NULL,
			AD9523_STAT_PLL2_REF_CLK);

static IIO_DEVICE_ATTR(sync_dividers, S_IWUSR,
			NULL,
			ad9523_store,
			AD9523_SYNC);

static IIO_DEVICE_ATTR(store_eeprom, S_IWUSR,
			NULL,
			ad9523_store,
			AD9523_EEPROM);

static struct attribute *ad9523_attributes[] =;

static const struct attribute_group ad9523_attribute_group =;

static int ad9523_read_raw(struct iio_dev *indio_dev,
			   struct iio_chan_spec const *chan,
			   int *val,
			   int *val2,
			   long m)
{
	struct ad9523_state *st = iio_priv(indio_dev);
	unsigned int code;
	int ret;

	mutex_lock(&st->lock);
	ret = ad9523_read(indio_dev, AD9523_CHANNEL_CLOCK_DIST(chan->channel));
	mutex_unlock(&st->lock);

	if (ret < 0)
		return ret;

	switch (m) {
	case IIO_CHAN_INFO_RAW:
		*val = !(ret & AD9523_CLK_DIST_PWR_DOWN_EN);
		return IIO_VAL_INT;
	case IIO_CHAN_INFO_FREQUENCY:
		*val = st->vco_out_freq[st->vco_out_map[chan->channel]] /
			AD9523_CLK_DIST_DIV_REV(ret);
		return IIO_VAL_INT;
	case IIO_CHAN_INFO_PHASE:
		code = (AD9523_CLK_DIST_DIV_PHASE_REV(ret) * 3141592) /
			AD9523_CLK_DIST_DIV_REV(ret);
		*val = code / 1000000;
		*val2 = code % 1000000;
		return IIO_VAL_INT_PLUS_MICRO;
	default:
		return -EINVAL;
	}
};

static int ad9523_write_raw(struct iio_dev *indio_dev,
			    struct iio_chan_spec const *chan,
			    int val,
			    int val2,
			    long mask)
{}

static int ad9523_reg_access(struct iio_dev *indio_dev,
			      unsigned int reg, unsigned int writeval,
			      unsigned int *readval)
{}

static const struct iio_info ad9523_info =;

static int ad9523_setup(struct iio_dev *indio_dev)
{}

static int ad9523_probe(struct spi_device *spi)
{}

static const struct spi_device_id ad9523_id[] =;
MODULE_DEVICE_TABLE(spi, ad9523_id);

static struct spi_driver ad9523_driver =;
module_spi_driver();

MODULE_AUTHOR();
MODULE_DESCRIPTION();
MODULE_LICENSE();