18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Analog Devices ADF4371 SPI Wideband Synthesizer driver
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright 2019 Analog Devices Inc.
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci#include <linux/bitfield.h>
88c2ecf20Sopenharmony_ci#include <linux/clk.h>
98c2ecf20Sopenharmony_ci#include <linux/device.h>
108c2ecf20Sopenharmony_ci#include <linux/err.h>
118c2ecf20Sopenharmony_ci#include <linux/gcd.h>
128c2ecf20Sopenharmony_ci#include <linux/kernel.h>
138c2ecf20Sopenharmony_ci#include <linux/module.h>
148c2ecf20Sopenharmony_ci#include <linux/regmap.h>
158c2ecf20Sopenharmony_ci#include <linux/sysfs.h>
168c2ecf20Sopenharmony_ci#include <linux/spi/spi.h>
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci#include <linux/iio/iio.h>
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci/* Registers address macro */
218c2ecf20Sopenharmony_ci#define ADF4371_REG(x)			(x)
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci/* ADF4371_REG0 */
248c2ecf20Sopenharmony_ci#define ADF4371_ADDR_ASC_MSK		BIT(2)
258c2ecf20Sopenharmony_ci#define ADF4371_ADDR_ASC(x)		FIELD_PREP(ADF4371_ADDR_ASC_MSK, x)
268c2ecf20Sopenharmony_ci#define ADF4371_ADDR_ASC_R_MSK		BIT(5)
278c2ecf20Sopenharmony_ci#define ADF4371_ADDR_ASC_R(x)		FIELD_PREP(ADF4371_ADDR_ASC_R_MSK, x)
288c2ecf20Sopenharmony_ci#define ADF4371_RESET_CMD		0x81
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci/* ADF4371_REG17 */
318c2ecf20Sopenharmony_ci#define ADF4371_FRAC2WORD_L_MSK		GENMASK(7, 1)
328c2ecf20Sopenharmony_ci#define ADF4371_FRAC2WORD_L(x)		FIELD_PREP(ADF4371_FRAC2WORD_L_MSK, x)
338c2ecf20Sopenharmony_ci#define ADF4371_FRAC1WORD_MSK		BIT(0)
348c2ecf20Sopenharmony_ci#define ADF4371_FRAC1WORD(x)		FIELD_PREP(ADF4371_FRAC1WORD_MSK, x)
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci/* ADF4371_REG18 */
378c2ecf20Sopenharmony_ci#define ADF4371_FRAC2WORD_H_MSK		GENMASK(6, 0)
388c2ecf20Sopenharmony_ci#define ADF4371_FRAC2WORD_H(x)		FIELD_PREP(ADF4371_FRAC2WORD_H_MSK, x)
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci/* ADF4371_REG1A */
418c2ecf20Sopenharmony_ci#define ADF4371_MOD2WORD_MSK		GENMASK(5, 0)
428c2ecf20Sopenharmony_ci#define ADF4371_MOD2WORD(x)		FIELD_PREP(ADF4371_MOD2WORD_MSK, x)
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci/* ADF4371_REG24 */
458c2ecf20Sopenharmony_ci#define ADF4371_RF_DIV_SEL_MSK		GENMASK(6, 4)
468c2ecf20Sopenharmony_ci#define ADF4371_RF_DIV_SEL(x)		FIELD_PREP(ADF4371_RF_DIV_SEL_MSK, x)
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ci/* ADF4371_REG25 */
498c2ecf20Sopenharmony_ci#define ADF4371_MUTE_LD_MSK		BIT(7)
508c2ecf20Sopenharmony_ci#define ADF4371_MUTE_LD(x)		FIELD_PREP(ADF4371_MUTE_LD_MSK, x)
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci/* ADF4371_REG32 */
538c2ecf20Sopenharmony_ci#define ADF4371_TIMEOUT_MSK		GENMASK(1, 0)
548c2ecf20Sopenharmony_ci#define ADF4371_TIMEOUT(x)		FIELD_PREP(ADF4371_TIMEOUT_MSK, x)
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci/* ADF4371_REG34 */
578c2ecf20Sopenharmony_ci#define ADF4371_VCO_ALC_TOUT_MSK	GENMASK(4, 0)
588c2ecf20Sopenharmony_ci#define ADF4371_VCO_ALC_TOUT(x)		FIELD_PREP(ADF4371_VCO_ALC_TOUT_MSK, x)
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci/* Specifications */
618c2ecf20Sopenharmony_ci#define ADF4371_MIN_VCO_FREQ		4000000000ULL /* 4000 MHz */
628c2ecf20Sopenharmony_ci#define ADF4371_MAX_VCO_FREQ		8000000000ULL /* 8000 MHz */
638c2ecf20Sopenharmony_ci#define ADF4371_MAX_OUT_RF8_FREQ	ADF4371_MAX_VCO_FREQ /* Hz */
648c2ecf20Sopenharmony_ci#define ADF4371_MIN_OUT_RF8_FREQ	(ADF4371_MIN_VCO_FREQ / 64) /* Hz */
658c2ecf20Sopenharmony_ci#define ADF4371_MAX_OUT_RF16_FREQ	(ADF4371_MAX_VCO_FREQ * 2) /* Hz */
668c2ecf20Sopenharmony_ci#define ADF4371_MIN_OUT_RF16_FREQ	(ADF4371_MIN_VCO_FREQ * 2) /* Hz */
678c2ecf20Sopenharmony_ci#define ADF4371_MAX_OUT_RF32_FREQ	(ADF4371_MAX_VCO_FREQ * 4) /* Hz */
688c2ecf20Sopenharmony_ci#define ADF4371_MIN_OUT_RF32_FREQ	(ADF4371_MIN_VCO_FREQ * 4) /* Hz */
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci#define ADF4371_MAX_FREQ_PFD		250000000UL /* Hz */
718c2ecf20Sopenharmony_ci#define ADF4371_MAX_FREQ_REFIN		600000000UL /* Hz */
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci/* MOD1 is a 24-bit primary modulus with fixed value of 2^25 */
748c2ecf20Sopenharmony_ci#define ADF4371_MODULUS1		33554432ULL
758c2ecf20Sopenharmony_ci/* MOD2 is the programmable, 14-bit auxiliary fractional modulus */
768c2ecf20Sopenharmony_ci#define ADF4371_MAX_MODULUS2		BIT(14)
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci#define ADF4371_CHECK_RANGE(freq, range) \
798c2ecf20Sopenharmony_ci	((freq > ADF4371_MAX_ ## range) || (freq < ADF4371_MIN_ ## range))
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_cienum {
828c2ecf20Sopenharmony_ci	ADF4371_FREQ,
838c2ecf20Sopenharmony_ci	ADF4371_POWER_DOWN,
848c2ecf20Sopenharmony_ci	ADF4371_CHANNEL_NAME
858c2ecf20Sopenharmony_ci};
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_cienum {
888c2ecf20Sopenharmony_ci	ADF4371_CH_RF8,
898c2ecf20Sopenharmony_ci	ADF4371_CH_RFAUX8,
908c2ecf20Sopenharmony_ci	ADF4371_CH_RF16,
918c2ecf20Sopenharmony_ci	ADF4371_CH_RF32
928c2ecf20Sopenharmony_ci};
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_cienum adf4371_variant {
958c2ecf20Sopenharmony_ci	ADF4371,
968c2ecf20Sopenharmony_ci	ADF4372
978c2ecf20Sopenharmony_ci};
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_cistruct adf4371_pwrdown {
1008c2ecf20Sopenharmony_ci	unsigned int reg;
1018c2ecf20Sopenharmony_ci	unsigned int bit;
1028c2ecf20Sopenharmony_ci};
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_cistatic const char * const adf4371_ch_names[] = {
1058c2ecf20Sopenharmony_ci	"RF8x", "RFAUX8x", "RF16x", "RF32x"
1068c2ecf20Sopenharmony_ci};
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_cistatic const struct adf4371_pwrdown adf4371_pwrdown_ch[4] = {
1098c2ecf20Sopenharmony_ci	[ADF4371_CH_RF8] = { ADF4371_REG(0x25), 2 },
1108c2ecf20Sopenharmony_ci	[ADF4371_CH_RFAUX8] = { ADF4371_REG(0x72), 3 },
1118c2ecf20Sopenharmony_ci	[ADF4371_CH_RF16] = { ADF4371_REG(0x25), 3 },
1128c2ecf20Sopenharmony_ci	[ADF4371_CH_RF32] = { ADF4371_REG(0x25), 4 },
1138c2ecf20Sopenharmony_ci};
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_cistatic const struct reg_sequence adf4371_reg_defaults[] = {
1168c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x0),  0x18 },
1178c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x12), 0x40 },
1188c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x1E), 0x48 },
1198c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x20), 0x14 },
1208c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x22), 0x00 },
1218c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x23), 0x00 },
1228c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x24), 0x80 },
1238c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x25), 0x07 },
1248c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x27), 0xC5 },
1258c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x28), 0x83 },
1268c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x2C), 0x44 },
1278c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x2D), 0x11 },
1288c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x2E), 0x12 },
1298c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x2F), 0x94 },
1308c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x32), 0x04 },
1318c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x35), 0xFA },
1328c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x36), 0x30 },
1338c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x39), 0x07 },
1348c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x3A), 0x55 },
1358c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x3E), 0x0C },
1368c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x3F), 0x80 },
1378c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x40), 0x50 },
1388c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x41), 0x28 },
1398c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x47), 0xC0 },
1408c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x52), 0xF4 },
1418c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x70), 0x03 },
1428c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x71), 0x60 },
1438c2ecf20Sopenharmony_ci	{ ADF4371_REG(0x72), 0x32 },
1448c2ecf20Sopenharmony_ci};
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_cistatic const struct regmap_config adf4371_regmap_config = {
1478c2ecf20Sopenharmony_ci	.reg_bits = 16,
1488c2ecf20Sopenharmony_ci	.val_bits = 8,
1498c2ecf20Sopenharmony_ci	.read_flag_mask = BIT(7),
1508c2ecf20Sopenharmony_ci};
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_cistruct adf4371_chip_info {
1538c2ecf20Sopenharmony_ci	unsigned int num_channels;
1548c2ecf20Sopenharmony_ci	const struct iio_chan_spec *channels;
1558c2ecf20Sopenharmony_ci};
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_cistruct adf4371_state {
1588c2ecf20Sopenharmony_ci	struct spi_device *spi;
1598c2ecf20Sopenharmony_ci	struct regmap *regmap;
1608c2ecf20Sopenharmony_ci	struct clk *clkin;
1618c2ecf20Sopenharmony_ci	/*
1628c2ecf20Sopenharmony_ci	 * Lock for accessing device registers. Some operations require
1638c2ecf20Sopenharmony_ci	 * multiple consecutive R/W operations, during which the device
1648c2ecf20Sopenharmony_ci	 * shouldn't be interrupted. The buffers are also shared across
1658c2ecf20Sopenharmony_ci	 * all operations so need to be protected on stand alone reads and
1668c2ecf20Sopenharmony_ci	 * writes.
1678c2ecf20Sopenharmony_ci	 */
1688c2ecf20Sopenharmony_ci	struct mutex lock;
1698c2ecf20Sopenharmony_ci	const struct adf4371_chip_info *chip_info;
1708c2ecf20Sopenharmony_ci	unsigned long clkin_freq;
1718c2ecf20Sopenharmony_ci	unsigned long fpfd;
1728c2ecf20Sopenharmony_ci	unsigned int integer;
1738c2ecf20Sopenharmony_ci	unsigned int fract1;
1748c2ecf20Sopenharmony_ci	unsigned int fract2;
1758c2ecf20Sopenharmony_ci	unsigned int mod2;
1768c2ecf20Sopenharmony_ci	unsigned int rf_div_sel;
1778c2ecf20Sopenharmony_ci	unsigned int ref_div_factor;
1788c2ecf20Sopenharmony_ci	u8 buf[10] ____cacheline_aligned;
1798c2ecf20Sopenharmony_ci};
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_cistatic unsigned long long adf4371_pll_fract_n_get_rate(struct adf4371_state *st,
1828c2ecf20Sopenharmony_ci						       u32 channel)
1838c2ecf20Sopenharmony_ci{
1848c2ecf20Sopenharmony_ci	unsigned long long val, tmp;
1858c2ecf20Sopenharmony_ci	unsigned int ref_div_sel;
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci	val = (((u64)st->integer * ADF4371_MODULUS1) + st->fract1) * st->fpfd;
1888c2ecf20Sopenharmony_ci	tmp = (u64)st->fract2 * st->fpfd;
1898c2ecf20Sopenharmony_ci	do_div(tmp, st->mod2);
1908c2ecf20Sopenharmony_ci	val += tmp + ADF4371_MODULUS1 / 2;
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	if (channel == ADF4371_CH_RF8 || channel == ADF4371_CH_RFAUX8)
1938c2ecf20Sopenharmony_ci		ref_div_sel = st->rf_div_sel;
1948c2ecf20Sopenharmony_ci	else
1958c2ecf20Sopenharmony_ci		ref_div_sel = 0;
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	do_div(val, ADF4371_MODULUS1 * (1 << ref_div_sel));
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci	if (channel == ADF4371_CH_RF16)
2008c2ecf20Sopenharmony_ci		val <<= 1;
2018c2ecf20Sopenharmony_ci	else if (channel == ADF4371_CH_RF32)
2028c2ecf20Sopenharmony_ci		val <<= 2;
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci	return val;
2058c2ecf20Sopenharmony_ci}
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_cistatic void adf4371_pll_fract_n_compute(unsigned long long vco,
2088c2ecf20Sopenharmony_ci				       unsigned long long pfd,
2098c2ecf20Sopenharmony_ci				       unsigned int *integer,
2108c2ecf20Sopenharmony_ci				       unsigned int *fract1,
2118c2ecf20Sopenharmony_ci				       unsigned int *fract2,
2128c2ecf20Sopenharmony_ci				       unsigned int *mod2)
2138c2ecf20Sopenharmony_ci{
2148c2ecf20Sopenharmony_ci	unsigned long long tmp;
2158c2ecf20Sopenharmony_ci	u32 gcd_div;
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	tmp = do_div(vco, pfd);
2188c2ecf20Sopenharmony_ci	tmp = tmp * ADF4371_MODULUS1;
2198c2ecf20Sopenharmony_ci	*fract2 = do_div(tmp, pfd);
2208c2ecf20Sopenharmony_ci
2218c2ecf20Sopenharmony_ci	*integer = vco;
2228c2ecf20Sopenharmony_ci	*fract1 = tmp;
2238c2ecf20Sopenharmony_ci
2248c2ecf20Sopenharmony_ci	*mod2 = pfd;
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci	while (*mod2 > ADF4371_MAX_MODULUS2) {
2278c2ecf20Sopenharmony_ci		*mod2 >>= 1;
2288c2ecf20Sopenharmony_ci		*fract2 >>= 1;
2298c2ecf20Sopenharmony_ci	}
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	gcd_div = gcd(*fract2, *mod2);
2328c2ecf20Sopenharmony_ci	*mod2 /= gcd_div;
2338c2ecf20Sopenharmony_ci	*fract2 /= gcd_div;
2348c2ecf20Sopenharmony_ci}
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_cistatic int adf4371_set_freq(struct adf4371_state *st, unsigned long long freq,
2378c2ecf20Sopenharmony_ci			    unsigned int channel)
2388c2ecf20Sopenharmony_ci{
2398c2ecf20Sopenharmony_ci	u32 cp_bleed;
2408c2ecf20Sopenharmony_ci	u8 int_mode = 0;
2418c2ecf20Sopenharmony_ci	int ret;
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	switch (channel) {
2448c2ecf20Sopenharmony_ci	case ADF4371_CH_RF8:
2458c2ecf20Sopenharmony_ci	case ADF4371_CH_RFAUX8:
2468c2ecf20Sopenharmony_ci		if (ADF4371_CHECK_RANGE(freq, OUT_RF8_FREQ))
2478c2ecf20Sopenharmony_ci			return -EINVAL;
2488c2ecf20Sopenharmony_ci
2498c2ecf20Sopenharmony_ci		st->rf_div_sel = 0;
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci		while (freq < ADF4371_MIN_VCO_FREQ) {
2528c2ecf20Sopenharmony_ci			freq <<= 1;
2538c2ecf20Sopenharmony_ci			st->rf_div_sel++;
2548c2ecf20Sopenharmony_ci		}
2558c2ecf20Sopenharmony_ci		break;
2568c2ecf20Sopenharmony_ci	case ADF4371_CH_RF16:
2578c2ecf20Sopenharmony_ci		/* ADF4371 RF16 8000...16000 MHz */
2588c2ecf20Sopenharmony_ci		if (ADF4371_CHECK_RANGE(freq, OUT_RF16_FREQ))
2598c2ecf20Sopenharmony_ci			return -EINVAL;
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci		freq >>= 1;
2628c2ecf20Sopenharmony_ci		break;
2638c2ecf20Sopenharmony_ci	case ADF4371_CH_RF32:
2648c2ecf20Sopenharmony_ci		/* ADF4371 RF32 16000...32000 MHz */
2658c2ecf20Sopenharmony_ci		if (ADF4371_CHECK_RANGE(freq, OUT_RF32_FREQ))
2668c2ecf20Sopenharmony_ci			return -EINVAL;
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci		freq >>= 2;
2698c2ecf20Sopenharmony_ci		break;
2708c2ecf20Sopenharmony_ci	default:
2718c2ecf20Sopenharmony_ci		return -EINVAL;
2728c2ecf20Sopenharmony_ci	}
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	adf4371_pll_fract_n_compute(freq, st->fpfd, &st->integer, &st->fract1,
2758c2ecf20Sopenharmony_ci				    &st->fract2, &st->mod2);
2768c2ecf20Sopenharmony_ci	st->buf[0] = st->integer >> 8;
2778c2ecf20Sopenharmony_ci	st->buf[1] = 0x40; /* REG12 default */
2788c2ecf20Sopenharmony_ci	st->buf[2] = 0x00;
2798c2ecf20Sopenharmony_ci	st->buf[3] = st->fract1 & 0xFF;
2808c2ecf20Sopenharmony_ci	st->buf[4] = st->fract1 >> 8;
2818c2ecf20Sopenharmony_ci	st->buf[5] = st->fract1 >> 16;
2828c2ecf20Sopenharmony_ci	st->buf[6] = ADF4371_FRAC2WORD_L(st->fract2 & 0x7F) |
2838c2ecf20Sopenharmony_ci		     ADF4371_FRAC1WORD(st->fract1 >> 24);
2848c2ecf20Sopenharmony_ci	st->buf[7] = ADF4371_FRAC2WORD_H(st->fract2 >> 7);
2858c2ecf20Sopenharmony_ci	st->buf[8] = st->mod2 & 0xFF;
2868c2ecf20Sopenharmony_ci	st->buf[9] = ADF4371_MOD2WORD(st->mod2 >> 8);
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ci	ret = regmap_bulk_write(st->regmap, ADF4371_REG(0x11), st->buf, 10);
2898c2ecf20Sopenharmony_ci	if (ret < 0)
2908c2ecf20Sopenharmony_ci		return ret;
2918c2ecf20Sopenharmony_ci	/*
2928c2ecf20Sopenharmony_ci	 * The R counter allows the input reference frequency to be
2938c2ecf20Sopenharmony_ci	 * divided down to produce the reference clock to the PFD
2948c2ecf20Sopenharmony_ci	 */
2958c2ecf20Sopenharmony_ci	ret = regmap_write(st->regmap, ADF4371_REG(0x1F), st->ref_div_factor);
2968c2ecf20Sopenharmony_ci	if (ret < 0)
2978c2ecf20Sopenharmony_ci		return ret;
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_ci	ret = regmap_update_bits(st->regmap, ADF4371_REG(0x24),
3008c2ecf20Sopenharmony_ci				 ADF4371_RF_DIV_SEL_MSK,
3018c2ecf20Sopenharmony_ci				 ADF4371_RF_DIV_SEL(st->rf_div_sel));
3028c2ecf20Sopenharmony_ci	if (ret < 0)
3038c2ecf20Sopenharmony_ci		return ret;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	cp_bleed = DIV_ROUND_UP(400 * 1750, st->integer * 375);
3068c2ecf20Sopenharmony_ci	cp_bleed = clamp(cp_bleed, 1U, 255U);
3078c2ecf20Sopenharmony_ci	ret = regmap_write(st->regmap, ADF4371_REG(0x26), cp_bleed);
3088c2ecf20Sopenharmony_ci	if (ret < 0)
3098c2ecf20Sopenharmony_ci		return ret;
3108c2ecf20Sopenharmony_ci	/*
3118c2ecf20Sopenharmony_ci	 * Set to 1 when in INT mode (when FRAC1 = FRAC2 = 0),
3128c2ecf20Sopenharmony_ci	 * and set to 0 when in FRAC mode.
3138c2ecf20Sopenharmony_ci	 */
3148c2ecf20Sopenharmony_ci	if (st->fract1 == 0 && st->fract2 == 0)
3158c2ecf20Sopenharmony_ci		int_mode = 0x01;
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	ret = regmap_write(st->regmap, ADF4371_REG(0x2B), int_mode);
3188c2ecf20Sopenharmony_ci	if (ret < 0)
3198c2ecf20Sopenharmony_ci		return ret;
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	return regmap_write(st->regmap, ADF4371_REG(0x10), st->integer & 0xFF);
3228c2ecf20Sopenharmony_ci}
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_cistatic ssize_t adf4371_read(struct iio_dev *indio_dev,
3258c2ecf20Sopenharmony_ci			    uintptr_t private,
3268c2ecf20Sopenharmony_ci			    const struct iio_chan_spec *chan,
3278c2ecf20Sopenharmony_ci			    char *buf)
3288c2ecf20Sopenharmony_ci{
3298c2ecf20Sopenharmony_ci	struct adf4371_state *st = iio_priv(indio_dev);
3308c2ecf20Sopenharmony_ci	unsigned long long val = 0;
3318c2ecf20Sopenharmony_ci	unsigned int readval, reg, bit;
3328c2ecf20Sopenharmony_ci	int ret;
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	switch ((u32)private) {
3358c2ecf20Sopenharmony_ci	case ADF4371_FREQ:
3368c2ecf20Sopenharmony_ci		val = adf4371_pll_fract_n_get_rate(st, chan->channel);
3378c2ecf20Sopenharmony_ci		ret = regmap_read(st->regmap, ADF4371_REG(0x7C), &readval);
3388c2ecf20Sopenharmony_ci		if (ret < 0)
3398c2ecf20Sopenharmony_ci			break;
3408c2ecf20Sopenharmony_ci
3418c2ecf20Sopenharmony_ci		if (readval == 0x00) {
3428c2ecf20Sopenharmony_ci			dev_dbg(&st->spi->dev, "PLL un-locked\n");
3438c2ecf20Sopenharmony_ci			ret = -EBUSY;
3448c2ecf20Sopenharmony_ci		}
3458c2ecf20Sopenharmony_ci		break;
3468c2ecf20Sopenharmony_ci	case ADF4371_POWER_DOWN:
3478c2ecf20Sopenharmony_ci		reg = adf4371_pwrdown_ch[chan->channel].reg;
3488c2ecf20Sopenharmony_ci		bit = adf4371_pwrdown_ch[chan->channel].bit;
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci		ret = regmap_read(st->regmap, reg, &readval);
3518c2ecf20Sopenharmony_ci		if (ret < 0)
3528c2ecf20Sopenharmony_ci			break;
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci		val = !(readval & BIT(bit));
3558c2ecf20Sopenharmony_ci		break;
3568c2ecf20Sopenharmony_ci	case ADF4371_CHANNEL_NAME:
3578c2ecf20Sopenharmony_ci		return sprintf(buf, "%s\n", adf4371_ch_names[chan->channel]);
3588c2ecf20Sopenharmony_ci	default:
3598c2ecf20Sopenharmony_ci		ret = -EINVAL;
3608c2ecf20Sopenharmony_ci		val = 0;
3618c2ecf20Sopenharmony_ci		break;
3628c2ecf20Sopenharmony_ci	}
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	return ret < 0 ? ret : sprintf(buf, "%llu\n", val);
3658c2ecf20Sopenharmony_ci}
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_cistatic ssize_t adf4371_write(struct iio_dev *indio_dev,
3688c2ecf20Sopenharmony_ci			     uintptr_t private,
3698c2ecf20Sopenharmony_ci			     const struct iio_chan_spec *chan,
3708c2ecf20Sopenharmony_ci			     const char *buf, size_t len)
3718c2ecf20Sopenharmony_ci{
3728c2ecf20Sopenharmony_ci	struct adf4371_state *st = iio_priv(indio_dev);
3738c2ecf20Sopenharmony_ci	unsigned long long freq;
3748c2ecf20Sopenharmony_ci	bool power_down;
3758c2ecf20Sopenharmony_ci	unsigned int bit, readval, reg;
3768c2ecf20Sopenharmony_ci	int ret;
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci	mutex_lock(&st->lock);
3798c2ecf20Sopenharmony_ci	switch ((u32)private) {
3808c2ecf20Sopenharmony_ci	case ADF4371_FREQ:
3818c2ecf20Sopenharmony_ci		ret = kstrtoull(buf, 10, &freq);
3828c2ecf20Sopenharmony_ci		if (ret)
3838c2ecf20Sopenharmony_ci			break;
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci		ret = adf4371_set_freq(st, freq, chan->channel);
3868c2ecf20Sopenharmony_ci		break;
3878c2ecf20Sopenharmony_ci	case ADF4371_POWER_DOWN:
3888c2ecf20Sopenharmony_ci		ret = kstrtobool(buf, &power_down);
3898c2ecf20Sopenharmony_ci		if (ret)
3908c2ecf20Sopenharmony_ci			break;
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci		reg = adf4371_pwrdown_ch[chan->channel].reg;
3938c2ecf20Sopenharmony_ci		bit = adf4371_pwrdown_ch[chan->channel].bit;
3948c2ecf20Sopenharmony_ci		ret = regmap_read(st->regmap, reg, &readval);
3958c2ecf20Sopenharmony_ci		if (ret < 0)
3968c2ecf20Sopenharmony_ci			break;
3978c2ecf20Sopenharmony_ci
3988c2ecf20Sopenharmony_ci		readval &= ~BIT(bit);
3998c2ecf20Sopenharmony_ci		readval |= (!power_down << bit);
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_ci		ret = regmap_write(st->regmap, reg, readval);
4028c2ecf20Sopenharmony_ci		break;
4038c2ecf20Sopenharmony_ci	default:
4048c2ecf20Sopenharmony_ci		ret = -EINVAL;
4058c2ecf20Sopenharmony_ci		break;
4068c2ecf20Sopenharmony_ci	}
4078c2ecf20Sopenharmony_ci	mutex_unlock(&st->lock);
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci	return ret ? ret : len;
4108c2ecf20Sopenharmony_ci}
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci#define _ADF4371_EXT_INFO(_name, _ident) { \
4138c2ecf20Sopenharmony_ci		.name = _name, \
4148c2ecf20Sopenharmony_ci		.read = adf4371_read, \
4158c2ecf20Sopenharmony_ci		.write = adf4371_write, \
4168c2ecf20Sopenharmony_ci		.private = _ident, \
4178c2ecf20Sopenharmony_ci		.shared = IIO_SEPARATE, \
4188c2ecf20Sopenharmony_ci}
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_cistatic const struct iio_chan_spec_ext_info adf4371_ext_info[] = {
4218c2ecf20Sopenharmony_ci	/*
4228c2ecf20Sopenharmony_ci	 * Ideally we use IIO_CHAN_INFO_FREQUENCY, but there are
4238c2ecf20Sopenharmony_ci	 * values > 2^32 in order to support the entire frequency range
4248c2ecf20Sopenharmony_ci	 * in Hz. Using scale is a bit ugly.
4258c2ecf20Sopenharmony_ci	 */
4268c2ecf20Sopenharmony_ci	_ADF4371_EXT_INFO("frequency", ADF4371_FREQ),
4278c2ecf20Sopenharmony_ci	_ADF4371_EXT_INFO("powerdown", ADF4371_POWER_DOWN),
4288c2ecf20Sopenharmony_ci	_ADF4371_EXT_INFO("name", ADF4371_CHANNEL_NAME),
4298c2ecf20Sopenharmony_ci	{ },
4308c2ecf20Sopenharmony_ci};
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci#define ADF4371_CHANNEL(index) { \
4338c2ecf20Sopenharmony_ci		.type = IIO_ALTVOLTAGE, \
4348c2ecf20Sopenharmony_ci		.output = 1, \
4358c2ecf20Sopenharmony_ci		.channel = index, \
4368c2ecf20Sopenharmony_ci		.ext_info = adf4371_ext_info, \
4378c2ecf20Sopenharmony_ci		.indexed = 1, \
4388c2ecf20Sopenharmony_ci	}
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_cistatic const struct iio_chan_spec adf4371_chan[] = {
4418c2ecf20Sopenharmony_ci	ADF4371_CHANNEL(ADF4371_CH_RF8),
4428c2ecf20Sopenharmony_ci	ADF4371_CHANNEL(ADF4371_CH_RFAUX8),
4438c2ecf20Sopenharmony_ci	ADF4371_CHANNEL(ADF4371_CH_RF16),
4448c2ecf20Sopenharmony_ci	ADF4371_CHANNEL(ADF4371_CH_RF32),
4458c2ecf20Sopenharmony_ci};
4468c2ecf20Sopenharmony_ci
4478c2ecf20Sopenharmony_cistatic const struct adf4371_chip_info adf4371_chip_info[] = {
4488c2ecf20Sopenharmony_ci	[ADF4371] = {
4498c2ecf20Sopenharmony_ci		.channels = adf4371_chan,
4508c2ecf20Sopenharmony_ci		.num_channels = 4,
4518c2ecf20Sopenharmony_ci	},
4528c2ecf20Sopenharmony_ci	[ADF4372] = {
4538c2ecf20Sopenharmony_ci		.channels = adf4371_chan,
4548c2ecf20Sopenharmony_ci		.num_channels = 3,
4558c2ecf20Sopenharmony_ci	}
4568c2ecf20Sopenharmony_ci};
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_cistatic int adf4371_reg_access(struct iio_dev *indio_dev,
4598c2ecf20Sopenharmony_ci			      unsigned int reg,
4608c2ecf20Sopenharmony_ci			      unsigned int writeval,
4618c2ecf20Sopenharmony_ci			      unsigned int *readval)
4628c2ecf20Sopenharmony_ci{
4638c2ecf20Sopenharmony_ci	struct adf4371_state *st = iio_priv(indio_dev);
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	if (readval)
4668c2ecf20Sopenharmony_ci		return regmap_read(st->regmap, reg, readval);
4678c2ecf20Sopenharmony_ci	else
4688c2ecf20Sopenharmony_ci		return regmap_write(st->regmap, reg, writeval);
4698c2ecf20Sopenharmony_ci}
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_cistatic const struct iio_info adf4371_info = {
4728c2ecf20Sopenharmony_ci	.debugfs_reg_access = &adf4371_reg_access,
4738c2ecf20Sopenharmony_ci};
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_cistatic int adf4371_setup(struct adf4371_state *st)
4768c2ecf20Sopenharmony_ci{
4778c2ecf20Sopenharmony_ci	unsigned int synth_timeout = 2, timeout = 1, vco_alc_timeout = 1;
4788c2ecf20Sopenharmony_ci	unsigned int vco_band_div, tmp;
4798c2ecf20Sopenharmony_ci	int ret;
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci	/* Perform a software reset */
4828c2ecf20Sopenharmony_ci	ret = regmap_write(st->regmap, ADF4371_REG(0x0), ADF4371_RESET_CMD);
4838c2ecf20Sopenharmony_ci	if (ret < 0)
4848c2ecf20Sopenharmony_ci		return ret;
4858c2ecf20Sopenharmony_ci
4868c2ecf20Sopenharmony_ci	ret = regmap_multi_reg_write(st->regmap, adf4371_reg_defaults,
4878c2ecf20Sopenharmony_ci				     ARRAY_SIZE(adf4371_reg_defaults));
4888c2ecf20Sopenharmony_ci	if (ret < 0)
4898c2ecf20Sopenharmony_ci		return ret;
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_ci	/* Mute to Lock Detect */
4928c2ecf20Sopenharmony_ci	if (device_property_read_bool(&st->spi->dev, "adi,mute-till-lock-en")) {
4938c2ecf20Sopenharmony_ci		ret = regmap_update_bits(st->regmap, ADF4371_REG(0x25),
4948c2ecf20Sopenharmony_ci					 ADF4371_MUTE_LD_MSK,
4958c2ecf20Sopenharmony_ci					 ADF4371_MUTE_LD(1));
4968c2ecf20Sopenharmony_ci		if (ret < 0)
4978c2ecf20Sopenharmony_ci			return ret;
4988c2ecf20Sopenharmony_ci	}
4998c2ecf20Sopenharmony_ci
5008c2ecf20Sopenharmony_ci	/* Set address in ascending order, so the bulk_write() will work */
5018c2ecf20Sopenharmony_ci	ret = regmap_update_bits(st->regmap, ADF4371_REG(0x0),
5028c2ecf20Sopenharmony_ci				 ADF4371_ADDR_ASC_MSK | ADF4371_ADDR_ASC_R_MSK,
5038c2ecf20Sopenharmony_ci				 ADF4371_ADDR_ASC(1) | ADF4371_ADDR_ASC_R(1));
5048c2ecf20Sopenharmony_ci	if (ret < 0)
5058c2ecf20Sopenharmony_ci		return ret;
5068c2ecf20Sopenharmony_ci	/*
5078c2ecf20Sopenharmony_ci	 * Calculate and maximize PFD frequency
5088c2ecf20Sopenharmony_ci	 * fPFD = REFIN × ((1 + D)/(R × (1 + T)))
5098c2ecf20Sopenharmony_ci	 * Where D is the REFIN doubler bit, T is the reference divide by 2,
5108c2ecf20Sopenharmony_ci	 * R is the reference division factor
5118c2ecf20Sopenharmony_ci	 * TODO: it is assumed D and T equal 0.
5128c2ecf20Sopenharmony_ci	 */
5138c2ecf20Sopenharmony_ci	do {
5148c2ecf20Sopenharmony_ci		st->ref_div_factor++;
5158c2ecf20Sopenharmony_ci		st->fpfd = st->clkin_freq / st->ref_div_factor;
5168c2ecf20Sopenharmony_ci	} while (st->fpfd > ADF4371_MAX_FREQ_PFD);
5178c2ecf20Sopenharmony_ci
5188c2ecf20Sopenharmony_ci	/* Calculate Timeouts */
5198c2ecf20Sopenharmony_ci	vco_band_div = DIV_ROUND_UP(st->fpfd, 2400000U);
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci	tmp = DIV_ROUND_CLOSEST(st->fpfd, 1000000U);
5228c2ecf20Sopenharmony_ci	do {
5238c2ecf20Sopenharmony_ci		timeout++;
5248c2ecf20Sopenharmony_ci		if (timeout > 1023) {
5258c2ecf20Sopenharmony_ci			timeout = 2;
5268c2ecf20Sopenharmony_ci			synth_timeout++;
5278c2ecf20Sopenharmony_ci		}
5288c2ecf20Sopenharmony_ci	} while (synth_timeout * 1024 + timeout <= 20 * tmp);
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci	do {
5318c2ecf20Sopenharmony_ci		vco_alc_timeout++;
5328c2ecf20Sopenharmony_ci	} while (vco_alc_timeout * 1024 - timeout <= 50 * tmp);
5338c2ecf20Sopenharmony_ci
5348c2ecf20Sopenharmony_ci	st->buf[0] = vco_band_div;
5358c2ecf20Sopenharmony_ci	st->buf[1] = timeout & 0xFF;
5368c2ecf20Sopenharmony_ci	st->buf[2] = ADF4371_TIMEOUT(timeout >> 8) | 0x04;
5378c2ecf20Sopenharmony_ci	st->buf[3] = synth_timeout;
5388c2ecf20Sopenharmony_ci	st->buf[4] = ADF4371_VCO_ALC_TOUT(vco_alc_timeout);
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	return regmap_bulk_write(st->regmap, ADF4371_REG(0x30), st->buf, 5);
5418c2ecf20Sopenharmony_ci}
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_cistatic void adf4371_clk_disable(void *data)
5448c2ecf20Sopenharmony_ci{
5458c2ecf20Sopenharmony_ci	struct adf4371_state *st = data;
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci	clk_disable_unprepare(st->clkin);
5488c2ecf20Sopenharmony_ci}
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_cistatic int adf4371_probe(struct spi_device *spi)
5518c2ecf20Sopenharmony_ci{
5528c2ecf20Sopenharmony_ci	const struct spi_device_id *id = spi_get_device_id(spi);
5538c2ecf20Sopenharmony_ci	struct iio_dev *indio_dev;
5548c2ecf20Sopenharmony_ci	struct adf4371_state *st;
5558c2ecf20Sopenharmony_ci	struct regmap *regmap;
5568c2ecf20Sopenharmony_ci	int ret;
5578c2ecf20Sopenharmony_ci
5588c2ecf20Sopenharmony_ci	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
5598c2ecf20Sopenharmony_ci	if (!indio_dev)
5608c2ecf20Sopenharmony_ci		return -ENOMEM;
5618c2ecf20Sopenharmony_ci
5628c2ecf20Sopenharmony_ci	regmap = devm_regmap_init_spi(spi, &adf4371_regmap_config);
5638c2ecf20Sopenharmony_ci	if (IS_ERR(regmap)) {
5648c2ecf20Sopenharmony_ci		dev_err(&spi->dev, "Error initializing spi regmap: %ld\n",
5658c2ecf20Sopenharmony_ci			PTR_ERR(regmap));
5668c2ecf20Sopenharmony_ci		return PTR_ERR(regmap);
5678c2ecf20Sopenharmony_ci	}
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	st = iio_priv(indio_dev);
5708c2ecf20Sopenharmony_ci	spi_set_drvdata(spi, indio_dev);
5718c2ecf20Sopenharmony_ci	st->spi = spi;
5728c2ecf20Sopenharmony_ci	st->regmap = regmap;
5738c2ecf20Sopenharmony_ci	mutex_init(&st->lock);
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_ci	st->chip_info = &adf4371_chip_info[id->driver_data];
5768c2ecf20Sopenharmony_ci	indio_dev->name = id->name;
5778c2ecf20Sopenharmony_ci	indio_dev->info = &adf4371_info;
5788c2ecf20Sopenharmony_ci	indio_dev->modes = INDIO_DIRECT_MODE;
5798c2ecf20Sopenharmony_ci	indio_dev->channels = st->chip_info->channels;
5808c2ecf20Sopenharmony_ci	indio_dev->num_channels = st->chip_info->num_channels;
5818c2ecf20Sopenharmony_ci
5828c2ecf20Sopenharmony_ci	st->clkin = devm_clk_get(&spi->dev, "clkin");
5838c2ecf20Sopenharmony_ci	if (IS_ERR(st->clkin))
5848c2ecf20Sopenharmony_ci		return PTR_ERR(st->clkin);
5858c2ecf20Sopenharmony_ci
5868c2ecf20Sopenharmony_ci	ret = clk_prepare_enable(st->clkin);
5878c2ecf20Sopenharmony_ci	if (ret < 0)
5888c2ecf20Sopenharmony_ci		return ret;
5898c2ecf20Sopenharmony_ci
5908c2ecf20Sopenharmony_ci	ret = devm_add_action_or_reset(&spi->dev, adf4371_clk_disable, st);
5918c2ecf20Sopenharmony_ci	if (ret)
5928c2ecf20Sopenharmony_ci		return ret;
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_ci	st->clkin_freq = clk_get_rate(st->clkin);
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci	ret = adf4371_setup(st);
5978c2ecf20Sopenharmony_ci	if (ret < 0) {
5988c2ecf20Sopenharmony_ci		dev_err(&spi->dev, "ADF4371 setup failed\n");
5998c2ecf20Sopenharmony_ci		return ret;
6008c2ecf20Sopenharmony_ci	}
6018c2ecf20Sopenharmony_ci
6028c2ecf20Sopenharmony_ci	return devm_iio_device_register(&spi->dev, indio_dev);
6038c2ecf20Sopenharmony_ci}
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_cistatic const struct spi_device_id adf4371_id_table[] = {
6068c2ecf20Sopenharmony_ci	{ "adf4371", ADF4371 },
6078c2ecf20Sopenharmony_ci	{ "adf4372", ADF4372 },
6088c2ecf20Sopenharmony_ci	{}
6098c2ecf20Sopenharmony_ci};
6108c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(spi, adf4371_id_table);
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_cistatic const struct of_device_id adf4371_of_match[] = {
6138c2ecf20Sopenharmony_ci	{ .compatible = "adi,adf4371" },
6148c2ecf20Sopenharmony_ci	{ .compatible = "adi,adf4372" },
6158c2ecf20Sopenharmony_ci	{ },
6168c2ecf20Sopenharmony_ci};
6178c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, adf4371_of_match);
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_cistatic struct spi_driver adf4371_driver = {
6208c2ecf20Sopenharmony_ci	.driver = {
6218c2ecf20Sopenharmony_ci		.name = "adf4371",
6228c2ecf20Sopenharmony_ci		.of_match_table = adf4371_of_match,
6238c2ecf20Sopenharmony_ci	},
6248c2ecf20Sopenharmony_ci	.probe = adf4371_probe,
6258c2ecf20Sopenharmony_ci	.id_table = adf4371_id_table,
6268c2ecf20Sopenharmony_ci};
6278c2ecf20Sopenharmony_cimodule_spi_driver(adf4371_driver);
6288c2ecf20Sopenharmony_ci
6298c2ecf20Sopenharmony_ciMODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");
6308c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Analog Devices ADF4371 SPI PLL");
6318c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
632