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