| // 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"); |