linux/drivers/iio/frequency/adf41513.c
Rodrigo Alencar 5809020d86 iio: frequency: adf41513: features on frequency change
Set Bleed current when PFD frequency changes (bleed enabled when in
fractional mode). Set lock detector window size, handling bias and
precision. Add phase resync support, setting clock dividers when
PFD frequency changes.

Signed-off-by: Rodrigo Alencar <rodrigo.alencar@analog.com>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
2026-06-30 00:15:52 +01:00

1247 lines
37 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// SPDX-License-Identifier: GPL-2.0-only
/*
* ADF41513 SPI PLL Frequency Synthesizer driver
*
* Copyright 2026 Analog Devices Inc.
*/
#include <linux/array_size.h>
#include <linux/bitfield.h>
#include <linux/bits.h>
#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/dev_printk.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/gpio/consumer.h>
#include <linux/kstrtox.h>
#include <linux/log2.h>
#include <linux/math64.h>
#include <linux/minmax.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/pm.h>
#include <linux/property.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
#include <linux/sysfs.h>
#include <linux/time64.h>
#include <linux/types.h>
#include <linux/units.h>
#include <linux/iio/iio.h>
/* Registers */
#define ADF41513_REG0 0
#define ADF41513_REG1 1
#define ADF41513_REG2 2
#define ADF41513_REG3 3
#define ADF41513_REG4 4
#define ADF41513_REG5 5
#define ADF41513_REG6 6
#define ADF41513_REG7 7
#define ADF41513_REG8 8
#define ADF41513_REG9 9
#define ADF41513_REG10 10
#define ADF41513_REG11 11
#define ADF41513_REG12 12
#define ADF41513_REG13 13
#define ADF41513_REG_NUM 14
#define ADF41513_SYNC_REG0 BIT(ADF41513_REG0)
#define ADF41513_SYNC_REG1 BIT(ADF41513_REG1)
#define ADF41513_SYNC_REG2 BIT(ADF41513_REG2)
#define ADF41513_SYNC_REG3 BIT(ADF41513_REG3)
#define ADF41513_SYNC_REG4 BIT(ADF41513_REG4)
#define ADF41513_SYNC_REG5 BIT(ADF41513_REG5)
#define ADF41513_SYNC_REG6 BIT(ADF41513_REG6)
#define ADF41513_SYNC_REG7 BIT(ADF41513_REG7)
#define ADF41513_SYNC_REG9 BIT(ADF41513_REG9)
#define ADF41513_SYNC_REG11 BIT(ADF41513_REG11)
#define ADF41513_SYNC_REG12 BIT(ADF41513_REG12)
#define ADF41513_SYNC_REG13 BIT(ADF41513_REG13)
#define ADF41513_SYNC_DIFF 0
#define ADF41513_SYNC_ALL GENMASK(ADF41513_REG13, ADF41513_REG0)
/* REG0 Bit Definitions */
#define ADF41513_REG0_CTRL_BITS_MSK GENMASK(3, 0)
#define ADF41513_REG0_INT_MSK GENMASK(19, 4)
#define ADF41513_REG0_VAR_MOD_MSK BIT(28)
/* REG1 Bit Definitions */
#define ADF41513_REG1_FRAC1_MSK GENMASK(28, 4)
#define ADF41513_REG1_DITHER2_MSK BIT(31)
/* REG2 Bit Definitions */
#define ADF41513_REG2_PHASE_VAL_MSK GENMASK(15, 4)
#define ADF41513_REG2_PHASE_ADJ_MSK BIT(31)
/* REG3 Bit Definitions */
#define ADF41513_REG3_FRAC2_MSK GENMASK(27, 4)
/* REG4 Bit Definitions */
#define ADF41513_REG4_MOD2_MSK GENMASK(27, 4)
/* REG5 Bit Definitions */
#define ADF41513_REG5_CLK1_DIV_MSK GENMASK(15, 4)
#define ADF41513_REG5_R_CNT_MSK GENMASK(20, 16)
#define ADF41513_REG5_REF_DOUBLER_MSK BIT(21)
#define ADF41513_REG5_RDIV2_MSK BIT(22)
#define ADF41513_REG5_PRESCALER_MSK BIT(23)
#define ADF41513_REG5_LSB_P1_MSK BIT(24)
#define ADF41513_REG5_CP_CURRENT_MSK GENMASK(28, 25)
#define ADF41513_REG5_DLD_MODES_MSK GENMASK(31, 30)
/* REG6 Bit Definitions */
#define ADF41513_REG6_COUNTER_RESET_MSK BIT(4)
#define ADF41513_REG6_CP_TRISTATE_MSK BIT(5)
#define ADF41513_REG6_POWER_DOWN_MSK BIT(6)
#define ADF41513_REG6_PD_POLARITY_MSK BIT(7)
#define ADF41513_REG6_LDP_MSK GENMASK(9, 8)
#define ADF41513_REG6_CP_TRISTATE_PD_ON_MSK BIT(16)
#define ADF41513_REG6_SD_RESET_MSK BIT(17)
#define ADF41513_REG6_LOL_ENABLE_MSK BIT(18)
#define ADF41513_REG6_ABP_MSK BIT(19)
#define ADF41513_REG6_INT_MODE_MSK BIT(20)
#define ADF41513_REG6_BLEED_ENABLE_MSK BIT(22)
#define ADF41513_REG6_BLEED_POLARITY_MSK BIT(23)
#define ADF41513_REG6_BLEED_CURRENT_MSK GENMASK(31, 24)
/* REG7 Bit Definitions */
#define ADF41513_REG7_CLK2_DIV_MSK GENMASK(17, 6)
#define ADF41513_REG7_CLK_DIV_MODE_MSK GENMASK(19, 18)
#define ADF41513_REG7_PS_BIAS_MSK GENMASK(21, 20)
#define ADF41513_REG7_N_DELAY_MSK GENMASK(23, 22)
#define ADF41513_REG7_LD_CLK_SEL_MSK BIT(26)
#define ADF41513_REG7_LD_COUNT_MSK GENMASK(29, 27)
/* REG9 Bit Definitions */
#define ADF41513_REG9_LD_BIAS_MSK GENMASK(31, 30)
/* REG11 Bit Definitions */
#define ADF41513_REG11_POWER_DOWN_SEL_MSK BIT(31)
/* REG12 Bit Definitions */
#define ADF41513_REG12_READBACK_SEL_MSK GENMASK(19, 14)
#define ADF41513_REG12_LE_SELECT_MSK BIT(20)
#define ADF41513_REG12_MASTER_RESET_MSK BIT(22)
#define ADF41513_REG12_LOGIC_LEVEL_MSK BIT(27)
#define ADF41513_REG12_MUXOUT_MSK GENMASK(31, 28)
/* MUXOUT Selection */
#define ADF41513_MUXOUT_TRISTATE 0x0
#define ADF41513_MUXOUT_DVDD 0x1
#define ADF41513_MUXOUT_DGND 0x2
#define ADF41513_MUXOUT_R_DIV 0x3
#define ADF41513_MUXOUT_N_DIV 0x4
#define ADF41513_MUXOUT_DIG_LD 0x6
#define ADF41513_MUXOUT_SDO 0x7
#define ADF41513_MUXOUT_READBACK 0x8
#define ADF41513_MUXOUT_CLK1_DIV 0xA
#define ADF41513_MUXOUT_R_DIV2 0xD
#define ADF41513_MUXOUT_N_DIV2 0xE
/* DLD Mode Selection */
#define ADF41513_DLD_TRISTATE 0x0
#define ADF41513_DLD_DIG_LD 0x1
#define ADF41513_DLD_LOW 0x2
#define ADF41513_DLD_HIGH 0x3
/* Prescaler Selection */
#define ADF41513_PRESCALER_4_5 0
#define ADF41513_PRESCALER_8_9 1
#define ADF41513_PRESCALER_AUTO 2
/* CLK Divider mode */
#define ADF41513_CLK_DIV_MODE_OFF 0
#define ADF41513_CLK_DIV_MODE_PHASE_RESYNC 2
/* Specifications */
#define ADF41510_MAX_RF_FREQ_HZ (10ULL * HZ_PER_GHZ)
#define ADF41513_MIN_RF_FREQ_HZ (1ULL * HZ_PER_GHZ)
#define ADF41513_MAX_RF_FREQ_HZ (26500ULL * HZ_PER_MHZ)
#define ADF41513_MIN_REF_FREQ_HZ (10 * HZ_PER_MHZ)
#define ADF41513_MAX_REF_FREQ_HZ (800 * HZ_PER_MHZ)
#define ADF41513_MAX_REF_FREQ_DOUBLER_HZ (225 * HZ_PER_MHZ)
#define ADF41513_MAX_PFD_FREQ_INT_N_UHZ (250ULL * MEGA * MICROHZ_PER_HZ)
#define ADF41513_MAX_PFD_FREQ_FRAC_N_UHZ (125ULL * MEGA * MICROHZ_PER_HZ)
#define ADF41513_MAX_FREQ_RESOLUTION_UHZ (100ULL * KILO * MICROHZ_PER_HZ)
#define ADF41513_MIN_INT_4_5 20
#define ADF41513_MAX_INT_4_5 511
#define ADF41513_MIN_INT_8_9 64
#define ADF41513_MAX_INT_8_9 1023
#define ADF41513_MIN_INT_FRAC_4_5 23
#define ADF41513_MIN_INT_FRAC_8_9 75
#define ADF41513_MIN_R_CNT 1
#define ADF41513_MAX_R_CNT 32
#define ADF41513_MIN_R_SET 1800
#define ADF41513_DEFAULT_R_SET 2700
#define ADF41513_MAX_R_SET 10000
#define ADF41513_MIN_CP_VOLTAGE_mV 810
#define ADF41513_DEFAULT_CP_VOLTAGE_mV 6480
#define ADF41513_MAX_CP_VOLTAGE_mV 12960
#define ADF41513_MIN_CP_CURRENT_uA 81
#define ADF41513_MAX_CP_CURRENT_uA 7200
#define ADF41513_LD_COUNT_FAST_MIN 2
#define ADF41513_LD_COUNT_FAST_LIMIT 64
#define ADF41513_LD_COUNT_MIN 64
#define ADF41513_LD_COUNT_MAX 8192
#define ADF41513_FIXED_MODULUS BIT(25)
#define ADF41513_MAX_MOD2 (BIT(24) - 1)
#define ADF41513_MAX_PHASE_VAL (BIT(12) - 1)
#define ADF41513_MAX_CLK_DIVIDER (BIT(12) - 1)
#define ADF41513_HZ_DECIMAL_SCALE 6
#define ADF41513_PS_BIAS_INIT 0x2
#define ADF41513_MAX_PHASE_MICRORAD ((2 * 314159265UL) / 100)
enum adf41513_pll_mode {
ADF41513_MODE_INVALID,
ADF41513_MODE_INTEGER_N,
ADF41513_MODE_FIXED_MODULUS,
ADF41513_MODE_VARIABLE_MODULUS,
};
struct adf41513_chip_info {
const char *name;
u64 max_rf_freq_hz;
bool has_prescaler_8_9;
};
struct adf41513_data {
u64 power_up_frequency_hz;
u64 freq_resolution_uhz;
u32 phase_resync_period_ns;
u32 charge_pump_voltage_mv;
u32 lock_detect_count;
u8 ref_div_factor;
bool ref_doubler_en;
bool ref_div2_en;
bool phase_detector_polarity;
bool logic_lvl_1v8_en;
bool le_sync_en;
};
struct adf41513_pll_settings {
enum adf41513_pll_mode mode;
/* reference path parameters */
u8 r_counter;
u8 ref_doubler;
u8 ref_div2;
u8 prescaler;
/* frequency parameters */
u64 target_frequency_uhz;
u64 actual_frequency_uhz;
u64 pfd_frequency_uhz;
/* pll parameters */
u32 frac1;
u32 frac2;
u32 mod2;
u16 int_val;
};
struct adf41513_state {
const struct adf41513_chip_info *chip_info;
struct spi_device *spi;
struct gpio_desc *lock_detect;
struct clk *ref_clk;
u32 ref_freq_hz;
/*
* 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;
/* Cached register values */
u32 regs[ADF41513_REG_NUM];
u32 regs_hw[ADF41513_REG_NUM];
struct adf41513_data data;
struct adf41513_pll_settings settings;
bool powerdown;
};
static const u16 adf41513_ld_window_x10_ns[] = {
9, 12, 16, 17, 21, 28, 29, 35, /* 0 - 7 */
43, 47, 49, 52, 70, 79, 115, /* 8 - 14 */
};
static const u8 adf41513_ldp_bias[] = {
0xC, 0xD, 0xE, 0x8, 0x9, 0x4, 0xA, 0x5, /* 0 - 7 */
0x0, 0x6, 0xB, 0x1, 0x2, 0x7, 0x3, /* 8 - 14 */
};
static const char * const adf41513_power_supplies[] = {
"avdd1", "avdd2", "avdd3", "avdd4", "avdd5", "vp",
};
static int adf41513_sync_config(struct adf41513_state *st, u16 sync_mask)
{
__be32 d32;
int ret;
/* write registers in reverse order (R13 to R0)*/
for (int i = ADF41513_REG13; i >= ADF41513_REG0; i--) {
if (st->regs_hw[i] == st->regs[i] && !(sync_mask & BIT(i)))
continue;
d32 = cpu_to_be32(st->regs[i] | i);
ret = spi_write_then_read(st->spi, &d32, sizeof(d32), NULL, 0);
if (ret < 0)
return ret;
st->regs_hw[i] = st->regs[i];
dev_dbg(&st->spi->dev, "REG%d <= 0x%08X\n", i, st->regs[i] | i);
}
return 0;
}
static u64 adf41513_pll_get_rate(struct adf41513_state *st)
{
struct adf41513_pll_settings *cfg = &st->settings;
if (cfg->mode != ADF41513_MODE_INVALID)
return cfg->actual_frequency_uhz;
/* get pll settings from regs_hw */
cfg->int_val = FIELD_GET(ADF41513_REG0_INT_MSK, st->regs_hw[ADF41513_REG0]);
cfg->frac1 = FIELD_GET(ADF41513_REG1_FRAC1_MSK, st->regs_hw[ADF41513_REG1]);
cfg->frac2 = FIELD_GET(ADF41513_REG3_FRAC2_MSK, st->regs_hw[ADF41513_REG3]);
cfg->mod2 = FIELD_GET(ADF41513_REG4_MOD2_MSK, st->regs_hw[ADF41513_REG4]);
cfg->r_counter = FIELD_GET(ADF41513_REG5_R_CNT_MSK, st->regs_hw[ADF41513_REG5]);
cfg->ref_doubler = FIELD_GET(ADF41513_REG5_REF_DOUBLER_MSK, st->regs_hw[ADF41513_REG5]);
cfg->ref_div2 = FIELD_GET(ADF41513_REG5_RDIV2_MSK, st->regs_hw[ADF41513_REG5]);
cfg->prescaler = FIELD_GET(ADF41513_REG5_PRESCALER_MSK, st->regs_hw[ADF41513_REG5]);
if (!cfg->mod2)
cfg->mod2 = 1;
if (!cfg->r_counter)
cfg->r_counter = ADF41513_MAX_R_CNT;
/* calculate pfd frequency */
cfg->pfd_frequency_uhz = (u64)st->ref_freq_hz * MICRO;
if (cfg->ref_doubler)
cfg->pfd_frequency_uhz <<= 1;
if (cfg->ref_div2)
cfg->pfd_frequency_uhz >>= 1;
cfg->pfd_frequency_uhz = div_u64(cfg->pfd_frequency_uhz, cfg->r_counter);
cfg->actual_frequency_uhz = (u64)cfg->int_val * cfg->pfd_frequency_uhz;
/* check if int mode is selected */
if (FIELD_GET(ADF41513_REG6_INT_MODE_MSK, st->regs_hw[ADF41513_REG6])) {
cfg->mode = ADF41513_MODE_INTEGER_N;
} else {
cfg->actual_frequency_uhz += mul_u64_u32_div(cfg->pfd_frequency_uhz,
cfg->frac1,
ADF41513_FIXED_MODULUS);
/* check if variable modulus is selected */
if (FIELD_GET(ADF41513_REG0_VAR_MOD_MSK, st->regs_hw[ADF41513_REG0])) {
cfg->actual_frequency_uhz +=
mul_u64_u64_div_u64(cfg->frac2,
cfg->pfd_frequency_uhz,
(u64)cfg->mod2 * ADF41513_FIXED_MODULUS);
cfg->mode = ADF41513_MODE_VARIABLE_MODULUS;
} else {
/* LSB_P1 offset */
if (!FIELD_GET(ADF41513_REG5_LSB_P1_MSK, st->regs_hw[ADF41513_REG5]))
cfg->actual_frequency_uhz +=
div_u64(cfg->pfd_frequency_uhz,
2 * ADF41513_FIXED_MODULUS);
cfg->mode = ADF41513_MODE_FIXED_MODULUS;
}
}
cfg->target_frequency_uhz = cfg->actual_frequency_uhz;
return cfg->actual_frequency_uhz;
}
static int adf41513_calc_pfd_frequency(struct adf41513_state *st,
struct adf41513_pll_settings *result,
u64 fpfd_limit_uhz)
{
result->ref_div2 = st->data.ref_div2_en;
result->ref_doubler = st->data.ref_doubler_en;
result->r_counter = st->data.ref_div_factor - 1;
do {
result->r_counter++;
/* f_PFD = REF_IN × ((1 + D)/(R × (1 + T))) */
result->pfd_frequency_uhz = (u64)st->ref_freq_hz * MICRO;
if (result->ref_doubler)
result->pfd_frequency_uhz <<= 1;
if (result->ref_div2)
result->pfd_frequency_uhz >>= 1;
result->pfd_frequency_uhz = div_u64(result->pfd_frequency_uhz,
result->r_counter);
} while (result->pfd_frequency_uhz > fpfd_limit_uhz);
if (result->r_counter > ADF41513_MAX_R_CNT) {
dev_err(&st->spi->dev, "Cannot optimize PFD frequency\n");
return -ERANGE;
}
return 0;
}
static int adf41513_calc_integer_n(struct adf41513_state *st,
struct adf41513_pll_settings *result)
{
u32 max_int = st->chip_info->has_prescaler_8_9 ?
ADF41513_MAX_INT_8_9 : ADF41513_MAX_INT_4_5;
u64 freq_error_uhz;
u32 int_val = div64_u64_rem(result->target_frequency_uhz, result->pfd_frequency_uhz,
&freq_error_uhz);
/* check if freq error is within a tolerance of 1/2 resolution */
if (freq_error_uhz > (result->pfd_frequency_uhz >> 1) && int_val < max_int) {
int_val++;
freq_error_uhz = result->pfd_frequency_uhz - freq_error_uhz;
}
if (freq_error_uhz > st->data.freq_resolution_uhz)
return -ERANGE;
/* set prescaler */
if (st->chip_info->has_prescaler_8_9 && int_val >= ADF41513_MIN_INT_8_9 &&
int_val <= ADF41513_MAX_INT_8_9)
result->prescaler = 1;
else if (int_val >= ADF41513_MIN_INT_4_5 && int_val <= ADF41513_MAX_INT_4_5)
result->prescaler = 0;
else
return -ERANGE;
result->actual_frequency_uhz = (u64)int_val * result->pfd_frequency_uhz;
result->mode = ADF41513_MODE_INTEGER_N;
result->int_val = int_val;
result->frac1 = 0;
result->frac2 = 0;
result->mod2 = 0;
return 0;
}
static int adf41513_calc_fixed_mod(struct adf41513_state *st,
struct adf41513_pll_settings *result)
{
u64 resolution_uhz = div_u64(result->pfd_frequency_uhz, ADF41513_FIXED_MODULUS);
u64 target_frequency_uhz = result->target_frequency_uhz;
u64 freq_error_uhz;
u32 int_val, frac1;
bool lsb_p1_offset = !FIELD_GET(ADF41513_REG5_LSB_P1_MSK, st->regs[ADF41513_REG5]);
/* LSB_P1 adds a frequency offset of f_pfd/2^26 */
if (lsb_p1_offset)
target_frequency_uhz -= resolution_uhz >> 1;
int_val = div64_u64_rem(target_frequency_uhz, result->pfd_frequency_uhz,
&freq_error_uhz);
if (st->chip_info->has_prescaler_8_9 && int_val >= ADF41513_MIN_INT_FRAC_8_9 &&
int_val <= ADF41513_MAX_INT_8_9)
result->prescaler = 1;
else if (int_val >= ADF41513_MIN_INT_FRAC_4_5 && int_val <= ADF41513_MAX_INT_4_5)
result->prescaler = 0;
else
return -ERANGE;
/* compute frac1 and fixed modulus error */
frac1 = mul_u64_u64_div_u64(freq_error_uhz, ADF41513_FIXED_MODULUS,
result->pfd_frequency_uhz);
freq_error_uhz -= mul_u64_u32_div(result->pfd_frequency_uhz, frac1,
ADF41513_FIXED_MODULUS);
/* check if freq error is within a tolerance of 1/2 resolution */
if (freq_error_uhz > (resolution_uhz >> 1) && frac1 < (ADF41513_FIXED_MODULUS - 1)) {
frac1++;
freq_error_uhz = freq_error_uhz < resolution_uhz ?
resolution_uhz - freq_error_uhz : 0;
}
if (freq_error_uhz > st->data.freq_resolution_uhz)
return -ERANGE;
/* integer part */
result->actual_frequency_uhz = (u64)int_val * result->pfd_frequency_uhz;
/* fractional part */
if (lsb_p1_offset)
result->actual_frequency_uhz += (resolution_uhz >> 1);
result->actual_frequency_uhz += mul_u64_u32_div(result->pfd_frequency_uhz, frac1,
ADF41513_FIXED_MODULUS);
result->mode = ADF41513_MODE_FIXED_MODULUS;
result->int_val = int_val;
result->frac1 = frac1;
result->frac2 = 0;
result->mod2 = 0;
return 0;
}
static int adf41513_calc_variable_mod(struct adf41513_state *st,
struct adf41513_pll_settings *result)
{
u64 freq_error_uhz, mod2;
u32 frac1, frac2;
u32 int_val = div64_u64_rem(result->target_frequency_uhz,
result->pfd_frequency_uhz, &freq_error_uhz);
if (st->chip_info->has_prescaler_8_9 && int_val >= ADF41513_MIN_INT_FRAC_8_9 &&
int_val <= ADF41513_MAX_INT_8_9)
result->prescaler = 1;
else if (int_val >= ADF41513_MIN_INT_FRAC_4_5 && int_val <= ADF41513_MAX_INT_4_5)
result->prescaler = 0;
else
return -ERANGE;
/* calculate required mod2 based on target resolution / 2 */
mod2 = DIV64_U64_ROUND_CLOSEST(result->pfd_frequency_uhz << 1,
st->data.freq_resolution_uhz * ADF41513_FIXED_MODULUS);
/* ensure mod2 is at least 2 for meaningful operation */
mod2 = clamp(mod2, 2, ADF41513_MAX_MOD2);
/* calculate frac1 and frac2 */
frac1 = mul_u64_u64_div_u64(freq_error_uhz, ADF41513_FIXED_MODULUS,
result->pfd_frequency_uhz);
frac2 = mul_u64_u64_div_u64(freq_error_uhz, mod2 * ADF41513_FIXED_MODULUS,
result->pfd_frequency_uhz) - mod2 * frac1;
/* integer part */
result->actual_frequency_uhz = (u64)int_val * result->pfd_frequency_uhz;
/* fractional part */
result->actual_frequency_uhz += mul_u64_u64_div_u64(mod2 * frac1 + frac2,
result->pfd_frequency_uhz,
mod2 * ADF41513_FIXED_MODULUS);
result->mode = ADF41513_MODE_VARIABLE_MODULUS;
result->int_val = int_val;
result->frac1 = frac1;
result->frac2 = frac2;
result->mod2 = mod2;
return 0;
}
static int adf41513_calc_pll_settings(struct adf41513_state *st,
struct adf41513_pll_settings *result,
u64 rf_out_uhz)
{
u64 max_rf_freq_uhz = st->chip_info->max_rf_freq_hz * MICRO;
u64 min_rf_freq_uhz = ADF41513_MIN_RF_FREQ_HZ * MICRO;
u64 pfd_freq_limit_uhz;
int ret;
if (rf_out_uhz < min_rf_freq_uhz || rf_out_uhz > max_rf_freq_uhz) {
dev_err(&st->spi->dev, "RF frequency %llu uHz out of range [%llu, %llu] uHz\n",
rf_out_uhz, min_rf_freq_uhz, max_rf_freq_uhz);
return -EINVAL;
}
result->target_frequency_uhz = rf_out_uhz;
/* try integer-N first (best phase noise performance) */
pfd_freq_limit_uhz = min(div_u64(rf_out_uhz, ADF41513_MIN_INT_4_5),
ADF41513_MAX_PFD_FREQ_INT_N_UHZ);
ret = adf41513_calc_pfd_frequency(st, result, pfd_freq_limit_uhz);
if (ret)
return ret;
if (adf41513_calc_integer_n(st, result) == 0)
return 0;
/* try fractional-N: recompute pfd frequency if necessary */
pfd_freq_limit_uhz = min(div_u64(rf_out_uhz, ADF41513_MIN_INT_FRAC_4_5),
ADF41513_MAX_PFD_FREQ_FRAC_N_UHZ);
if (pfd_freq_limit_uhz < result->pfd_frequency_uhz) {
ret = adf41513_calc_pfd_frequency(st, result, pfd_freq_limit_uhz);
if (ret)
return ret;
}
/* fixed-modulus attempt */
if (adf41513_calc_fixed_mod(st, result) == 0)
return 0;
/* variable-modulus attempt */
ret = adf41513_calc_variable_mod(st, result);
if (ret) {
dev_err(&st->spi->dev,
"no valid PLL configuration found for %llu uHz\n",
rf_out_uhz);
return ret;
}
return 0;
}
static void adf41513_set_bleed_val(struct adf41513_state *st)
{
u32 bleed_value, cp_index;
if (!(st->regs[ADF41513_REG6] & ADF41513_REG6_BLEED_ENABLE_MSK))
return;
if (st->data.phase_detector_polarity)
bleed_value = 90;
else
bleed_value = 144;
cp_index = 1 + FIELD_GET(ADF41513_REG5_CP_CURRENT_MSK,
st->regs[ADF41513_REG5]);
bleed_value = div64_u64(st->settings.pfd_frequency_uhz * cp_index * bleed_value,
1600ULL * MEGA * MICROHZ_PER_HZ);
FIELD_MODIFY(ADF41513_REG6_BLEED_CURRENT_MSK, &st->regs[ADF41513_REG6],
bleed_value);
}
static void adf41513_set_ld_window(struct adf41513_state *st)
{
/*
* The ideal lock detector window size is halfway between the max
* window, set by the phase comparison period t_PFD = (1 / f_PFD),
* and the minimum is set by (I_BLEED/I_CP) × t_PFD
*/
u16 ld_window_10x_ns = div64_u64(10ULL * NSEC_PER_SEC * MICROHZ_PER_HZ,
st->settings.pfd_frequency_uhz << 1);
u8 ld_idx, ldp, ld_bias;
if (st->settings.mode != ADF41513_MODE_INTEGER_N) {
/* account for bleed current (deduced from eq.6 and eq.7) */
if (st->data.phase_detector_polarity)
ld_window_10x_ns += 4;
else
ld_window_10x_ns += 6;
}
ld_idx = find_closest(ld_window_10x_ns, adf41513_ld_window_x10_ns,
ARRAY_SIZE(adf41513_ld_window_x10_ns));
ldp = (adf41513_ldp_bias[ld_idx] >> 2) & 0x3;
ld_bias = adf41513_ldp_bias[ld_idx] & 0x3;
FIELD_MODIFY(ADF41513_REG6_LDP_MSK, &st->regs[ADF41513_REG6], ldp);
FIELD_MODIFY(ADF41513_REG9_LD_BIAS_MSK, &st->regs[ADF41513_REG9], ld_bias);
}
static void adf41513_set_phase_resync(struct adf41513_state *st)
{
u32 total_div, clk1_div, clk2_div;
if (!st->data.phase_resync_period_ns)
return;
/* assuming both clock dividers hold similar values */
total_div = mul_u64_u64_div_u64(st->settings.pfd_frequency_uhz,
st->data.phase_resync_period_ns,
1ULL * MICROHZ_PER_HZ * NSEC_PER_SEC);
clk1_div = clamp(int_sqrt(total_div), 1,
ADF41513_MAX_CLK_DIVIDER);
clk2_div = clamp(DIV_ROUND_CLOSEST(total_div, clk1_div), 1,
ADF41513_MAX_CLK_DIVIDER);
FIELD_MODIFY(ADF41513_REG5_CLK1_DIV_MSK, &st->regs[ADF41513_REG5],
clk1_div);
FIELD_MODIFY(ADF41513_REG7_CLK2_DIV_MSK, &st->regs[ADF41513_REG7],
clk2_div);
/* enable phase resync */
FIELD_MODIFY(ADF41513_REG7_CLK_DIV_MODE_MSK, &st->regs[ADF41513_REG7],
ADF41513_CLK_DIV_MODE_PHASE_RESYNC);
}
static int adf41513_set_frequency(struct adf41513_state *st, u64 freq_uhz, u16 sync_mask)
{
struct adf41513_pll_settings result;
bool pfd_change = false;
bool mode_change = false;
int ret;
ret = adf41513_calc_pll_settings(st, &result, freq_uhz);
if (ret < 0)
return ret;
/* apply computed results to pll settings */
pfd_change = st->settings.pfd_frequency_uhz != result.pfd_frequency_uhz;
mode_change = st->settings.mode != result.mode;
st->settings = result;
dev_dbg(&st->spi->dev,
"%s mode: int=%u, frac1=%u, frac2=%u, mod2=%u, fpdf=%llu Hz, prescaler=%s\n",
(result.mode == ADF41513_MODE_INTEGER_N) ? "integer-n" :
(result.mode == ADF41513_MODE_FIXED_MODULUS) ? "fixed-modulus" : "variable-modulus",
result.int_val, result.frac1, result.frac2, result.mod2,
div64_u64(result.pfd_frequency_uhz, MICRO),
result.prescaler ? "8/9" : "4/5");
st->regs[ADF41513_REG0] = FIELD_PREP(ADF41513_REG0_INT_MSK,
st->settings.int_val);
if (st->settings.mode == ADF41513_MODE_VARIABLE_MODULUS)
st->regs[ADF41513_REG0] |= ADF41513_REG0_VAR_MOD_MSK;
st->regs[ADF41513_REG1] = FIELD_PREP(ADF41513_REG1_FRAC1_MSK,
st->settings.frac1);
if (st->settings.mode != ADF41513_MODE_INTEGER_N)
st->regs[ADF41513_REG1] |= ADF41513_REG1_DITHER2_MSK;
st->regs[ADF41513_REG3] = FIELD_PREP(ADF41513_REG3_FRAC2_MSK,
st->settings.frac2);
FIELD_MODIFY(ADF41513_REG4_MOD2_MSK, &st->regs[ADF41513_REG4],
st->settings.mod2);
FIELD_MODIFY(ADF41513_REG5_R_CNT_MSK, &st->regs[ADF41513_REG5],
st->settings.r_counter % ADF41513_MAX_R_CNT);
FIELD_MODIFY(ADF41513_REG5_REF_DOUBLER_MSK, &st->regs[ADF41513_REG5],
st->settings.ref_doubler);
FIELD_MODIFY(ADF41513_REG5_RDIV2_MSK, &st->regs[ADF41513_REG5],
st->settings.ref_div2);
FIELD_MODIFY(ADF41513_REG5_PRESCALER_MSK, &st->regs[ADF41513_REG5],
st->settings.prescaler);
if (st->settings.mode == ADF41513_MODE_INTEGER_N) {
st->regs[ADF41513_REG6] |= ADF41513_REG6_INT_MODE_MSK;
st->regs[ADF41513_REG6] &= ~ADF41513_REG6_BLEED_ENABLE_MSK;
} else {
st->regs[ADF41513_REG6] &= ~ADF41513_REG6_INT_MODE_MSK;
st->regs[ADF41513_REG6] |= ADF41513_REG6_BLEED_ENABLE_MSK;
}
if (pfd_change)
adf41513_set_phase_resync(st);
if (pfd_change || mode_change) {
adf41513_set_bleed_val(st);
adf41513_set_ld_window(st);
}
return adf41513_sync_config(st, sync_mask | ADF41513_SYNC_REG0);
}
static int adf41513_suspend(struct adf41513_state *st)
{
st->regs[ADF41513_REG6] |= FIELD_PREP(ADF41513_REG6_POWER_DOWN_MSK, 1);
st->regs[ADF41513_REG12] &= ~ADF41513_REG12_LE_SELECT_MSK;
return adf41513_sync_config(st, ADF41513_SYNC_DIFF);
}
static int adf41513_resume(struct adf41513_state *st)
{
int ret;
st->regs[ADF41513_REG6] &= ~ADF41513_REG6_POWER_DOWN_MSK;
st->regs[ADF41513_REG12] &= ~ADF41513_REG12_LE_SELECT_MSK;
ret = adf41513_sync_config(st, ADF41513_SYNC_ALL);
if (ret)
return ret;
if (st->data.le_sync_en) {
st->regs[ADF41513_REG12] |= ADF41513_REG12_LE_SELECT_MSK;
ret = adf41513_sync_config(st, ADF41513_SYNC_DIFF);
if (ret)
return ret;
}
return 0;
}
static ssize_t adf41513_read_resolution(struct iio_dev *indio_dev,
uintptr_t private,
const struct iio_chan_spec *chan,
char *buf)
{
struct adf41513_state *st = iio_priv(indio_dev);
int vals[2];
guard(mutex)(&st->lock);
iio_val_s64_decompose(st->data.freq_resolution_uhz, &vals[0], &vals[1]);
return iio_format_value(buf, IIO_VAL_DECIMAL64_MICRO, ARRAY_SIZE(vals), vals);
}
static ssize_t adf41513_read_powerdown(struct iio_dev *indio_dev,
uintptr_t private,
const struct iio_chan_spec *chan,
char *buf)
{
struct adf41513_state *st = iio_priv(indio_dev);
u32 val;
guard(mutex)(&st->lock);
val = FIELD_GET(ADF41513_REG6_POWER_DOWN_MSK, st->regs_hw[ADF41513_REG6]);
return sysfs_emit(buf, "%u\n", val);
}
static ssize_t adf41513_write_resolution(struct iio_dev *indio_dev,
uintptr_t private,
const struct iio_chan_spec *chan,
const char *buf, size_t len)
{
struct adf41513_state *st = iio_priv(indio_dev);
u64 freq_uhz;
int ret;
ret = kstrtoudec64(buf, ADF41513_HZ_DECIMAL_SCALE, &freq_uhz);
if (ret)
return ret;
if (freq_uhz == 0 || freq_uhz > ADF41513_MAX_FREQ_RESOLUTION_UHZ)
return -EINVAL;
guard(mutex)(&st->lock);
st->data.freq_resolution_uhz = freq_uhz;
return len;
}
static ssize_t adf41513_write_powerdown(struct iio_dev *indio_dev,
uintptr_t private,
const struct iio_chan_spec *chan,
const char *buf, size_t len)
{
struct adf41513_state *st = iio_priv(indio_dev);
bool val;
int ret;
ret = kstrtobool(buf, &val);
if (ret)
return ret;
guard(mutex)(&st->lock);
if (val)
ret = adf41513_suspend(st);
else
ret = adf41513_resume(st);
if (ret)
return ret;
st->powerdown = val;
return len;
}
static const struct iio_chan_spec_ext_info adf41513_ext_info[] = {
{
.name = "frequency_resolution",
.read = adf41513_read_resolution,
.write = adf41513_write_resolution,
.shared = IIO_SEPARATE,
},
{
.name = "powerdown",
.read = adf41513_read_powerdown,
.write = adf41513_write_powerdown,
.shared = IIO_SEPARATE,
},
{ }
};
static const struct iio_chan_spec adf41513_chan = {
.type = IIO_ALTVOLTAGE,
.indexed = 1,
.output = 1,
.channel = 0,
.info_mask_separate = BIT(IIO_CHAN_INFO_FREQUENCY) |
BIT(IIO_CHAN_INFO_PHASE),
.ext_info = adf41513_ext_info,
};
static int adf41513_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2, long info)
{
struct adf41513_state *st = iio_priv(indio_dev);
u64 tmp64;
guard(mutex)(&st->lock);
switch (info) {
case IIO_CHAN_INFO_FREQUENCY:
if (st->lock_detect &&
!gpiod_get_value_cansleep(st->lock_detect)) {
dev_dbg(&st->spi->dev, "PLL un-locked\n");
return -EBUSY;
}
tmp64 = adf41513_pll_get_rate(st);
iio_val_s64_decompose(tmp64, val, val2);
return IIO_VAL_DECIMAL64_MICRO;
case IIO_CHAN_INFO_PHASE:
tmp64 = FIELD_GET(ADF41513_REG2_PHASE_VAL_MSK,
st->regs_hw[ADF41513_REG2]);
tmp64 = (tmp64 * ADF41513_MAX_PHASE_MICRORAD) >> 12;
iio_val_s64_decompose(tmp64, val, val2);
return IIO_VAL_DECIMAL64_MICRO;
default:
return -EINVAL;
}
}
static int adf41513_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long info)
{
struct adf41513_state *st = iio_priv(indio_dev);
u64 tmp64 = iio_val_s64_compose(val, val2);
u16 phase_val;
int ret;
guard(mutex)(&st->lock);
switch (info) {
case IIO_CHAN_INFO_FREQUENCY:
return adf41513_set_frequency(st, tmp64, ADF41513_SYNC_DIFF);
case IIO_CHAN_INFO_PHASE:
if (tmp64 >= ADF41513_MAX_PHASE_MICRORAD)
return -EINVAL;
phase_val = DIV_U64_ROUND_CLOSEST(tmp64 << 12,
ADF41513_MAX_PHASE_MICRORAD);
phase_val = min(phase_val, ADF41513_MAX_PHASE_VAL);
st->regs[ADF41513_REG2] |= ADF41513_REG2_PHASE_ADJ_MSK;
FIELD_MODIFY(ADF41513_REG2_PHASE_VAL_MSK,
&st->regs[ADF41513_REG2], phase_val);
ret = adf41513_sync_config(st, ADF41513_SYNC_REG0);
/* clear phase adjust for the next sync */
st->regs[ADF41513_REG2] &= ~ADF41513_REG2_PHASE_ADJ_MSK;
return ret;
default:
return -EINVAL;
}
}
static int adf41513_write_raw_get_fmt(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
long mask)
{
switch (mask) {
case IIO_CHAN_INFO_FREQUENCY:
case IIO_CHAN_INFO_PHASE:
return IIO_VAL_DECIMAL64_MICRO;
default:
return -EINVAL;
}
}
static int adf41513_reg_access(struct iio_dev *indio_dev, unsigned int reg,
unsigned int writeval, unsigned int *readval)
{
struct adf41513_state *st = iio_priv(indio_dev);
if (reg > ADF41513_REG13)
return -EINVAL;
guard(mutex)(&st->lock);
if (!readval) {
if (reg <= ADF41513_REG6)
st->settings.mode = ADF41513_MODE_INVALID;
st->regs[reg] = writeval & ~0xF; /* Clear control bits */
return adf41513_sync_config(st, BIT(reg));
}
*readval = st->regs_hw[reg];
return 0;
}
static const struct iio_info adf41513_info = {
.read_raw = adf41513_read_raw,
.write_raw = adf41513_write_raw,
.write_raw_get_fmt = adf41513_write_raw_get_fmt,
.debugfs_reg_access = &adf41513_reg_access,
};
static int adf41513_parse_fw(struct adf41513_state *st)
{
struct device *dev = &st->spi->dev;
u32 tmp, cp_resistance, cp_current;
int ret;
tmp = ADF41510_MAX_RF_FREQ_HZ / MEGA;
device_property_read_u32(dev, "adi,power-up-frequency-mhz", &tmp);
st->data.power_up_frequency_hz = (u64)tmp * MEGA;
if (st->data.power_up_frequency_hz < ADF41513_MIN_RF_FREQ_HZ ||
st->data.power_up_frequency_hz > st->chip_info->max_rf_freq_hz)
return dev_err_probe(dev, -ERANGE,
"power-up frequency %llu Hz out of range\n",
st->data.power_up_frequency_hz);
tmp = ADF41513_MIN_R_CNT;
device_property_read_u32(dev, "adi,reference-div-factor", &tmp);
if (tmp < ADF41513_MIN_R_CNT || tmp > ADF41513_MAX_R_CNT)
return dev_err_probe(dev, -ERANGE,
"invalid reference div factor %u\n", tmp);
st->data.ref_div_factor = tmp;
st->data.ref_div2_en = device_property_read_bool(dev, "adi,reference-div2-enable");
st->data.ref_doubler_en = device_property_read_bool(dev, "adi,reference-doubler-enable");
if (st->data.ref_doubler_en &&
st->ref_freq_hz > ADF41513_MAX_REF_FREQ_DOUBLER_HZ) {
return dev_err_probe(dev, -ERANGE,
"Ref frequency not supported with doubler enabled\n");
}
cp_resistance = ADF41513_DEFAULT_R_SET;
device_property_read_u32(dev, "adi,charge-pump-resistor-ohms", &cp_resistance);
if (cp_resistance < ADF41513_MIN_R_SET || cp_resistance > ADF41513_MAX_R_SET)
return dev_err_probe(dev, -ERANGE, "R_SET %u Ohms out of range\n", cp_resistance);
st->data.charge_pump_voltage_mv = ADF41513_DEFAULT_CP_VOLTAGE_mV;
ret = device_property_read_u32(dev, "adi,charge-pump-current-microamp", &cp_current);
if (!ret) {
if (cp_current < ADF41513_MIN_CP_CURRENT_uA ||
cp_current > ADF41513_MAX_CP_CURRENT_uA)
return dev_err_probe(dev, -ERANGE,
"I_CP %u uA out of range\n", cp_current);
tmp = DIV_ROUND_CLOSEST(cp_current * cp_resistance, MILLI);
if (tmp < ADF41513_MIN_CP_VOLTAGE_mV || tmp > ADF41513_MAX_CP_VOLTAGE_mV)
return dev_err_probe(dev, -ERANGE, "I_CP %u uA (%u Ohms) out of range\n",
cp_current, cp_resistance);
st->data.charge_pump_voltage_mv = tmp;
}
st->data.phase_detector_polarity =
device_property_read_bool(dev, "adi,phase-detector-polarity-positive-enable");
st->data.phase_resync_period_ns = 0;
ret = device_property_read_u32(dev, "adi,phase-resync-period-ns", &tmp);
if (!ret)
st->data.phase_resync_period_ns = tmp;
st->data.logic_lvl_1v8_en = device_property_read_bool(dev, "adi,logic-level-1v8-enable");
tmp = ADF41513_LD_COUNT_MIN;
device_property_read_u32(dev, "adi,lock-detector-count", &tmp);
if (tmp < ADF41513_LD_COUNT_FAST_MIN || tmp > ADF41513_LD_COUNT_MAX ||
!is_power_of_2(tmp))
return dev_err_probe(dev, -ERANGE,
"invalid lock detect count: %u\n", tmp);
st->data.lock_detect_count = tmp;
/* load enable sync */
st->data.le_sync_en = device_property_read_bool(dev, "adi,le-sync-enable");
st->data.freq_resolution_uhz = MICROHZ_PER_HZ;
return 0;
}
static void adf41513_chip_disable(void *data)
{
gpiod_set_value_cansleep(data, 0);
}
static void adf41513_close(void *data)
{
adf41513_suspend(data);
}
static int adf41513_setup(struct device *dev, struct adf41513_state *st)
{
u32 tmp;
int ret;
memset(st->regs_hw, 0xFF, sizeof(st->regs_hw));
/* assuming DLD pin is used for lock detection */
st->regs[ADF41513_REG5] = FIELD_PREP(ADF41513_REG5_DLD_MODES_MSK,
ADF41513_DLD_DIG_LD);
tmp = DIV_ROUND_CLOSEST(st->data.charge_pump_voltage_mv, ADF41513_MIN_CP_VOLTAGE_mV);
st->regs[ADF41513_REG5] |= FIELD_PREP(ADF41513_REG5_CP_CURRENT_MSK, tmp - 1);
st->regs[ADF41513_REG6] = ADF41513_REG6_ABP_MSK |
ADF41513_REG6_LOL_ENABLE_MSK |
ADF41513_REG6_SD_RESET_MSK;
if (st->data.phase_detector_polarity)
st->regs[ADF41513_REG6] |= ADF41513_REG6_PD_POLARITY_MSK;
st->regs[ADF41513_REG7] = FIELD_PREP(ADF41513_REG7_PS_BIAS_MSK,
ADF41513_PS_BIAS_INIT);
tmp = ilog2(st->data.lock_detect_count);
if (st->data.lock_detect_count < ADF41513_LD_COUNT_FAST_LIMIT) {
tmp -= const_ilog2(ADF41513_LD_COUNT_FAST_MIN);
st->regs[ADF41513_REG7] |= ADF41513_REG7_LD_CLK_SEL_MSK;
} else {
tmp -= const_ilog2(ADF41513_LD_COUNT_MIN);
}
st->regs[ADF41513_REG7] |= FIELD_PREP(ADF41513_REG7_LD_COUNT_MSK, tmp);
st->regs[ADF41513_REG11] = ADF41513_REG11_POWER_DOWN_SEL_MSK;
st->regs[ADF41513_REG12] = FIELD_PREP(ADF41513_REG12_LOGIC_LEVEL_MSK,
st->data.logic_lvl_1v8_en ? 0 : 1);
/* perform initialization sequence with power-up frequency */
ret = adf41513_set_frequency(st, st->data.power_up_frequency_hz * MICRO,
ADF41513_SYNC_ALL);
if (ret)
return ret;
ret = devm_add_action_or_reset(dev, adf41513_close, st);
if (ret)
return ret;
if (st->data.le_sync_en) {
st->regs[ADF41513_REG12] |= ADF41513_REG12_LE_SELECT_MSK;
ret = adf41513_sync_config(st, ADF41513_SYNC_DIFF);
if (ret)
return ret;
}
return 0;
}
static int adf41513_pm_suspend(struct device *dev)
{
struct adf41513_state *st = dev_get_drvdata(dev);
guard(mutex)(&st->lock);
return adf41513_suspend(st);
}
static int adf41513_pm_resume(struct device *dev)
{
struct adf41513_state *st = dev_get_drvdata(dev);
guard(mutex)(&st->lock);
if (st->powerdown)
return 0; /* nothing to do */
return adf41513_resume(st);
}
static const struct adf41513_chip_info adf41510_chip_info = {
.name = "adf41510",
.max_rf_freq_hz = ADF41510_MAX_RF_FREQ_HZ,
.has_prescaler_8_9 = false,
};
static const struct adf41513_chip_info adf41513_chip_info = {
.name = "adf41513",
.max_rf_freq_hz = ADF41513_MAX_RF_FREQ_HZ,
.has_prescaler_8_9 = true,
};
static int adf41513_probe(struct spi_device *spi)
{
struct device *dev = &spi->dev;
struct gpio_desc *chip_enable;
struct iio_dev *indio_dev;
struct adf41513_state *st;
int ret;
indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
st = iio_priv(indio_dev);
st->spi = spi;
st->chip_info = spi_get_device_match_data(spi);
if (!st->chip_info)
return -EINVAL;
spi_set_drvdata(spi, st);
st->ref_clk = devm_clk_get_enabled(dev, NULL);
if (IS_ERR(st->ref_clk))
return PTR_ERR(st->ref_clk);
st->ref_freq_hz = clk_get_rate(st->ref_clk);
if (st->ref_freq_hz < ADF41513_MIN_REF_FREQ_HZ ||
st->ref_freq_hz > ADF41513_MAX_REF_FREQ_HZ)
return dev_err_probe(dev, -ERANGE,
"reference frequency %u Hz out of range\n",
st->ref_freq_hz);
ret = adf41513_parse_fw(st);
if (ret)
return ret;
ret = devm_regulator_bulk_get_enable(dev,
ARRAY_SIZE(adf41513_power_supplies),
adf41513_power_supplies);
if (ret)
return dev_err_probe(dev, ret,
"failed to get and enable regulators\n");
st->lock_detect = devm_gpiod_get_optional(dev, "lock-detect", GPIOD_IN);
if (IS_ERR(st->lock_detect))
return dev_err_probe(dev, PTR_ERR(st->lock_detect),
"fail to request lock detect GPIO\n");
chip_enable = devm_gpiod_get_optional(dev, "enable", GPIOD_OUT_HIGH);
if (IS_ERR(chip_enable))
return dev_err_probe(dev, PTR_ERR(chip_enable),
"fail to request chip enable GPIO\n");
ret = devm_add_action_or_reset(dev, adf41513_chip_disable, chip_enable);
if (ret)
return dev_err_probe(dev, ret, "Failed to add disable action\n");
ret = devm_mutex_init(dev, &st->lock);
if (ret)
return ret;
indio_dev->name = st->chip_info->name;
indio_dev->info = &adf41513_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = &adf41513_chan;
indio_dev->num_channels = 1;
ret = adf41513_setup(dev, st);
if (ret < 0)
return dev_err_probe(dev, ret, "failed to setup device\n");
return devm_iio_device_register(dev, indio_dev);
}
static const struct spi_device_id adf41513_id[] = {
{ .name = "adf41510", .driver_data = (kernel_ulong_t)&adf41510_chip_info },
{ .name = "adf41513", .driver_data = (kernel_ulong_t)&adf41513_chip_info },
{ }
};
MODULE_DEVICE_TABLE(spi, adf41513_id);
static const struct of_device_id adf41513_of_match[] = {
{ .compatible = "adi,adf41510", .data = &adf41510_chip_info },
{ .compatible = "adi,adf41513", .data = &adf41513_chip_info },
{ }
};
MODULE_DEVICE_TABLE(of, adf41513_of_match);
static DEFINE_SIMPLE_DEV_PM_OPS(adf41513_pm_ops, adf41513_pm_suspend, adf41513_pm_resume);
static struct spi_driver adf41513_driver = {
.driver = {
.name = "adf41513",
.pm = pm_ptr(&adf41513_pm_ops),
.of_match_table = adf41513_of_match,
},
.probe = adf41513_probe,
.id_table = adf41513_id,
};
module_spi_driver(adf41513_driver);
MODULE_AUTHOR("Rodrigo Alencar <rodrigo.alencar@analog.com>");
MODULE_DESCRIPTION("Analog Devices ADF41513 PLL Frequency Synthesizer");
MODULE_LICENSE("GPL");