| // SPDX-License-Identifier: GPL-2.0 | |
| /* | |
| * Analog Devices ADF4371 SPI Wideband Synthesizer driver | |
| * | |
| * Copyright 2019 Analog Devices Inc. | |
| */ | |
| #include "linux/dev_printk.h" | |
| #include <linux/bitfield.h> | |
| #include <linux/clk.h> | |
| #include <linux/device.h> | |
| #include <linux/err.h> | |
| #include <linux/gcd.h> | |
| #include <linux/kernel.h> | |
| #include <linux/module.h> | |
| #include <linux/regmap.h> | |
| #include <linux/sysfs.h> | |
| #include <linux/spi/spi.h> | |
| #include <linux/iio/iio.h> | |
| /* Registers address macro */ | |
| #define ADF4371_REG(x) (x) | |
| /* ADF4371_REG0 */ | |
| #define ADF4371_ADDR_ASC_MSK BIT(2) | |
| #define ADF4371_ADDR_ASC(x) FIELD_PREP(ADF4371_ADDR_ASC_MSK, x) | |
| #define ADF4371_ADDR_ASC_R_MSK BIT(5) | |
| #define ADF4371_ADDR_ASC_R(x) FIELD_PREP(ADF4371_ADDR_ASC_R_MSK, x) | |
| #define ADF4371_RESET_CMD 0x81 | |
| /* ADF4371_REG17 */ | |
| #define ADF4371_FRAC2WORD_L_MSK GENMASK(7, 1) | |
| #define ADF4371_FRAC2WORD_L(x) FIELD_PREP(ADF4371_FRAC2WORD_L_MSK, x) | |
| #define ADF4371_FRAC1WORD_MSK BIT(0) | |
| #define ADF4371_FRAC1WORD(x) FIELD_PREP(ADF4371_FRAC1WORD_MSK, x) | |
| /* ADF4371_REG18 */ | |
| #define ADF4371_FRAC2WORD_H_MSK GENMASK(6, 0) | |
| #define ADF4371_FRAC2WORD_H(x) FIELD_PREP(ADF4371_FRAC2WORD_H_MSK, x) | |
| /* ADF4371_REG1A */ | |
| #define ADF4371_MOD2WORD_MSK GENMASK(5, 0) | |
| #define ADF4371_MOD2WORD(x) FIELD_PREP(ADF4371_MOD2WORD_MSK, x) | |
| /* ADF4371_REG22 */ | |
| #define ADF4371_REFIN_MODE_MASK BIT(6) | |
| #define ADF4371_REFIN_MODE(x) FIELD_PREP(ADF4371_REFIN_MODE_MASK, x) | |
| #define ADF4371_REF_DOUB_MASK BIT(5) | |
| #define ADF4371_REF_DOUB(x) FIELD_PREP(ADF4371_REF_DOUB_MASK, x)\ | |
| /* ADF4371_REG24 */ | |
| #define ADF4371_RF_DIV_SEL_MSK GENMASK(6, 4) | |
| #define ADF4371_RF_DIV_SEL(x) FIELD_PREP(ADF4371_RF_DIV_SEL_MSK, x) | |
| /* ADF4371_REG25 */ | |
| #define ADF4371_MUTE_LD_MSK BIT(7) | |
| #define ADF4371_MUTE_LD(x) FIELD_PREP(ADF4371_MUTE_LD_MSK, x) | |
| /* ADF4371_REG32 */ | |
| #define ADF4371_TIMEOUT_MSK GENMASK(1, 0) | |
| #define ADF4371_TIMEOUT(x) FIELD_PREP(ADF4371_TIMEOUT_MSK, x) | |
| /* ADF4371_REG34 */ | |
| #define ADF4371_VCO_ALC_TOUT_MSK GENMASK(4, 0) | |
| #define ADF4371_VCO_ALC_TOUT(x) FIELD_PREP(ADF4371_VCO_ALC_TOUT_MSK, x) | |
| /* Specifications */ | |
| #define ADF4371_MIN_VCO_FREQ 4000000000ULL /* 4000 MHz */ | |
| #define ADF4371_MAX_VCO_FREQ 8000000000ULL /* 8000 MHz */ | |
| #define ADF4371_MAX_OUT_RF8_FREQ ADF4371_MAX_VCO_FREQ /* Hz */ | |
| #define ADF4371_MIN_OUT_RF8_FREQ (ADF4371_MIN_VCO_FREQ / 64) /* Hz */ | |
| #define ADF4371_MAX_OUT_RF16_FREQ (ADF4371_MAX_VCO_FREQ * 2) /* Hz */ | |
| #define ADF4371_MIN_OUT_RF16_FREQ (ADF4371_MIN_VCO_FREQ * 2) /* Hz */ | |
| #define ADF4371_MAX_OUT_RF32_FREQ (ADF4371_MAX_VCO_FREQ * 4) /* Hz */ | |
| #define ADF4371_MIN_OUT_RF32_FREQ (ADF4371_MIN_VCO_FREQ * 4) /* Hz */ | |
| #define ADF4371_MAX_FREQ_PFD 250000000UL /* Hz */ | |
| #define ADF4371_MAX_FREQ_REFIN 600000000UL /* Hz */ | |
| #define ADF4371_MAX_FREQ_REFIN_SE 500000000UL /* Hz */ | |
| #define ADF4371_MIN_CLKIN_DOUB_FREQ 10000000ULL /* Hz */ | |
| #define ADF4371_MAX_CLKIN_DOUB_FREQ 125000000ULL /* Hz */ | |
| /* MOD1 is a 24-bit primary modulus with fixed value of 2^25 */ | |
| #define ADF4371_MODULUS1 33554432ULL | |
| /* MOD2 is the programmable, 14-bit auxiliary fractional modulus */ | |
| #define ADF4371_MAX_MODULUS2 BIT(14) | |
| #define ADF4371_CHECK_RANGE(freq, range) \ | |
| ((freq > ADF4371_MAX_ ## range) || (freq < ADF4371_MIN_ ## range)) | |
| enum { | |
| ADF4371_FREQ, | |
| ADF4371_POWER_DOWN, | |
| ADF4371_CHANNEL_NAME | |
| }; | |
| enum { | |
| ADF4371_CH_RF8, | |
| ADF4371_CH_RFAUX8, | |
| ADF4371_CH_RF16, | |
| ADF4371_CH_RF32 | |
| }; | |
| enum adf4371_variant { | |
| ADF4371, | |
| ADF4372 | |
| }; | |
| struct adf4371_pwrdown { | |
| unsigned int reg; | |
| unsigned int bit; | |
| }; | |
| static const char * const adf4371_ch_names[] = { | |
| "RF8x", "RFAUX8x", "RF16x", "RF32x" | |
| }; | |
| static const struct adf4371_pwrdown adf4371_pwrdown_ch[4] = { | |
| [ADF4371_CH_RF8] = { ADF4371_REG(0x25), 2 }, | |
| [ADF4371_CH_RFAUX8] = { ADF4371_REG(0x72), 3 }, | |
| [ADF4371_CH_RF16] = { ADF4371_REG(0x25), 3 }, | |
| [ADF4371_CH_RF32] = { ADF4371_REG(0x25), 4 }, | |
| }; | |
| static const struct reg_sequence adf4371_reg_defaults[] = { | |
| { ADF4371_REG(0x0), 0x18 }, | |
| { ADF4371_REG(0x12), 0x40 }, | |
| { ADF4371_REG(0x1E), 0x48 }, | |
| { ADF4371_REG(0x20), 0x14 }, | |
| { ADF4371_REG(0x22), 0x00 }, | |
| { ADF4371_REG(0x23), 0x00 }, | |
| { ADF4371_REG(0x24), 0x80 }, | |
| { ADF4371_REG(0x25), 0x07 }, | |
| { ADF4371_REG(0x27), 0xC5 }, | |
| { ADF4371_REG(0x28), 0x83 }, | |
| { ADF4371_REG(0x2C), 0x44 }, | |
| { ADF4371_REG(0x2D), 0x11 }, | |
| { ADF4371_REG(0x2E), 0x12 }, | |
| { ADF4371_REG(0x2F), 0x94 }, | |
| { ADF4371_REG(0x32), 0x04 }, | |
| { ADF4371_REG(0x35), 0xFA }, | |
| { ADF4371_REG(0x36), 0x30 }, | |
| { ADF4371_REG(0x39), 0x07 }, | |
| { ADF4371_REG(0x3A), 0x55 }, | |
| { ADF4371_REG(0x3E), 0x0C }, | |
| { ADF4371_REG(0x3F), 0x80 }, | |
| { ADF4371_REG(0x40), 0x50 }, | |
| { ADF4371_REG(0x41), 0x28 }, | |
| { ADF4371_REG(0x47), 0xC0 }, | |
| { ADF4371_REG(0x52), 0xF4 }, | |
| { ADF4371_REG(0x70), 0x03 }, | |
| { ADF4371_REG(0x71), 0x60 }, | |
| { ADF4371_REG(0x72), 0x32 }, | |
| }; | |
| static const struct regmap_config adf4371_regmap_config = { | |
| .reg_bits = 16, | |
| .val_bits = 8, | |
| .read_flag_mask = BIT(7), | |
| }; | |
| struct adf4371_chip_info { | |
| const char *name; | |
| unsigned int num_channels; | |
| const struct iio_chan_spec *channels; | |
| }; | |
| struct adf4371_state { | |
| struct spi_device *spi; | |
| struct regmap *regmap; | |
| /* | |
| * Lock for accessing device registers. Some operations require | |
| * multiple consecutive R/W operations, during which the device | |
| * shouldn't be interrupted. The buffers are also shared across | |
| * all operations so need to be protected on stand alone reads and | |
| * writes. | |
| */ | |
| struct mutex lock; | |
| const struct adf4371_chip_info *chip_info; | |
| unsigned long clkin_freq; | |
| unsigned long fpfd; | |
| unsigned int integer; | |
| unsigned int fract1; | |
| unsigned int fract2; | |
| unsigned int mod2; | |
| unsigned int rf_div_sel; | |
| unsigned int ref_div_factor; | |
| bool ref_diff_en; | |
| u8 buf[10] __aligned(IIO_DMA_MINALIGN); | |
| }; | |
| static unsigned long long adf4371_pll_fract_n_get_rate(struct adf4371_state *st, | |
| u32 channel) | |
| { | |
| unsigned long long val, tmp; | |
| unsigned int ref_div_sel; | |
| val = (((u64)st->integer * ADF4371_MODULUS1) + st->fract1) * st->fpfd; | |
| tmp = (u64)st->fract2 * st->fpfd; | |
| do_div(tmp, st->mod2); | |
| val += tmp + ADF4371_MODULUS1 / 2; | |
| if (channel == ADF4371_CH_RF8 || channel == ADF4371_CH_RFAUX8) | |
| ref_div_sel = st->rf_div_sel; | |
| else | |
| ref_div_sel = 0; | |
| do_div(val, ADF4371_MODULUS1 * (1 << ref_div_sel)); | |
| if (channel == ADF4371_CH_RF16) | |
| val <<= 1; | |
| else if (channel == ADF4371_CH_RF32) | |
| val <<= 2; | |
| return val; | |
| } | |
| static void adf4371_pll_fract_n_compute(unsigned long long vco, | |
| unsigned long long pfd, | |
| unsigned int *integer, | |
| unsigned int *fract1, | |
| unsigned int *fract2, | |
| unsigned int *mod2) | |
| { | |
| unsigned long long tmp; | |
| u32 gcd_div; | |
| tmp = do_div(vco, pfd); | |
| tmp = tmp * ADF4371_MODULUS1; | |
| *fract2 = do_div(tmp, pfd); | |
| *integer = vco; | |
| *fract1 = tmp; | |
| *mod2 = pfd; | |
| while (*mod2 > ADF4371_MAX_MODULUS2) { | |
| *mod2 >>= 1; | |
| *fract2 >>= 1; | |
| } | |
| gcd_div = gcd(*fract2, *mod2); | |
| *mod2 /= gcd_div; | |
| *fract2 /= gcd_div; | |
| } | |
| static int adf4371_set_freq(struct adf4371_state *st, unsigned long long freq, | |
| unsigned int channel) | |
| { | |
| u32 cp_bleed; | |
| u8 int_mode = 0; | |
| int ret; | |
| switch (channel) { | |
| case ADF4371_CH_RF8: | |
| case ADF4371_CH_RFAUX8: | |
| if (ADF4371_CHECK_RANGE(freq, OUT_RF8_FREQ)) | |
| return -EINVAL; | |
| st->rf_div_sel = 0; | |
| while (freq < ADF4371_MIN_VCO_FREQ) { | |
| freq <<= 1; | |
| st->rf_div_sel++; | |
| } | |
| break; | |
| case ADF4371_CH_RF16: | |
| /* ADF4371 RF16 8000...16000 MHz */ | |
| if (ADF4371_CHECK_RANGE(freq, OUT_RF16_FREQ)) | |
| return -EINVAL; | |
| freq >>= 1; | |
| break; | |
| case ADF4371_CH_RF32: | |
| /* ADF4371 RF32 16000...32000 MHz */ | |
| if (ADF4371_CHECK_RANGE(freq, OUT_RF32_FREQ)) | |
| return -EINVAL; | |
| freq >>= 2; | |
| break; | |
| default: | |
| return -EINVAL; | |
| } | |
| adf4371_pll_fract_n_compute(freq, st->fpfd, &st->integer, &st->fract1, | |
| &st->fract2, &st->mod2); | |
| st->buf[0] = st->integer >> 8; | |
| st->buf[1] = 0x40; /* REG12 default */ | |
| st->buf[2] = 0x00; | |
| st->buf[3] = st->fract1 & 0xFF; | |
| st->buf[4] = st->fract1 >> 8; | |
| st->buf[5] = st->fract1 >> 16; | |
| st->buf[6] = ADF4371_FRAC2WORD_L(st->fract2 & 0x7F) | | |
| ADF4371_FRAC1WORD(st->fract1 >> 24); | |
| st->buf[7] = ADF4371_FRAC2WORD_H(st->fract2 >> 7); | |
| st->buf[8] = st->mod2 & 0xFF; | |
| st->buf[9] = ADF4371_MOD2WORD(st->mod2 >> 8); | |
| ret = regmap_bulk_write(st->regmap, ADF4371_REG(0x11), st->buf, 10); | |
| if (ret < 0) | |
| return ret; | |
| /* | |
| * The R counter allows the input reference frequency to be | |
| * divided down to produce the reference clock to the PFD | |
| */ | |
| ret = regmap_write(st->regmap, ADF4371_REG(0x1F), st->ref_div_factor); | |
| if (ret < 0) | |
| return ret; | |
| ret = regmap_update_bits(st->regmap, ADF4371_REG(0x24), | |
| ADF4371_RF_DIV_SEL_MSK, | |
| ADF4371_RF_DIV_SEL(st->rf_div_sel)); | |
| if (ret < 0) | |
| return ret; | |
| cp_bleed = DIV_ROUND_UP(400 * 1750, st->integer * 375); | |
| cp_bleed = clamp(cp_bleed, 1U, 255U); | |
| ret = regmap_write(st->regmap, ADF4371_REG(0x26), cp_bleed); | |
| if (ret < 0) | |
| return ret; | |
| /* | |
| * Set to 1 when in INT mode (when FRAC1 = FRAC2 = 0), | |
| * and set to 0 when in FRAC mode. | |
| */ | |
| if (st->fract1 == 0 && st->fract2 == 0) | |
| int_mode = 0x01; | |
| ret = regmap_write(st->regmap, ADF4371_REG(0x2B), int_mode); | |
| if (ret < 0) | |
| return ret; | |
| return regmap_write(st->regmap, ADF4371_REG(0x10), st->integer & 0xFF); | |
| } | |
| static ssize_t adf4371_read(struct iio_dev *indio_dev, | |
| uintptr_t private, | |
| const struct iio_chan_spec *chan, | |
| char *buf) | |
| { | |
| struct adf4371_state *st = iio_priv(indio_dev); | |
| unsigned long long val = 0; | |
| unsigned int readval, reg, bit; | |
| int ret; | |
| switch ((u32)private) { | |
| case ADF4371_FREQ: | |
| val = adf4371_pll_fract_n_get_rate(st, chan->channel); | |
| ret = regmap_read(st->regmap, ADF4371_REG(0x7C), &readval); | |
| if (ret < 0) | |
| break; | |
| if (readval == 0x00) { | |
| dev_dbg(&st->spi->dev, "PLL un-locked\n"); | |
| ret = -EBUSY; | |
| } | |
| break; | |
| case ADF4371_POWER_DOWN: | |
| reg = adf4371_pwrdown_ch[chan->channel].reg; | |
| bit = adf4371_pwrdown_ch[chan->channel].bit; | |
| ret = regmap_read(st->regmap, reg, &readval); | |
| if (ret < 0) | |
| break; | |
| val = !(readval & BIT(bit)); | |
| break; | |
| case ADF4371_CHANNEL_NAME: | |
| return sprintf(buf, "%s\n", adf4371_ch_names[chan->channel]); | |
| default: | |
| ret = -EINVAL; | |
| val = 0; | |
| break; | |
| } | |
| return ret < 0 ? ret : sprintf(buf, "%llu\n", val); | |
| } | |
| static ssize_t adf4371_write(struct iio_dev *indio_dev, | |
| uintptr_t private, | |
| const struct iio_chan_spec *chan, | |
| const char *buf, size_t len) | |
| { | |
| struct adf4371_state *st = iio_priv(indio_dev); | |
| unsigned long long freq; | |
| bool power_down; | |
| unsigned int bit, readval, reg; | |
| int ret; | |
| mutex_lock(&st->lock); | |
| switch ((u32)private) { | |
| case ADF4371_FREQ: | |
| ret = kstrtoull(buf, 10, &freq); | |
| if (ret) | |
| break; | |
| ret = adf4371_set_freq(st, freq, chan->channel); | |
| break; | |
| case ADF4371_POWER_DOWN: | |
| ret = kstrtobool(buf, &power_down); | |
| if (ret) | |
| break; | |
| reg = adf4371_pwrdown_ch[chan->channel].reg; | |
| bit = adf4371_pwrdown_ch[chan->channel].bit; | |
| ret = regmap_read(st->regmap, reg, &readval); | |
| if (ret < 0) | |
| break; | |
| readval &= ~BIT(bit); | |
| readval |= (!power_down << bit); | |
| ret = regmap_write(st->regmap, reg, readval); | |
| break; | |
| default: | |
| ret = -EINVAL; | |
| break; | |
| } | |
| mutex_unlock(&st->lock); | |
| return ret ? ret : len; | |
| } | |
| #define _ADF4371_EXT_INFO(_name, _ident) { \ | |
| .name = _name, \ | |
| .read = adf4371_read, \ | |
| .write = adf4371_write, \ | |
| .private = _ident, \ | |
| .shared = IIO_SEPARATE, \ | |
| } | |
| static const struct iio_chan_spec_ext_info adf4371_ext_info[] = { | |
| /* | |
| * Ideally we use IIO_CHAN_INFO_FREQUENCY, but there are | |
| * values > 2^32 in order to support the entire frequency range | |
| * in Hz. Using scale is a bit ugly. | |
| */ | |
| _ADF4371_EXT_INFO("frequency", ADF4371_FREQ), | |
| _ADF4371_EXT_INFO("powerdown", ADF4371_POWER_DOWN), | |
| _ADF4371_EXT_INFO("name", ADF4371_CHANNEL_NAME), | |
| { } | |
| }; | |
| #define ADF4371_CHANNEL(index) { \ | |
| .type = IIO_ALTVOLTAGE, \ | |
| .output = 1, \ | |
| .channel = index, \ | |
| .ext_info = adf4371_ext_info, \ | |
| .indexed = 1, \ | |
| } | |
| static const struct iio_chan_spec adf4371_chan[] = { | |
| ADF4371_CHANNEL(ADF4371_CH_RF8), | |
| ADF4371_CHANNEL(ADF4371_CH_RFAUX8), | |
| ADF4371_CHANNEL(ADF4371_CH_RF16), | |
| ADF4371_CHANNEL(ADF4371_CH_RF32), | |
| }; | |
| static const struct adf4371_chip_info adf4371_chip_info = { | |
| .name = "adf4371", | |
| .channels = adf4371_chan, | |
| .num_channels = 4, | |
| }; | |
| static const struct adf4371_chip_info adf4372_chip_info = { | |
| .name = "adf4372", | |
| .channels = adf4371_chan, | |
| .num_channels = 3, | |
| }; | |
| static int adf4371_reg_access(struct iio_dev *indio_dev, | |
| unsigned int reg, | |
| unsigned int writeval, | |
| unsigned int *readval) | |
| { | |
| struct adf4371_state *st = iio_priv(indio_dev); | |
| if (readval) | |
| return regmap_read(st->regmap, reg, readval); | |
| else | |
| return regmap_write(st->regmap, reg, writeval); | |
| } | |
| static const struct iio_info adf4371_info = { | |
| .debugfs_reg_access = &adf4371_reg_access, | |
| }; | |
| static int adf4371_setup(struct adf4371_state *st) | |
| { | |
| unsigned int synth_timeout = 2, timeout = 1, vco_alc_timeout = 1; | |
| unsigned int vco_band_div, tmp, ref_doubler_en = 0; | |
| int ret; | |
| /* Perform a software reset */ | |
| ret = regmap_write(st->regmap, ADF4371_REG(0x0), ADF4371_RESET_CMD); | |
| if (ret < 0) | |
| return ret; | |
| ret = regmap_multi_reg_write(st->regmap, adf4371_reg_defaults, | |
| ARRAY_SIZE(adf4371_reg_defaults)); | |
| if (ret < 0) | |
| return ret; | |
| /* Mute to Lock Detect */ | |
| if (device_property_read_bool(&st->spi->dev, "adi,mute-till-lock-en")) { | |
| ret = regmap_update_bits(st->regmap, ADF4371_REG(0x25), | |
| ADF4371_MUTE_LD_MSK, | |
| ADF4371_MUTE_LD(1)); | |
| if (ret < 0) | |
| return ret; | |
| } | |
| /* Set address in ascending order, so the bulk_write() will work */ | |
| ret = regmap_update_bits(st->regmap, ADF4371_REG(0x0), | |
| ADF4371_ADDR_ASC_MSK | ADF4371_ADDR_ASC_R_MSK, | |
| ADF4371_ADDR_ASC(1) | ADF4371_ADDR_ASC_R(1)); | |
| if (ret < 0) | |
| return ret; | |
| if ((st->ref_diff_en && st->clkin_freq > ADF4371_MAX_FREQ_REFIN) || | |
| (!st->ref_diff_en && st->clkin_freq > ADF4371_MAX_FREQ_REFIN_SE)) | |
| return -EINVAL; | |
| if (st->clkin_freq < ADF4371_MAX_CLKIN_DOUB_FREQ && | |
| st->clkin_freq > ADF4371_MIN_CLKIN_DOUB_FREQ) | |
| ref_doubler_en = 1; | |
| ret = regmap_update_bits(st->regmap, ADF4371_REG(0x22), | |
| ADF4371_REF_DOUB_MASK | | |
| ADF4371_REFIN_MODE_MASK, | |
| ADF4371_REF_DOUB(ref_doubler_en) | | |
| ADF4371_REFIN_MODE(st->ref_diff_en)); | |
| if (ret < 0) | |
| return ret; | |
| /* | |
| * Calculate and maximize PFD frequency | |
| * fPFD = REFIN × ((1 + D)/(R × (1 + T))) | |
| * Where D is the REFIN doubler bit, T is the reference divide by 2, | |
| * R is the reference division factor | |
| * TODO: it is assumed D and T equal 0. | |
| */ | |
| do { | |
| st->ref_div_factor++; | |
| st->fpfd = st->clkin_freq * (1 + ref_doubler_en) / | |
| st->ref_div_factor; | |
| } while (st->fpfd > ADF4371_MAX_FREQ_PFD); | |
| /* Calculate Timeouts */ | |
| vco_band_div = DIV_ROUND_UP(st->fpfd, 2400000U); | |
| tmp = DIV_ROUND_CLOSEST(st->fpfd, 1000000U); | |
| do { | |
| timeout++; | |
| if (timeout > 1023) { | |
| timeout = 2; | |
| synth_timeout++; | |
| } | |
| } while (synth_timeout * 1024 + timeout <= 20 * tmp); | |
| do { | |
| vco_alc_timeout++; | |
| } while (vco_alc_timeout * 1024 - timeout <= 50 * tmp); | |
| st->buf[0] = vco_band_div; | |
| st->buf[1] = timeout & 0xFF; | |
| st->buf[2] = ADF4371_TIMEOUT(timeout >> 8) | 0x04; | |
| st->buf[3] = synth_timeout; | |
| st->buf[4] = ADF4371_VCO_ALC_TOUT(vco_alc_timeout); | |
| return regmap_bulk_write(st->regmap, ADF4371_REG(0x30), st->buf, 5); | |
| } | |
| static int adf4371_probe(struct spi_device *spi) | |
| { | |
| struct iio_dev *indio_dev; | |
| struct adf4371_state *st; | |
| struct regmap *regmap; | |
| struct clk *clkin; | |
| int ret; | |
| indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); | |
| if (!indio_dev) | |
| return -ENOMEM; | |
| regmap = devm_regmap_init_spi(spi, &adf4371_regmap_config); | |
| if (IS_ERR(regmap)) | |
| return dev_err_probe(&spi->dev, PTR_ERR(regmap), | |
| "Error initializing spi regmap\n"); | |
| st = iio_priv(indio_dev); | |
| st->spi = spi; | |
| st->regmap = regmap; | |
| mutex_init(&st->lock); | |
| st->chip_info = spi_get_device_match_data(spi); | |
| if (!st->chip_info) | |
| return -ENODEV; | |
| indio_dev->name = st->chip_info->name; | |
| indio_dev->info = &adf4371_info; | |
| indio_dev->modes = INDIO_DIRECT_MODE; | |
| indio_dev->channels = st->chip_info->channels; | |
| indio_dev->num_channels = st->chip_info->num_channels; | |
| st->ref_diff_en = false; | |
| clkin = devm_clk_get_enabled(&spi->dev, "clkin"); | |
| if (IS_ERR(clkin)) { | |
| clkin = devm_clk_get_enabled(&spi->dev, "clkin-diff"); | |
| if (IS_ERR(clkin)) | |
| return dev_err_probe(&spi->dev, PTR_ERR(clkin), | |
| "Failed to get clkin/clkin-diff\n"); | |
| st->ref_diff_en = true; | |
| } | |
| st->clkin_freq = clk_get_rate(clkin); | |
| ret = adf4371_setup(st); | |
| if (ret < 0) | |
| return dev_err_probe(&spi->dev, ret, "ADF4371 setup failed\n"); | |
| return devm_iio_device_register(&spi->dev, indio_dev); | |
| } | |
| static const struct spi_device_id adf4371_id_table[] = { | |
| { .name = "adf4371", .driver_data = (kernel_ulong_t)&adf4371_chip_info }, | |
| { .name = "adf4372", .driver_data = (kernel_ulong_t)&adf4372_chip_info }, | |
| { } | |
| }; | |
| MODULE_DEVICE_TABLE(spi, adf4371_id_table); | |
| static const struct of_device_id adf4371_of_match[] = { | |
| { .compatible = "adi,adf4371", .data = &adf4371_chip_info }, | |
| { .compatible = "adi,adf4372", .data = &adf4372_chip_info}, | |
| { } | |
| }; | |
| MODULE_DEVICE_TABLE(of, adf4371_of_match); | |
| static struct spi_driver adf4371_driver = { | |
| .driver = { | |
| .name = "adf4371", | |
| .of_match_table = adf4371_of_match, | |
| }, | |
| .probe = adf4371_probe, | |
| .id_table = adf4371_id_table, | |
| }; | |
| module_spi_driver(adf4371_driver); | |
| MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>"); | |
| MODULE_DESCRIPTION("Analog Devices ADF4371 SPI PLL"); | |
| MODULE_LICENSE("GPL"); |