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