162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Analog Devices ADF4371 SPI Wideband Synthesizer driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright 2019 Analog Devices Inc.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci#include <linux/bitfield.h>
862306a36Sopenharmony_ci#include <linux/clk.h>
962306a36Sopenharmony_ci#include <linux/device.h>
1062306a36Sopenharmony_ci#include <linux/err.h>
1162306a36Sopenharmony_ci#include <linux/gcd.h>
1262306a36Sopenharmony_ci#include <linux/kernel.h>
1362306a36Sopenharmony_ci#include <linux/module.h>
1462306a36Sopenharmony_ci#include <linux/regmap.h>
1562306a36Sopenharmony_ci#include <linux/sysfs.h>
1662306a36Sopenharmony_ci#include <linux/spi/spi.h>
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#include <linux/iio/iio.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci/* Registers address macro */
2162306a36Sopenharmony_ci#define ADF4371_REG(x)			(x)
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci/* ADF4371_REG0 */
2462306a36Sopenharmony_ci#define ADF4371_ADDR_ASC_MSK		BIT(2)
2562306a36Sopenharmony_ci#define ADF4371_ADDR_ASC(x)		FIELD_PREP(ADF4371_ADDR_ASC_MSK, x)
2662306a36Sopenharmony_ci#define ADF4371_ADDR_ASC_R_MSK		BIT(5)
2762306a36Sopenharmony_ci#define ADF4371_ADDR_ASC_R(x)		FIELD_PREP(ADF4371_ADDR_ASC_R_MSK, x)
2862306a36Sopenharmony_ci#define ADF4371_RESET_CMD		0x81
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci/* ADF4371_REG17 */
3162306a36Sopenharmony_ci#define ADF4371_FRAC2WORD_L_MSK		GENMASK(7, 1)
3262306a36Sopenharmony_ci#define ADF4371_FRAC2WORD_L(x)		FIELD_PREP(ADF4371_FRAC2WORD_L_MSK, x)
3362306a36Sopenharmony_ci#define ADF4371_FRAC1WORD_MSK		BIT(0)
3462306a36Sopenharmony_ci#define ADF4371_FRAC1WORD(x)		FIELD_PREP(ADF4371_FRAC1WORD_MSK, x)
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci/* ADF4371_REG18 */
3762306a36Sopenharmony_ci#define ADF4371_FRAC2WORD_H_MSK		GENMASK(6, 0)
3862306a36Sopenharmony_ci#define ADF4371_FRAC2WORD_H(x)		FIELD_PREP(ADF4371_FRAC2WORD_H_MSK, x)
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci/* ADF4371_REG1A */
4162306a36Sopenharmony_ci#define ADF4371_MOD2WORD_MSK		GENMASK(5, 0)
4262306a36Sopenharmony_ci#define ADF4371_MOD2WORD(x)		FIELD_PREP(ADF4371_MOD2WORD_MSK, x)
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci/* ADF4371_REG24 */
4562306a36Sopenharmony_ci#define ADF4371_RF_DIV_SEL_MSK		GENMASK(6, 4)
4662306a36Sopenharmony_ci#define ADF4371_RF_DIV_SEL(x)		FIELD_PREP(ADF4371_RF_DIV_SEL_MSK, x)
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci/* ADF4371_REG25 */
4962306a36Sopenharmony_ci#define ADF4371_MUTE_LD_MSK		BIT(7)
5062306a36Sopenharmony_ci#define ADF4371_MUTE_LD(x)		FIELD_PREP(ADF4371_MUTE_LD_MSK, x)
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci/* ADF4371_REG32 */
5362306a36Sopenharmony_ci#define ADF4371_TIMEOUT_MSK		GENMASK(1, 0)
5462306a36Sopenharmony_ci#define ADF4371_TIMEOUT(x)		FIELD_PREP(ADF4371_TIMEOUT_MSK, x)
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci/* ADF4371_REG34 */
5762306a36Sopenharmony_ci#define ADF4371_VCO_ALC_TOUT_MSK	GENMASK(4, 0)
5862306a36Sopenharmony_ci#define ADF4371_VCO_ALC_TOUT(x)		FIELD_PREP(ADF4371_VCO_ALC_TOUT_MSK, x)
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci/* Specifications */
6162306a36Sopenharmony_ci#define ADF4371_MIN_VCO_FREQ		4000000000ULL /* 4000 MHz */
6262306a36Sopenharmony_ci#define ADF4371_MAX_VCO_FREQ		8000000000ULL /* 8000 MHz */
6362306a36Sopenharmony_ci#define ADF4371_MAX_OUT_RF8_FREQ	ADF4371_MAX_VCO_FREQ /* Hz */
6462306a36Sopenharmony_ci#define ADF4371_MIN_OUT_RF8_FREQ	(ADF4371_MIN_VCO_FREQ / 64) /* Hz */
6562306a36Sopenharmony_ci#define ADF4371_MAX_OUT_RF16_FREQ	(ADF4371_MAX_VCO_FREQ * 2) /* Hz */
6662306a36Sopenharmony_ci#define ADF4371_MIN_OUT_RF16_FREQ	(ADF4371_MIN_VCO_FREQ * 2) /* Hz */
6762306a36Sopenharmony_ci#define ADF4371_MAX_OUT_RF32_FREQ	(ADF4371_MAX_VCO_FREQ * 4) /* Hz */
6862306a36Sopenharmony_ci#define ADF4371_MIN_OUT_RF32_FREQ	(ADF4371_MIN_VCO_FREQ * 4) /* Hz */
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci#define ADF4371_MAX_FREQ_PFD		250000000UL /* Hz */
7162306a36Sopenharmony_ci#define ADF4371_MAX_FREQ_REFIN		600000000UL /* Hz */
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci/* MOD1 is a 24-bit primary modulus with fixed value of 2^25 */
7462306a36Sopenharmony_ci#define ADF4371_MODULUS1		33554432ULL
7562306a36Sopenharmony_ci/* MOD2 is the programmable, 14-bit auxiliary fractional modulus */
7662306a36Sopenharmony_ci#define ADF4371_MAX_MODULUS2		BIT(14)
7762306a36Sopenharmony_ci
7862306a36Sopenharmony_ci#define ADF4371_CHECK_RANGE(freq, range) \
7962306a36Sopenharmony_ci	((freq > ADF4371_MAX_ ## range) || (freq < ADF4371_MIN_ ## range))
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_cienum {
8262306a36Sopenharmony_ci	ADF4371_FREQ,
8362306a36Sopenharmony_ci	ADF4371_POWER_DOWN,
8462306a36Sopenharmony_ci	ADF4371_CHANNEL_NAME
8562306a36Sopenharmony_ci};
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_cienum {
8862306a36Sopenharmony_ci	ADF4371_CH_RF8,
8962306a36Sopenharmony_ci	ADF4371_CH_RFAUX8,
9062306a36Sopenharmony_ci	ADF4371_CH_RF16,
9162306a36Sopenharmony_ci	ADF4371_CH_RF32
9262306a36Sopenharmony_ci};
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cienum adf4371_variant {
9562306a36Sopenharmony_ci	ADF4371,
9662306a36Sopenharmony_ci	ADF4372
9762306a36Sopenharmony_ci};
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistruct adf4371_pwrdown {
10062306a36Sopenharmony_ci	unsigned int reg;
10162306a36Sopenharmony_ci	unsigned int bit;
10262306a36Sopenharmony_ci};
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_cistatic const char * const adf4371_ch_names[] = {
10562306a36Sopenharmony_ci	"RF8x", "RFAUX8x", "RF16x", "RF32x"
10662306a36Sopenharmony_ci};
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_cistatic const struct adf4371_pwrdown adf4371_pwrdown_ch[4] = {
10962306a36Sopenharmony_ci	[ADF4371_CH_RF8] = { ADF4371_REG(0x25), 2 },
11062306a36Sopenharmony_ci	[ADF4371_CH_RFAUX8] = { ADF4371_REG(0x72), 3 },
11162306a36Sopenharmony_ci	[ADF4371_CH_RF16] = { ADF4371_REG(0x25), 3 },
11262306a36Sopenharmony_ci	[ADF4371_CH_RF32] = { ADF4371_REG(0x25), 4 },
11362306a36Sopenharmony_ci};
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_cistatic const struct reg_sequence adf4371_reg_defaults[] = {
11662306a36Sopenharmony_ci	{ ADF4371_REG(0x0),  0x18 },
11762306a36Sopenharmony_ci	{ ADF4371_REG(0x12), 0x40 },
11862306a36Sopenharmony_ci	{ ADF4371_REG(0x1E), 0x48 },
11962306a36Sopenharmony_ci	{ ADF4371_REG(0x20), 0x14 },
12062306a36Sopenharmony_ci	{ ADF4371_REG(0x22), 0x00 },
12162306a36Sopenharmony_ci	{ ADF4371_REG(0x23), 0x00 },
12262306a36Sopenharmony_ci	{ ADF4371_REG(0x24), 0x80 },
12362306a36Sopenharmony_ci	{ ADF4371_REG(0x25), 0x07 },
12462306a36Sopenharmony_ci	{ ADF4371_REG(0x27), 0xC5 },
12562306a36Sopenharmony_ci	{ ADF4371_REG(0x28), 0x83 },
12662306a36Sopenharmony_ci	{ ADF4371_REG(0x2C), 0x44 },
12762306a36Sopenharmony_ci	{ ADF4371_REG(0x2D), 0x11 },
12862306a36Sopenharmony_ci	{ ADF4371_REG(0x2E), 0x12 },
12962306a36Sopenharmony_ci	{ ADF4371_REG(0x2F), 0x94 },
13062306a36Sopenharmony_ci	{ ADF4371_REG(0x32), 0x04 },
13162306a36Sopenharmony_ci	{ ADF4371_REG(0x35), 0xFA },
13262306a36Sopenharmony_ci	{ ADF4371_REG(0x36), 0x30 },
13362306a36Sopenharmony_ci	{ ADF4371_REG(0x39), 0x07 },
13462306a36Sopenharmony_ci	{ ADF4371_REG(0x3A), 0x55 },
13562306a36Sopenharmony_ci	{ ADF4371_REG(0x3E), 0x0C },
13662306a36Sopenharmony_ci	{ ADF4371_REG(0x3F), 0x80 },
13762306a36Sopenharmony_ci	{ ADF4371_REG(0x40), 0x50 },
13862306a36Sopenharmony_ci	{ ADF4371_REG(0x41), 0x28 },
13962306a36Sopenharmony_ci	{ ADF4371_REG(0x47), 0xC0 },
14062306a36Sopenharmony_ci	{ ADF4371_REG(0x52), 0xF4 },
14162306a36Sopenharmony_ci	{ ADF4371_REG(0x70), 0x03 },
14262306a36Sopenharmony_ci	{ ADF4371_REG(0x71), 0x60 },
14362306a36Sopenharmony_ci	{ ADF4371_REG(0x72), 0x32 },
14462306a36Sopenharmony_ci};
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_cistatic const struct regmap_config adf4371_regmap_config = {
14762306a36Sopenharmony_ci	.reg_bits = 16,
14862306a36Sopenharmony_ci	.val_bits = 8,
14962306a36Sopenharmony_ci	.read_flag_mask = BIT(7),
15062306a36Sopenharmony_ci};
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_cistruct adf4371_chip_info {
15362306a36Sopenharmony_ci	unsigned int num_channels;
15462306a36Sopenharmony_ci	const struct iio_chan_spec *channels;
15562306a36Sopenharmony_ci};
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_cistruct adf4371_state {
15862306a36Sopenharmony_ci	struct spi_device *spi;
15962306a36Sopenharmony_ci	struct regmap *regmap;
16062306a36Sopenharmony_ci	struct clk *clkin;
16162306a36Sopenharmony_ci	/*
16262306a36Sopenharmony_ci	 * Lock for accessing device registers. Some operations require
16362306a36Sopenharmony_ci	 * multiple consecutive R/W operations, during which the device
16462306a36Sopenharmony_ci	 * shouldn't be interrupted. The buffers are also shared across
16562306a36Sopenharmony_ci	 * all operations so need to be protected on stand alone reads and
16662306a36Sopenharmony_ci	 * writes.
16762306a36Sopenharmony_ci	 */
16862306a36Sopenharmony_ci	struct mutex lock;
16962306a36Sopenharmony_ci	const struct adf4371_chip_info *chip_info;
17062306a36Sopenharmony_ci	unsigned long clkin_freq;
17162306a36Sopenharmony_ci	unsigned long fpfd;
17262306a36Sopenharmony_ci	unsigned int integer;
17362306a36Sopenharmony_ci	unsigned int fract1;
17462306a36Sopenharmony_ci	unsigned int fract2;
17562306a36Sopenharmony_ci	unsigned int mod2;
17662306a36Sopenharmony_ci	unsigned int rf_div_sel;
17762306a36Sopenharmony_ci	unsigned int ref_div_factor;
17862306a36Sopenharmony_ci	u8 buf[10] __aligned(IIO_DMA_MINALIGN);
17962306a36Sopenharmony_ci};
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_cistatic unsigned long long adf4371_pll_fract_n_get_rate(struct adf4371_state *st,
18262306a36Sopenharmony_ci						       u32 channel)
18362306a36Sopenharmony_ci{
18462306a36Sopenharmony_ci	unsigned long long val, tmp;
18562306a36Sopenharmony_ci	unsigned int ref_div_sel;
18662306a36Sopenharmony_ci
18762306a36Sopenharmony_ci	val = (((u64)st->integer * ADF4371_MODULUS1) + st->fract1) * st->fpfd;
18862306a36Sopenharmony_ci	tmp = (u64)st->fract2 * st->fpfd;
18962306a36Sopenharmony_ci	do_div(tmp, st->mod2);
19062306a36Sopenharmony_ci	val += tmp + ADF4371_MODULUS1 / 2;
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	if (channel == ADF4371_CH_RF8 || channel == ADF4371_CH_RFAUX8)
19362306a36Sopenharmony_ci		ref_div_sel = st->rf_div_sel;
19462306a36Sopenharmony_ci	else
19562306a36Sopenharmony_ci		ref_div_sel = 0;
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_ci	do_div(val, ADF4371_MODULUS1 * (1 << ref_div_sel));
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	if (channel == ADF4371_CH_RF16)
20062306a36Sopenharmony_ci		val <<= 1;
20162306a36Sopenharmony_ci	else if (channel == ADF4371_CH_RF32)
20262306a36Sopenharmony_ci		val <<= 2;
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	return val;
20562306a36Sopenharmony_ci}
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_cistatic void adf4371_pll_fract_n_compute(unsigned long long vco,
20862306a36Sopenharmony_ci				       unsigned long long pfd,
20962306a36Sopenharmony_ci				       unsigned int *integer,
21062306a36Sopenharmony_ci				       unsigned int *fract1,
21162306a36Sopenharmony_ci				       unsigned int *fract2,
21262306a36Sopenharmony_ci				       unsigned int *mod2)
21362306a36Sopenharmony_ci{
21462306a36Sopenharmony_ci	unsigned long long tmp;
21562306a36Sopenharmony_ci	u32 gcd_div;
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	tmp = do_div(vco, pfd);
21862306a36Sopenharmony_ci	tmp = tmp * ADF4371_MODULUS1;
21962306a36Sopenharmony_ci	*fract2 = do_div(tmp, pfd);
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	*integer = vco;
22262306a36Sopenharmony_ci	*fract1 = tmp;
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ci	*mod2 = pfd;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	while (*mod2 > ADF4371_MAX_MODULUS2) {
22762306a36Sopenharmony_ci		*mod2 >>= 1;
22862306a36Sopenharmony_ci		*fract2 >>= 1;
22962306a36Sopenharmony_ci	}
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	gcd_div = gcd(*fract2, *mod2);
23262306a36Sopenharmony_ci	*mod2 /= gcd_div;
23362306a36Sopenharmony_ci	*fract2 /= gcd_div;
23462306a36Sopenharmony_ci}
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_cistatic int adf4371_set_freq(struct adf4371_state *st, unsigned long long freq,
23762306a36Sopenharmony_ci			    unsigned int channel)
23862306a36Sopenharmony_ci{
23962306a36Sopenharmony_ci	u32 cp_bleed;
24062306a36Sopenharmony_ci	u8 int_mode = 0;
24162306a36Sopenharmony_ci	int ret;
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	switch (channel) {
24462306a36Sopenharmony_ci	case ADF4371_CH_RF8:
24562306a36Sopenharmony_ci	case ADF4371_CH_RFAUX8:
24662306a36Sopenharmony_ci		if (ADF4371_CHECK_RANGE(freq, OUT_RF8_FREQ))
24762306a36Sopenharmony_ci			return -EINVAL;
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci		st->rf_div_sel = 0;
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_ci		while (freq < ADF4371_MIN_VCO_FREQ) {
25262306a36Sopenharmony_ci			freq <<= 1;
25362306a36Sopenharmony_ci			st->rf_div_sel++;
25462306a36Sopenharmony_ci		}
25562306a36Sopenharmony_ci		break;
25662306a36Sopenharmony_ci	case ADF4371_CH_RF16:
25762306a36Sopenharmony_ci		/* ADF4371 RF16 8000...16000 MHz */
25862306a36Sopenharmony_ci		if (ADF4371_CHECK_RANGE(freq, OUT_RF16_FREQ))
25962306a36Sopenharmony_ci			return -EINVAL;
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci		freq >>= 1;
26262306a36Sopenharmony_ci		break;
26362306a36Sopenharmony_ci	case ADF4371_CH_RF32:
26462306a36Sopenharmony_ci		/* ADF4371 RF32 16000...32000 MHz */
26562306a36Sopenharmony_ci		if (ADF4371_CHECK_RANGE(freq, OUT_RF32_FREQ))
26662306a36Sopenharmony_ci			return -EINVAL;
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci		freq >>= 2;
26962306a36Sopenharmony_ci		break;
27062306a36Sopenharmony_ci	default:
27162306a36Sopenharmony_ci		return -EINVAL;
27262306a36Sopenharmony_ci	}
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci	adf4371_pll_fract_n_compute(freq, st->fpfd, &st->integer, &st->fract1,
27562306a36Sopenharmony_ci				    &st->fract2, &st->mod2);
27662306a36Sopenharmony_ci	st->buf[0] = st->integer >> 8;
27762306a36Sopenharmony_ci	st->buf[1] = 0x40; /* REG12 default */
27862306a36Sopenharmony_ci	st->buf[2] = 0x00;
27962306a36Sopenharmony_ci	st->buf[3] = st->fract1 & 0xFF;
28062306a36Sopenharmony_ci	st->buf[4] = st->fract1 >> 8;
28162306a36Sopenharmony_ci	st->buf[5] = st->fract1 >> 16;
28262306a36Sopenharmony_ci	st->buf[6] = ADF4371_FRAC2WORD_L(st->fract2 & 0x7F) |
28362306a36Sopenharmony_ci		     ADF4371_FRAC1WORD(st->fract1 >> 24);
28462306a36Sopenharmony_ci	st->buf[7] = ADF4371_FRAC2WORD_H(st->fract2 >> 7);
28562306a36Sopenharmony_ci	st->buf[8] = st->mod2 & 0xFF;
28662306a36Sopenharmony_ci	st->buf[9] = ADF4371_MOD2WORD(st->mod2 >> 8);
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	ret = regmap_bulk_write(st->regmap, ADF4371_REG(0x11), st->buf, 10);
28962306a36Sopenharmony_ci	if (ret < 0)
29062306a36Sopenharmony_ci		return ret;
29162306a36Sopenharmony_ci	/*
29262306a36Sopenharmony_ci	 * The R counter allows the input reference frequency to be
29362306a36Sopenharmony_ci	 * divided down to produce the reference clock to the PFD
29462306a36Sopenharmony_ci	 */
29562306a36Sopenharmony_ci	ret = regmap_write(st->regmap, ADF4371_REG(0x1F), st->ref_div_factor);
29662306a36Sopenharmony_ci	if (ret < 0)
29762306a36Sopenharmony_ci		return ret;
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci	ret = regmap_update_bits(st->regmap, ADF4371_REG(0x24),
30062306a36Sopenharmony_ci				 ADF4371_RF_DIV_SEL_MSK,
30162306a36Sopenharmony_ci				 ADF4371_RF_DIV_SEL(st->rf_div_sel));
30262306a36Sopenharmony_ci	if (ret < 0)
30362306a36Sopenharmony_ci		return ret;
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	cp_bleed = DIV_ROUND_UP(400 * 1750, st->integer * 375);
30662306a36Sopenharmony_ci	cp_bleed = clamp(cp_bleed, 1U, 255U);
30762306a36Sopenharmony_ci	ret = regmap_write(st->regmap, ADF4371_REG(0x26), cp_bleed);
30862306a36Sopenharmony_ci	if (ret < 0)
30962306a36Sopenharmony_ci		return ret;
31062306a36Sopenharmony_ci	/*
31162306a36Sopenharmony_ci	 * Set to 1 when in INT mode (when FRAC1 = FRAC2 = 0),
31262306a36Sopenharmony_ci	 * and set to 0 when in FRAC mode.
31362306a36Sopenharmony_ci	 */
31462306a36Sopenharmony_ci	if (st->fract1 == 0 && st->fract2 == 0)
31562306a36Sopenharmony_ci		int_mode = 0x01;
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_ci	ret = regmap_write(st->regmap, ADF4371_REG(0x2B), int_mode);
31862306a36Sopenharmony_ci	if (ret < 0)
31962306a36Sopenharmony_ci		return ret;
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	return regmap_write(st->regmap, ADF4371_REG(0x10), st->integer & 0xFF);
32262306a36Sopenharmony_ci}
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_cistatic ssize_t adf4371_read(struct iio_dev *indio_dev,
32562306a36Sopenharmony_ci			    uintptr_t private,
32662306a36Sopenharmony_ci			    const struct iio_chan_spec *chan,
32762306a36Sopenharmony_ci			    char *buf)
32862306a36Sopenharmony_ci{
32962306a36Sopenharmony_ci	struct adf4371_state *st = iio_priv(indio_dev);
33062306a36Sopenharmony_ci	unsigned long long val = 0;
33162306a36Sopenharmony_ci	unsigned int readval, reg, bit;
33262306a36Sopenharmony_ci	int ret;
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	switch ((u32)private) {
33562306a36Sopenharmony_ci	case ADF4371_FREQ:
33662306a36Sopenharmony_ci		val = adf4371_pll_fract_n_get_rate(st, chan->channel);
33762306a36Sopenharmony_ci		ret = regmap_read(st->regmap, ADF4371_REG(0x7C), &readval);
33862306a36Sopenharmony_ci		if (ret < 0)
33962306a36Sopenharmony_ci			break;
34062306a36Sopenharmony_ci
34162306a36Sopenharmony_ci		if (readval == 0x00) {
34262306a36Sopenharmony_ci			dev_dbg(&st->spi->dev, "PLL un-locked\n");
34362306a36Sopenharmony_ci			ret = -EBUSY;
34462306a36Sopenharmony_ci		}
34562306a36Sopenharmony_ci		break;
34662306a36Sopenharmony_ci	case ADF4371_POWER_DOWN:
34762306a36Sopenharmony_ci		reg = adf4371_pwrdown_ch[chan->channel].reg;
34862306a36Sopenharmony_ci		bit = adf4371_pwrdown_ch[chan->channel].bit;
34962306a36Sopenharmony_ci
35062306a36Sopenharmony_ci		ret = regmap_read(st->regmap, reg, &readval);
35162306a36Sopenharmony_ci		if (ret < 0)
35262306a36Sopenharmony_ci			break;
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci		val = !(readval & BIT(bit));
35562306a36Sopenharmony_ci		break;
35662306a36Sopenharmony_ci	case ADF4371_CHANNEL_NAME:
35762306a36Sopenharmony_ci		return sprintf(buf, "%s\n", adf4371_ch_names[chan->channel]);
35862306a36Sopenharmony_ci	default:
35962306a36Sopenharmony_ci		ret = -EINVAL;
36062306a36Sopenharmony_ci		val = 0;
36162306a36Sopenharmony_ci		break;
36262306a36Sopenharmony_ci	}
36362306a36Sopenharmony_ci
36462306a36Sopenharmony_ci	return ret < 0 ? ret : sprintf(buf, "%llu\n", val);
36562306a36Sopenharmony_ci}
36662306a36Sopenharmony_ci
36762306a36Sopenharmony_cistatic ssize_t adf4371_write(struct iio_dev *indio_dev,
36862306a36Sopenharmony_ci			     uintptr_t private,
36962306a36Sopenharmony_ci			     const struct iio_chan_spec *chan,
37062306a36Sopenharmony_ci			     const char *buf, size_t len)
37162306a36Sopenharmony_ci{
37262306a36Sopenharmony_ci	struct adf4371_state *st = iio_priv(indio_dev);
37362306a36Sopenharmony_ci	unsigned long long freq;
37462306a36Sopenharmony_ci	bool power_down;
37562306a36Sopenharmony_ci	unsigned int bit, readval, reg;
37662306a36Sopenharmony_ci	int ret;
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci	mutex_lock(&st->lock);
37962306a36Sopenharmony_ci	switch ((u32)private) {
38062306a36Sopenharmony_ci	case ADF4371_FREQ:
38162306a36Sopenharmony_ci		ret = kstrtoull(buf, 10, &freq);
38262306a36Sopenharmony_ci		if (ret)
38362306a36Sopenharmony_ci			break;
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci		ret = adf4371_set_freq(st, freq, chan->channel);
38662306a36Sopenharmony_ci		break;
38762306a36Sopenharmony_ci	case ADF4371_POWER_DOWN:
38862306a36Sopenharmony_ci		ret = kstrtobool(buf, &power_down);
38962306a36Sopenharmony_ci		if (ret)
39062306a36Sopenharmony_ci			break;
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci		reg = adf4371_pwrdown_ch[chan->channel].reg;
39362306a36Sopenharmony_ci		bit = adf4371_pwrdown_ch[chan->channel].bit;
39462306a36Sopenharmony_ci		ret = regmap_read(st->regmap, reg, &readval);
39562306a36Sopenharmony_ci		if (ret < 0)
39662306a36Sopenharmony_ci			break;
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci		readval &= ~BIT(bit);
39962306a36Sopenharmony_ci		readval |= (!power_down << bit);
40062306a36Sopenharmony_ci
40162306a36Sopenharmony_ci		ret = regmap_write(st->regmap, reg, readval);
40262306a36Sopenharmony_ci		break;
40362306a36Sopenharmony_ci	default:
40462306a36Sopenharmony_ci		ret = -EINVAL;
40562306a36Sopenharmony_ci		break;
40662306a36Sopenharmony_ci	}
40762306a36Sopenharmony_ci	mutex_unlock(&st->lock);
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci	return ret ? ret : len;
41062306a36Sopenharmony_ci}
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_ci#define _ADF4371_EXT_INFO(_name, _ident) { \
41362306a36Sopenharmony_ci		.name = _name, \
41462306a36Sopenharmony_ci		.read = adf4371_read, \
41562306a36Sopenharmony_ci		.write = adf4371_write, \
41662306a36Sopenharmony_ci		.private = _ident, \
41762306a36Sopenharmony_ci		.shared = IIO_SEPARATE, \
41862306a36Sopenharmony_ci}
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_cistatic const struct iio_chan_spec_ext_info adf4371_ext_info[] = {
42162306a36Sopenharmony_ci	/*
42262306a36Sopenharmony_ci	 * Ideally we use IIO_CHAN_INFO_FREQUENCY, but there are
42362306a36Sopenharmony_ci	 * values > 2^32 in order to support the entire frequency range
42462306a36Sopenharmony_ci	 * in Hz. Using scale is a bit ugly.
42562306a36Sopenharmony_ci	 */
42662306a36Sopenharmony_ci	_ADF4371_EXT_INFO("frequency", ADF4371_FREQ),
42762306a36Sopenharmony_ci	_ADF4371_EXT_INFO("powerdown", ADF4371_POWER_DOWN),
42862306a36Sopenharmony_ci	_ADF4371_EXT_INFO("name", ADF4371_CHANNEL_NAME),
42962306a36Sopenharmony_ci	{ },
43062306a36Sopenharmony_ci};
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci#define ADF4371_CHANNEL(index) { \
43362306a36Sopenharmony_ci		.type = IIO_ALTVOLTAGE, \
43462306a36Sopenharmony_ci		.output = 1, \
43562306a36Sopenharmony_ci		.channel = index, \
43662306a36Sopenharmony_ci		.ext_info = adf4371_ext_info, \
43762306a36Sopenharmony_ci		.indexed = 1, \
43862306a36Sopenharmony_ci	}
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_cistatic const struct iio_chan_spec adf4371_chan[] = {
44162306a36Sopenharmony_ci	ADF4371_CHANNEL(ADF4371_CH_RF8),
44262306a36Sopenharmony_ci	ADF4371_CHANNEL(ADF4371_CH_RFAUX8),
44362306a36Sopenharmony_ci	ADF4371_CHANNEL(ADF4371_CH_RF16),
44462306a36Sopenharmony_ci	ADF4371_CHANNEL(ADF4371_CH_RF32),
44562306a36Sopenharmony_ci};
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_cistatic const struct adf4371_chip_info adf4371_chip_info[] = {
44862306a36Sopenharmony_ci	[ADF4371] = {
44962306a36Sopenharmony_ci		.channels = adf4371_chan,
45062306a36Sopenharmony_ci		.num_channels = 4,
45162306a36Sopenharmony_ci	},
45262306a36Sopenharmony_ci	[ADF4372] = {
45362306a36Sopenharmony_ci		.channels = adf4371_chan,
45462306a36Sopenharmony_ci		.num_channels = 3,
45562306a36Sopenharmony_ci	}
45662306a36Sopenharmony_ci};
45762306a36Sopenharmony_ci
45862306a36Sopenharmony_cistatic int adf4371_reg_access(struct iio_dev *indio_dev,
45962306a36Sopenharmony_ci			      unsigned int reg,
46062306a36Sopenharmony_ci			      unsigned int writeval,
46162306a36Sopenharmony_ci			      unsigned int *readval)
46262306a36Sopenharmony_ci{
46362306a36Sopenharmony_ci	struct adf4371_state *st = iio_priv(indio_dev);
46462306a36Sopenharmony_ci
46562306a36Sopenharmony_ci	if (readval)
46662306a36Sopenharmony_ci		return regmap_read(st->regmap, reg, readval);
46762306a36Sopenharmony_ci	else
46862306a36Sopenharmony_ci		return regmap_write(st->regmap, reg, writeval);
46962306a36Sopenharmony_ci}
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_cistatic const struct iio_info adf4371_info = {
47262306a36Sopenharmony_ci	.debugfs_reg_access = &adf4371_reg_access,
47362306a36Sopenharmony_ci};
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_cistatic int adf4371_setup(struct adf4371_state *st)
47662306a36Sopenharmony_ci{
47762306a36Sopenharmony_ci	unsigned int synth_timeout = 2, timeout = 1, vco_alc_timeout = 1;
47862306a36Sopenharmony_ci	unsigned int vco_band_div, tmp;
47962306a36Sopenharmony_ci	int ret;
48062306a36Sopenharmony_ci
48162306a36Sopenharmony_ci	/* Perform a software reset */
48262306a36Sopenharmony_ci	ret = regmap_write(st->regmap, ADF4371_REG(0x0), ADF4371_RESET_CMD);
48362306a36Sopenharmony_ci	if (ret < 0)
48462306a36Sopenharmony_ci		return ret;
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci	ret = regmap_multi_reg_write(st->regmap, adf4371_reg_defaults,
48762306a36Sopenharmony_ci				     ARRAY_SIZE(adf4371_reg_defaults));
48862306a36Sopenharmony_ci	if (ret < 0)
48962306a36Sopenharmony_ci		return ret;
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci	/* Mute to Lock Detect */
49262306a36Sopenharmony_ci	if (device_property_read_bool(&st->spi->dev, "adi,mute-till-lock-en")) {
49362306a36Sopenharmony_ci		ret = regmap_update_bits(st->regmap, ADF4371_REG(0x25),
49462306a36Sopenharmony_ci					 ADF4371_MUTE_LD_MSK,
49562306a36Sopenharmony_ci					 ADF4371_MUTE_LD(1));
49662306a36Sopenharmony_ci		if (ret < 0)
49762306a36Sopenharmony_ci			return ret;
49862306a36Sopenharmony_ci	}
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci	/* Set address in ascending order, so the bulk_write() will work */
50162306a36Sopenharmony_ci	ret = regmap_update_bits(st->regmap, ADF4371_REG(0x0),
50262306a36Sopenharmony_ci				 ADF4371_ADDR_ASC_MSK | ADF4371_ADDR_ASC_R_MSK,
50362306a36Sopenharmony_ci				 ADF4371_ADDR_ASC(1) | ADF4371_ADDR_ASC_R(1));
50462306a36Sopenharmony_ci	if (ret < 0)
50562306a36Sopenharmony_ci		return ret;
50662306a36Sopenharmony_ci	/*
50762306a36Sopenharmony_ci	 * Calculate and maximize PFD frequency
50862306a36Sopenharmony_ci	 * fPFD = REFIN × ((1 + D)/(R × (1 + T)))
50962306a36Sopenharmony_ci	 * Where D is the REFIN doubler bit, T is the reference divide by 2,
51062306a36Sopenharmony_ci	 * R is the reference division factor
51162306a36Sopenharmony_ci	 * TODO: it is assumed D and T equal 0.
51262306a36Sopenharmony_ci	 */
51362306a36Sopenharmony_ci	do {
51462306a36Sopenharmony_ci		st->ref_div_factor++;
51562306a36Sopenharmony_ci		st->fpfd = st->clkin_freq / st->ref_div_factor;
51662306a36Sopenharmony_ci	} while (st->fpfd > ADF4371_MAX_FREQ_PFD);
51762306a36Sopenharmony_ci
51862306a36Sopenharmony_ci	/* Calculate Timeouts */
51962306a36Sopenharmony_ci	vco_band_div = DIV_ROUND_UP(st->fpfd, 2400000U);
52062306a36Sopenharmony_ci
52162306a36Sopenharmony_ci	tmp = DIV_ROUND_CLOSEST(st->fpfd, 1000000U);
52262306a36Sopenharmony_ci	do {
52362306a36Sopenharmony_ci		timeout++;
52462306a36Sopenharmony_ci		if (timeout > 1023) {
52562306a36Sopenharmony_ci			timeout = 2;
52662306a36Sopenharmony_ci			synth_timeout++;
52762306a36Sopenharmony_ci		}
52862306a36Sopenharmony_ci	} while (synth_timeout * 1024 + timeout <= 20 * tmp);
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	do {
53162306a36Sopenharmony_ci		vco_alc_timeout++;
53262306a36Sopenharmony_ci	} while (vco_alc_timeout * 1024 - timeout <= 50 * tmp);
53362306a36Sopenharmony_ci
53462306a36Sopenharmony_ci	st->buf[0] = vco_band_div;
53562306a36Sopenharmony_ci	st->buf[1] = timeout & 0xFF;
53662306a36Sopenharmony_ci	st->buf[2] = ADF4371_TIMEOUT(timeout >> 8) | 0x04;
53762306a36Sopenharmony_ci	st->buf[3] = synth_timeout;
53862306a36Sopenharmony_ci	st->buf[4] = ADF4371_VCO_ALC_TOUT(vco_alc_timeout);
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci	return regmap_bulk_write(st->regmap, ADF4371_REG(0x30), st->buf, 5);
54162306a36Sopenharmony_ci}
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_cistatic int adf4371_probe(struct spi_device *spi)
54462306a36Sopenharmony_ci{
54562306a36Sopenharmony_ci	const struct spi_device_id *id = spi_get_device_id(spi);
54662306a36Sopenharmony_ci	struct iio_dev *indio_dev;
54762306a36Sopenharmony_ci	struct adf4371_state *st;
54862306a36Sopenharmony_ci	struct regmap *regmap;
54962306a36Sopenharmony_ci	int ret;
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
55262306a36Sopenharmony_ci	if (!indio_dev)
55362306a36Sopenharmony_ci		return -ENOMEM;
55462306a36Sopenharmony_ci
55562306a36Sopenharmony_ci	regmap = devm_regmap_init_spi(spi, &adf4371_regmap_config);
55662306a36Sopenharmony_ci	if (IS_ERR(regmap)) {
55762306a36Sopenharmony_ci		dev_err(&spi->dev, "Error initializing spi regmap: %ld\n",
55862306a36Sopenharmony_ci			PTR_ERR(regmap));
55962306a36Sopenharmony_ci		return PTR_ERR(regmap);
56062306a36Sopenharmony_ci	}
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_ci	st = iio_priv(indio_dev);
56362306a36Sopenharmony_ci	spi_set_drvdata(spi, indio_dev);
56462306a36Sopenharmony_ci	st->spi = spi;
56562306a36Sopenharmony_ci	st->regmap = regmap;
56662306a36Sopenharmony_ci	mutex_init(&st->lock);
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci	st->chip_info = &adf4371_chip_info[id->driver_data];
56962306a36Sopenharmony_ci	indio_dev->name = id->name;
57062306a36Sopenharmony_ci	indio_dev->info = &adf4371_info;
57162306a36Sopenharmony_ci	indio_dev->modes = INDIO_DIRECT_MODE;
57262306a36Sopenharmony_ci	indio_dev->channels = st->chip_info->channels;
57362306a36Sopenharmony_ci	indio_dev->num_channels = st->chip_info->num_channels;
57462306a36Sopenharmony_ci
57562306a36Sopenharmony_ci	st->clkin = devm_clk_get_enabled(&spi->dev, "clkin");
57662306a36Sopenharmony_ci	if (IS_ERR(st->clkin))
57762306a36Sopenharmony_ci		return PTR_ERR(st->clkin);
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci	st->clkin_freq = clk_get_rate(st->clkin);
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci	ret = adf4371_setup(st);
58262306a36Sopenharmony_ci	if (ret < 0) {
58362306a36Sopenharmony_ci		dev_err(&spi->dev, "ADF4371 setup failed\n");
58462306a36Sopenharmony_ci		return ret;
58562306a36Sopenharmony_ci	}
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci	return devm_iio_device_register(&spi->dev, indio_dev);
58862306a36Sopenharmony_ci}
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_cistatic const struct spi_device_id adf4371_id_table[] = {
59162306a36Sopenharmony_ci	{ "adf4371", ADF4371 },
59262306a36Sopenharmony_ci	{ "adf4372", ADF4372 },
59362306a36Sopenharmony_ci	{}
59462306a36Sopenharmony_ci};
59562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, adf4371_id_table);
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_cistatic const struct of_device_id adf4371_of_match[] = {
59862306a36Sopenharmony_ci	{ .compatible = "adi,adf4371" },
59962306a36Sopenharmony_ci	{ .compatible = "adi,adf4372" },
60062306a36Sopenharmony_ci	{ },
60162306a36Sopenharmony_ci};
60262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, adf4371_of_match);
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_cistatic struct spi_driver adf4371_driver = {
60562306a36Sopenharmony_ci	.driver = {
60662306a36Sopenharmony_ci		.name = "adf4371",
60762306a36Sopenharmony_ci		.of_match_table = adf4371_of_match,
60862306a36Sopenharmony_ci	},
60962306a36Sopenharmony_ci	.probe = adf4371_probe,
61062306a36Sopenharmony_ci	.id_table = adf4371_id_table,
61162306a36Sopenharmony_ci};
61262306a36Sopenharmony_cimodule_spi_driver(adf4371_driver);
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ciMODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");
61562306a36Sopenharmony_ciMODULE_DESCRIPTION("Analog Devices ADF4371 SPI PLL");
61662306a36Sopenharmony_ciMODULE_LICENSE("GPL");
617