Stefan Popa | 7f699bd | 2019-06-04 17:58:02 +0300 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0 |
| 2 | /* |
| 3 | * Analog Devices ADF4371 SPI Wideband Synthesizer driver |
| 4 | * |
| 5 | * Copyright 2019 Analog Devices Inc. |
| 6 | */ |
| 7 | #include <linux/bitfield.h> |
| 8 | #include <linux/clk.h> |
| 9 | #include <linux/device.h> |
| 10 | #include <linux/err.h> |
| 11 | #include <linux/gcd.h> |
| 12 | #include <linux/kernel.h> |
| 13 | #include <linux/module.h> |
| 14 | #include <linux/regmap.h> |
| 15 | #include <linux/sysfs.h> |
| 16 | #include <linux/spi/spi.h> |
| 17 | |
| 18 | #include <linux/iio/iio.h> |
| 19 | |
| 20 | /* Registers address macro */ |
| 21 | #define ADF4371_REG(x) (x) |
| 22 | |
| 23 | /* ADF4371_REG0 */ |
| 24 | #define ADF4371_ADDR_ASC_MSK BIT(2) |
| 25 | #define ADF4371_ADDR_ASC(x) FIELD_PREP(ADF4371_ADDR_ASC_MSK, x) |
| 26 | #define ADF4371_ADDR_ASC_R_MSK BIT(5) |
| 27 | #define ADF4371_ADDR_ASC_R(x) FIELD_PREP(ADF4371_ADDR_ASC_R_MSK, x) |
| 28 | #define ADF4371_RESET_CMD 0x81 |
| 29 | |
| 30 | /* ADF4371_REG17 */ |
| 31 | #define ADF4371_FRAC2WORD_L_MSK GENMASK(7, 1) |
| 32 | #define ADF4371_FRAC2WORD_L(x) FIELD_PREP(ADF4371_FRAC2WORD_L_MSK, x) |
| 33 | #define ADF4371_FRAC1WORD_MSK BIT(0) |
| 34 | #define ADF4371_FRAC1WORD(x) FIELD_PREP(ADF4371_FRAC1WORD_MSK, x) |
| 35 | |
| 36 | /* ADF4371_REG18 */ |
| 37 | #define ADF4371_FRAC2WORD_H_MSK GENMASK(6, 0) |
| 38 | #define ADF4371_FRAC2WORD_H(x) FIELD_PREP(ADF4371_FRAC2WORD_H_MSK, x) |
| 39 | |
| 40 | /* ADF4371_REG1A */ |
| 41 | #define ADF4371_MOD2WORD_MSK GENMASK(5, 0) |
| 42 | #define ADF4371_MOD2WORD(x) FIELD_PREP(ADF4371_MOD2WORD_MSK, x) |
| 43 | |
| 44 | /* ADF4371_REG24 */ |
| 45 | #define ADF4371_RF_DIV_SEL_MSK GENMASK(6, 4) |
| 46 | #define ADF4371_RF_DIV_SEL(x) FIELD_PREP(ADF4371_RF_DIV_SEL_MSK, x) |
| 47 | |
Stefan Popa | def914a | 2019-06-24 18:13:56 +0300 | [diff] [blame] | 48 | /* ADF4371_REG25 */ |
| 49 | #define ADF4371_MUTE_LD_MSK BIT(7) |
| 50 | #define ADF4371_MUTE_LD(x) FIELD_PREP(ADF4371_MUTE_LD_MSK, x) |
| 51 | |
Stefan Popa | 7f699bd | 2019-06-04 17:58:02 +0300 | [diff] [blame] | 52 | /* ADF4371_REG32 */ |
| 53 | #define ADF4371_TIMEOUT_MSK GENMASK(1, 0) |
| 54 | #define ADF4371_TIMEOUT(x) FIELD_PREP(ADF4371_TIMEOUT_MSK, x) |
| 55 | |
| 56 | /* ADF4371_REG34 */ |
| 57 | #define ADF4371_VCO_ALC_TOUT_MSK GENMASK(4, 0) |
| 58 | #define ADF4371_VCO_ALC_TOUT(x) FIELD_PREP(ADF4371_VCO_ALC_TOUT_MSK, x) |
| 59 | |
| 60 | /* Specifications */ |
| 61 | #define ADF4371_MIN_VCO_FREQ 4000000000ULL /* 4000 MHz */ |
| 62 | #define ADF4371_MAX_VCO_FREQ 8000000000ULL /* 8000 MHz */ |
| 63 | #define ADF4371_MAX_OUT_RF8_FREQ ADF4371_MAX_VCO_FREQ /* Hz */ |
| 64 | #define ADF4371_MIN_OUT_RF8_FREQ (ADF4371_MIN_VCO_FREQ / 64) /* Hz */ |
| 65 | #define ADF4371_MAX_OUT_RF16_FREQ (ADF4371_MAX_VCO_FREQ * 2) /* Hz */ |
| 66 | #define ADF4371_MIN_OUT_RF16_FREQ (ADF4371_MIN_VCO_FREQ * 2) /* Hz */ |
| 67 | #define ADF4371_MAX_OUT_RF32_FREQ (ADF4371_MAX_VCO_FREQ * 4) /* Hz */ |
| 68 | #define ADF4371_MIN_OUT_RF32_FREQ (ADF4371_MIN_VCO_FREQ * 4) /* Hz */ |
| 69 | |
| 70 | #define ADF4371_MAX_FREQ_PFD 250000000UL /* Hz */ |
| 71 | #define ADF4371_MAX_FREQ_REFIN 600000000UL /* Hz */ |
| 72 | |
| 73 | /* MOD1 is a 24-bit primary modulus with fixed value of 2^25 */ |
| 74 | #define ADF4371_MODULUS1 33554432ULL |
| 75 | /* MOD2 is the programmable, 14-bit auxiliary fractional modulus */ |
| 76 | #define ADF4371_MAX_MODULUS2 BIT(14) |
| 77 | |
| 78 | #define ADF4371_CHECK_RANGE(freq, range) \ |
| 79 | ((freq > ADF4371_MAX_ ## range) || (freq < ADF4371_MIN_ ## range)) |
| 80 | |
| 81 | enum { |
| 82 | ADF4371_FREQ, |
| 83 | ADF4371_POWER_DOWN, |
| 84 | ADF4371_CHANNEL_NAME |
| 85 | }; |
| 86 | |
| 87 | enum { |
| 88 | ADF4371_CH_RF8, |
| 89 | ADF4371_CH_RFAUX8, |
| 90 | ADF4371_CH_RF16, |
| 91 | ADF4371_CH_RF32 |
| 92 | }; |
| 93 | |
Stefan Popa | 13a0af4 | 2019-06-24 18:12:12 +0300 | [diff] [blame] | 94 | enum adf4371_variant { |
| 95 | ADF4371, |
| 96 | ADF4372 |
| 97 | }; |
| 98 | |
Stefan Popa | 7f699bd | 2019-06-04 17:58:02 +0300 | [diff] [blame] | 99 | struct adf4371_pwrdown { |
| 100 | unsigned int reg; |
| 101 | unsigned int bit; |
| 102 | }; |
| 103 | |
| 104 | static const char * const adf4371_ch_names[] = { |
| 105 | "RF8x", "RFAUX8x", "RF16x", "RF32x" |
| 106 | }; |
| 107 | |
| 108 | static const struct adf4371_pwrdown adf4371_pwrdown_ch[4] = { |
| 109 | [ADF4371_CH_RF8] = { ADF4371_REG(0x25), 2 }, |
| 110 | [ADF4371_CH_RFAUX8] = { ADF4371_REG(0x72), 3 }, |
| 111 | [ADF4371_CH_RF16] = { ADF4371_REG(0x25), 3 }, |
| 112 | [ADF4371_CH_RF32] = { ADF4371_REG(0x25), 4 }, |
| 113 | }; |
| 114 | |
| 115 | static const struct reg_sequence adf4371_reg_defaults[] = { |
| 116 | { ADF4371_REG(0x0), 0x18 }, |
| 117 | { ADF4371_REG(0x12), 0x40 }, |
| 118 | { ADF4371_REG(0x1E), 0x48 }, |
| 119 | { ADF4371_REG(0x20), 0x14 }, |
| 120 | { ADF4371_REG(0x22), 0x00 }, |
| 121 | { ADF4371_REG(0x23), 0x00 }, |
| 122 | { ADF4371_REG(0x24), 0x80 }, |
| 123 | { ADF4371_REG(0x25), 0x07 }, |
| 124 | { ADF4371_REG(0x27), 0xC5 }, |
| 125 | { ADF4371_REG(0x28), 0x83 }, |
| 126 | { ADF4371_REG(0x2C), 0x44 }, |
| 127 | { ADF4371_REG(0x2D), 0x11 }, |
| 128 | { ADF4371_REG(0x2E), 0x12 }, |
| 129 | { ADF4371_REG(0x2F), 0x94 }, |
| 130 | { ADF4371_REG(0x32), 0x04 }, |
| 131 | { ADF4371_REG(0x35), 0xFA }, |
| 132 | { ADF4371_REG(0x36), 0x30 }, |
| 133 | { ADF4371_REG(0x39), 0x07 }, |
| 134 | { ADF4371_REG(0x3A), 0x55 }, |
| 135 | { ADF4371_REG(0x3E), 0x0C }, |
| 136 | { ADF4371_REG(0x3F), 0x80 }, |
| 137 | { ADF4371_REG(0x40), 0x50 }, |
| 138 | { ADF4371_REG(0x41), 0x28 }, |
| 139 | { ADF4371_REG(0x47), 0xC0 }, |
| 140 | { ADF4371_REG(0x52), 0xF4 }, |
| 141 | { ADF4371_REG(0x70), 0x03 }, |
| 142 | { ADF4371_REG(0x71), 0x60 }, |
| 143 | { ADF4371_REG(0x72), 0x32 }, |
| 144 | }; |
| 145 | |
| 146 | static const struct regmap_config adf4371_regmap_config = { |
| 147 | .reg_bits = 16, |
| 148 | .val_bits = 8, |
| 149 | .read_flag_mask = BIT(7), |
| 150 | }; |
| 151 | |
Stefan Popa | 13a0af4 | 2019-06-24 18:12:12 +0300 | [diff] [blame] | 152 | struct adf4371_chip_info { |
| 153 | unsigned int num_channels; |
| 154 | const struct iio_chan_spec *channels; |
| 155 | }; |
| 156 | |
Stefan Popa | 7f699bd | 2019-06-04 17:58:02 +0300 | [diff] [blame] | 157 | struct adf4371_state { |
| 158 | struct spi_device *spi; |
| 159 | struct regmap *regmap; |
| 160 | struct clk *clkin; |
| 161 | /* |
| 162 | * Lock for accessing device registers. Some operations require |
| 163 | * multiple consecutive R/W operations, during which the device |
| 164 | * shouldn't be interrupted. The buffers are also shared across |
| 165 | * all operations so need to be protected on stand alone reads and |
| 166 | * writes. |
| 167 | */ |
| 168 | struct mutex lock; |
Stefan Popa | 13a0af4 | 2019-06-24 18:12:12 +0300 | [diff] [blame] | 169 | const struct adf4371_chip_info *chip_info; |
Stefan Popa | 7f699bd | 2019-06-04 17:58:02 +0300 | [diff] [blame] | 170 | unsigned long clkin_freq; |
| 171 | unsigned long fpfd; |
| 172 | unsigned int integer; |
| 173 | unsigned int fract1; |
| 174 | unsigned int fract2; |
| 175 | unsigned int mod2; |
| 176 | unsigned int rf_div_sel; |
| 177 | unsigned int ref_div_factor; |
| 178 | u8 buf[10] ____cacheline_aligned; |
| 179 | }; |
| 180 | |
| 181 | static unsigned long long adf4371_pll_fract_n_get_rate(struct adf4371_state *st, |
| 182 | u32 channel) |
| 183 | { |
| 184 | unsigned long long val, tmp; |
| 185 | unsigned int ref_div_sel; |
| 186 | |
| 187 | val = (((u64)st->integer * ADF4371_MODULUS1) + st->fract1) * st->fpfd; |
| 188 | tmp = (u64)st->fract2 * st->fpfd; |
| 189 | do_div(tmp, st->mod2); |
| 190 | val += tmp + ADF4371_MODULUS1 / 2; |
| 191 | |
| 192 | if (channel == ADF4371_CH_RF8 || channel == ADF4371_CH_RFAUX8) |
| 193 | ref_div_sel = st->rf_div_sel; |
| 194 | else |
| 195 | ref_div_sel = 0; |
| 196 | |
| 197 | do_div(val, ADF4371_MODULUS1 * (1 << ref_div_sel)); |
| 198 | |
| 199 | if (channel == ADF4371_CH_RF16) |
| 200 | val <<= 1; |
| 201 | else if (channel == ADF4371_CH_RF32) |
| 202 | val <<= 2; |
| 203 | |
| 204 | return val; |
| 205 | } |
| 206 | |
| 207 | static void adf4371_pll_fract_n_compute(unsigned long long vco, |
| 208 | unsigned long long pfd, |
| 209 | unsigned int *integer, |
| 210 | unsigned int *fract1, |
| 211 | unsigned int *fract2, |
| 212 | unsigned int *mod2) |
| 213 | { |
| 214 | unsigned long long tmp; |
| 215 | u32 gcd_div; |
| 216 | |
| 217 | tmp = do_div(vco, pfd); |
| 218 | tmp = tmp * ADF4371_MODULUS1; |
| 219 | *fract2 = do_div(tmp, pfd); |
| 220 | |
| 221 | *integer = vco; |
| 222 | *fract1 = tmp; |
| 223 | |
| 224 | *mod2 = pfd; |
| 225 | |
| 226 | while (*mod2 > ADF4371_MAX_MODULUS2) { |
| 227 | *mod2 >>= 1; |
| 228 | *fract2 >>= 1; |
| 229 | } |
| 230 | |
| 231 | gcd_div = gcd(*fract2, *mod2); |
| 232 | *mod2 /= gcd_div; |
| 233 | *fract2 /= gcd_div; |
| 234 | } |
| 235 | |
| 236 | static int adf4371_set_freq(struct adf4371_state *st, unsigned long long freq, |
| 237 | unsigned int channel) |
| 238 | { |
| 239 | u32 cp_bleed; |
| 240 | u8 int_mode = 0; |
| 241 | int ret; |
| 242 | |
| 243 | switch (channel) { |
| 244 | case ADF4371_CH_RF8: |
| 245 | case ADF4371_CH_RFAUX8: |
| 246 | if (ADF4371_CHECK_RANGE(freq, OUT_RF8_FREQ)) |
| 247 | return -EINVAL; |
| 248 | |
| 249 | st->rf_div_sel = 0; |
| 250 | |
| 251 | while (freq < ADF4371_MIN_VCO_FREQ) { |
| 252 | freq <<= 1; |
| 253 | st->rf_div_sel++; |
| 254 | } |
| 255 | break; |
| 256 | case ADF4371_CH_RF16: |
| 257 | /* ADF4371 RF16 8000...16000 MHz */ |
| 258 | if (ADF4371_CHECK_RANGE(freq, OUT_RF16_FREQ)) |
| 259 | return -EINVAL; |
| 260 | |
| 261 | freq >>= 1; |
| 262 | break; |
| 263 | case ADF4371_CH_RF32: |
| 264 | /* ADF4371 RF32 16000...32000 MHz */ |
| 265 | if (ADF4371_CHECK_RANGE(freq, OUT_RF32_FREQ)) |
| 266 | return -EINVAL; |
| 267 | |
| 268 | freq >>= 2; |
| 269 | break; |
| 270 | default: |
| 271 | return -EINVAL; |
| 272 | } |
| 273 | |
| 274 | adf4371_pll_fract_n_compute(freq, st->fpfd, &st->integer, &st->fract1, |
| 275 | &st->fract2, &st->mod2); |
| 276 | st->buf[0] = st->integer >> 8; |
| 277 | st->buf[1] = 0x40; /* REG12 default */ |
| 278 | st->buf[2] = 0x00; |
Nuno Sá | 82a5008 | 2019-08-05 15:37:16 +0200 | [diff] [blame] | 279 | st->buf[3] = st->fract1 & 0xFF; |
| 280 | st->buf[4] = st->fract1 >> 8; |
| 281 | st->buf[5] = st->fract1 >> 16; |
Stefan Popa | 7f699bd | 2019-06-04 17:58:02 +0300 | [diff] [blame] | 282 | st->buf[6] = ADF4371_FRAC2WORD_L(st->fract2 & 0x7F) | |
Nuno Sá | 82a5008 | 2019-08-05 15:37:16 +0200 | [diff] [blame] | 283 | ADF4371_FRAC1WORD(st->fract1 >> 24); |
Stefan Popa | 7f699bd | 2019-06-04 17:58:02 +0300 | [diff] [blame] | 284 | st->buf[7] = ADF4371_FRAC2WORD_H(st->fract2 >> 7); |
| 285 | st->buf[8] = st->mod2 & 0xFF; |
| 286 | st->buf[9] = ADF4371_MOD2WORD(st->mod2 >> 8); |
| 287 | |
| 288 | ret = regmap_bulk_write(st->regmap, ADF4371_REG(0x11), st->buf, 10); |
| 289 | if (ret < 0) |
| 290 | return ret; |
| 291 | /* |
| 292 | * The R counter allows the input reference frequency to be |
| 293 | * divided down to produce the reference clock to the PFD |
| 294 | */ |
| 295 | ret = regmap_write(st->regmap, ADF4371_REG(0x1F), st->ref_div_factor); |
| 296 | if (ret < 0) |
| 297 | return ret; |
| 298 | |
| 299 | ret = regmap_update_bits(st->regmap, ADF4371_REG(0x24), |
| 300 | ADF4371_RF_DIV_SEL_MSK, |
| 301 | ADF4371_RF_DIV_SEL(st->rf_div_sel)); |
| 302 | if (ret < 0) |
| 303 | return ret; |
| 304 | |
| 305 | cp_bleed = DIV_ROUND_UP(400 * 1750, st->integer * 375); |
| 306 | cp_bleed = clamp(cp_bleed, 1U, 255U); |
| 307 | ret = regmap_write(st->regmap, ADF4371_REG(0x26), cp_bleed); |
| 308 | if (ret < 0) |
| 309 | return ret; |
| 310 | /* |
| 311 | * Set to 1 when in INT mode (when FRAC1 = FRAC2 = 0), |
| 312 | * and set to 0 when in FRAC mode. |
| 313 | */ |
| 314 | if (st->fract1 == 0 && st->fract2 == 0) |
| 315 | int_mode = 0x01; |
| 316 | |
| 317 | ret = regmap_write(st->regmap, ADF4371_REG(0x2B), int_mode); |
| 318 | if (ret < 0) |
| 319 | return ret; |
| 320 | |
| 321 | return regmap_write(st->regmap, ADF4371_REG(0x10), st->integer & 0xFF); |
| 322 | } |
| 323 | |
| 324 | static ssize_t adf4371_read(struct iio_dev *indio_dev, |
| 325 | uintptr_t private, |
| 326 | const struct iio_chan_spec *chan, |
| 327 | char *buf) |
| 328 | { |
| 329 | struct adf4371_state *st = iio_priv(indio_dev); |
| 330 | unsigned long long val = 0; |
| 331 | unsigned int readval, reg, bit; |
| 332 | int ret; |
| 333 | |
| 334 | switch ((u32)private) { |
| 335 | case ADF4371_FREQ: |
| 336 | val = adf4371_pll_fract_n_get_rate(st, chan->channel); |
| 337 | ret = regmap_read(st->regmap, ADF4371_REG(0x7C), &readval); |
| 338 | if (ret < 0) |
| 339 | break; |
| 340 | |
| 341 | if (readval == 0x00) { |
| 342 | dev_dbg(&st->spi->dev, "PLL un-locked\n"); |
| 343 | ret = -EBUSY; |
| 344 | } |
| 345 | break; |
| 346 | case ADF4371_POWER_DOWN: |
| 347 | reg = adf4371_pwrdown_ch[chan->channel].reg; |
| 348 | bit = adf4371_pwrdown_ch[chan->channel].bit; |
| 349 | |
| 350 | ret = regmap_read(st->regmap, reg, &readval); |
| 351 | if (ret < 0) |
| 352 | break; |
| 353 | |
| 354 | val = !(readval & BIT(bit)); |
| 355 | break; |
| 356 | case ADF4371_CHANNEL_NAME: |
| 357 | return sprintf(buf, "%s\n", adf4371_ch_names[chan->channel]); |
| 358 | default: |
| 359 | ret = -EINVAL; |
| 360 | val = 0; |
| 361 | break; |
| 362 | } |
| 363 | |
| 364 | return ret < 0 ? ret : sprintf(buf, "%llu\n", val); |
| 365 | } |
| 366 | |
| 367 | static ssize_t adf4371_write(struct iio_dev *indio_dev, |
| 368 | uintptr_t private, |
| 369 | const struct iio_chan_spec *chan, |
| 370 | const char *buf, size_t len) |
| 371 | { |
| 372 | struct adf4371_state *st = iio_priv(indio_dev); |
| 373 | unsigned long long freq; |
| 374 | bool power_down; |
| 375 | unsigned int bit, readval, reg; |
| 376 | int ret; |
| 377 | |
| 378 | mutex_lock(&st->lock); |
| 379 | switch ((u32)private) { |
| 380 | case ADF4371_FREQ: |
| 381 | ret = kstrtoull(buf, 10, &freq); |
| 382 | if (ret) |
| 383 | break; |
| 384 | |
| 385 | ret = adf4371_set_freq(st, freq, chan->channel); |
| 386 | break; |
| 387 | case ADF4371_POWER_DOWN: |
| 388 | ret = kstrtobool(buf, &power_down); |
| 389 | if (ret) |
| 390 | break; |
| 391 | |
| 392 | reg = adf4371_pwrdown_ch[chan->channel].reg; |
| 393 | bit = adf4371_pwrdown_ch[chan->channel].bit; |
| 394 | ret = regmap_read(st->regmap, reg, &readval); |
| 395 | if (ret < 0) |
| 396 | break; |
| 397 | |
| 398 | readval &= ~BIT(bit); |
| 399 | readval |= (!power_down << bit); |
| 400 | |
| 401 | ret = regmap_write(st->regmap, reg, readval); |
| 402 | break; |
| 403 | default: |
| 404 | ret = -EINVAL; |
| 405 | break; |
| 406 | } |
| 407 | mutex_unlock(&st->lock); |
| 408 | |
| 409 | return ret ? ret : len; |
| 410 | } |
| 411 | |
| 412 | #define _ADF4371_EXT_INFO(_name, _ident) { \ |
| 413 | .name = _name, \ |
| 414 | .read = adf4371_read, \ |
| 415 | .write = adf4371_write, \ |
| 416 | .private = _ident, \ |
| 417 | .shared = IIO_SEPARATE, \ |
| 418 | } |
| 419 | |
| 420 | static const struct iio_chan_spec_ext_info adf4371_ext_info[] = { |
| 421 | /* |
| 422 | * Ideally we use IIO_CHAN_INFO_FREQUENCY, but there are |
| 423 | * values > 2^32 in order to support the entire frequency range |
| 424 | * in Hz. Using scale is a bit ugly. |
| 425 | */ |
| 426 | _ADF4371_EXT_INFO("frequency", ADF4371_FREQ), |
| 427 | _ADF4371_EXT_INFO("powerdown", ADF4371_POWER_DOWN), |
| 428 | _ADF4371_EXT_INFO("name", ADF4371_CHANNEL_NAME), |
| 429 | { }, |
| 430 | }; |
| 431 | |
| 432 | #define ADF4371_CHANNEL(index) { \ |
| 433 | .type = IIO_ALTVOLTAGE, \ |
| 434 | .output = 1, \ |
| 435 | .channel = index, \ |
| 436 | .ext_info = adf4371_ext_info, \ |
| 437 | .indexed = 1, \ |
| 438 | } |
| 439 | |
| 440 | static const struct iio_chan_spec adf4371_chan[] = { |
| 441 | ADF4371_CHANNEL(ADF4371_CH_RF8), |
| 442 | ADF4371_CHANNEL(ADF4371_CH_RFAUX8), |
| 443 | ADF4371_CHANNEL(ADF4371_CH_RF16), |
| 444 | ADF4371_CHANNEL(ADF4371_CH_RF32), |
| 445 | }; |
| 446 | |
Stefan Popa | 13a0af4 | 2019-06-24 18:12:12 +0300 | [diff] [blame] | 447 | static const struct adf4371_chip_info adf4371_chip_info[] = { |
| 448 | [ADF4371] = { |
| 449 | .channels = adf4371_chan, |
| 450 | .num_channels = 4, |
| 451 | }, |
| 452 | [ADF4372] = { |
| 453 | .channels = adf4371_chan, |
| 454 | .num_channels = 3, |
| 455 | } |
| 456 | }; |
| 457 | |
Stefan Popa | 7f699bd | 2019-06-04 17:58:02 +0300 | [diff] [blame] | 458 | static int adf4371_reg_access(struct iio_dev *indio_dev, |
| 459 | unsigned int reg, |
| 460 | unsigned int writeval, |
| 461 | unsigned int *readval) |
| 462 | { |
| 463 | struct adf4371_state *st = iio_priv(indio_dev); |
| 464 | |
| 465 | if (readval) |
| 466 | return regmap_read(st->regmap, reg, readval); |
| 467 | else |
| 468 | return regmap_write(st->regmap, reg, writeval); |
| 469 | } |
| 470 | |
| 471 | static const struct iio_info adf4371_info = { |
| 472 | .debugfs_reg_access = &adf4371_reg_access, |
| 473 | }; |
| 474 | |
| 475 | static int adf4371_setup(struct adf4371_state *st) |
| 476 | { |
| 477 | unsigned int synth_timeout = 2, timeout = 1, vco_alc_timeout = 1; |
| 478 | unsigned int vco_band_div, tmp; |
| 479 | int ret; |
| 480 | |
| 481 | /* Perform a software reset */ |
| 482 | ret = regmap_write(st->regmap, ADF4371_REG(0x0), ADF4371_RESET_CMD); |
| 483 | if (ret < 0) |
| 484 | return ret; |
| 485 | |
| 486 | ret = regmap_multi_reg_write(st->regmap, adf4371_reg_defaults, |
| 487 | ARRAY_SIZE(adf4371_reg_defaults)); |
| 488 | if (ret < 0) |
| 489 | return ret; |
| 490 | |
Stefan Popa | def914a | 2019-06-24 18:13:56 +0300 | [diff] [blame] | 491 | /* Mute to Lock Detect */ |
| 492 | if (device_property_read_bool(&st->spi->dev, "adi,mute-till-lock-en")) { |
| 493 | ret = regmap_update_bits(st->regmap, ADF4371_REG(0x25), |
| 494 | ADF4371_MUTE_LD_MSK, |
| 495 | ADF4371_MUTE_LD(1)); |
| 496 | if (ret < 0) |
| 497 | return ret; |
| 498 | } |
| 499 | |
Stefan Popa | 7f699bd | 2019-06-04 17:58:02 +0300 | [diff] [blame] | 500 | /* Set address in ascending order, so the bulk_write() will work */ |
| 501 | ret = regmap_update_bits(st->regmap, ADF4371_REG(0x0), |
| 502 | ADF4371_ADDR_ASC_MSK | ADF4371_ADDR_ASC_R_MSK, |
| 503 | ADF4371_ADDR_ASC(1) | ADF4371_ADDR_ASC_R(1)); |
| 504 | if (ret < 0) |
| 505 | return ret; |
| 506 | /* |
| 507 | * Calculate and maximize PFD frequency |
| 508 | * fPFD = REFIN × ((1 + D)/(R × (1 + T))) |
| 509 | * Where D is the REFIN doubler bit, T is the reference divide by 2, |
| 510 | * R is the reference division factor |
| 511 | * TODO: it is assumed D and T equal 0. |
| 512 | */ |
| 513 | do { |
| 514 | st->ref_div_factor++; |
| 515 | st->fpfd = st->clkin_freq / st->ref_div_factor; |
| 516 | } while (st->fpfd > ADF4371_MAX_FREQ_PFD); |
| 517 | |
| 518 | /* Calculate Timeouts */ |
| 519 | vco_band_div = DIV_ROUND_UP(st->fpfd, 2400000U); |
| 520 | |
| 521 | tmp = DIV_ROUND_CLOSEST(st->fpfd, 1000000U); |
| 522 | do { |
| 523 | timeout++; |
| 524 | if (timeout > 1023) { |
| 525 | timeout = 2; |
| 526 | synth_timeout++; |
| 527 | } |
| 528 | } while (synth_timeout * 1024 + timeout <= 20 * tmp); |
| 529 | |
| 530 | do { |
| 531 | vco_alc_timeout++; |
| 532 | } while (vco_alc_timeout * 1024 - timeout <= 50 * tmp); |
| 533 | |
| 534 | st->buf[0] = vco_band_div; |
| 535 | st->buf[1] = timeout & 0xFF; |
| 536 | st->buf[2] = ADF4371_TIMEOUT(timeout >> 8) | 0x04; |
| 537 | st->buf[3] = synth_timeout; |
| 538 | st->buf[4] = ADF4371_VCO_ALC_TOUT(vco_alc_timeout); |
| 539 | |
| 540 | return regmap_bulk_write(st->regmap, ADF4371_REG(0x30), st->buf, 5); |
| 541 | } |
| 542 | |
| 543 | static void adf4371_clk_disable(void *data) |
| 544 | { |
| 545 | struct adf4371_state *st = data; |
| 546 | |
| 547 | clk_disable_unprepare(st->clkin); |
| 548 | } |
| 549 | |
| 550 | static int adf4371_probe(struct spi_device *spi) |
| 551 | { |
| 552 | const struct spi_device_id *id = spi_get_device_id(spi); |
| 553 | struct iio_dev *indio_dev; |
| 554 | struct adf4371_state *st; |
| 555 | struct regmap *regmap; |
| 556 | int ret; |
| 557 | |
| 558 | indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); |
| 559 | if (!indio_dev) |
| 560 | return -ENOMEM; |
| 561 | |
| 562 | regmap = devm_regmap_init_spi(spi, &adf4371_regmap_config); |
| 563 | if (IS_ERR(regmap)) { |
| 564 | dev_err(&spi->dev, "Error initializing spi regmap: %ld\n", |
| 565 | PTR_ERR(regmap)); |
| 566 | return PTR_ERR(regmap); |
| 567 | } |
| 568 | |
| 569 | st = iio_priv(indio_dev); |
| 570 | spi_set_drvdata(spi, indio_dev); |
| 571 | st->spi = spi; |
| 572 | st->regmap = regmap; |
| 573 | mutex_init(&st->lock); |
| 574 | |
Stefan Popa | 13a0af4 | 2019-06-24 18:12:12 +0300 | [diff] [blame] | 575 | st->chip_info = &adf4371_chip_info[id->driver_data]; |
Stefan Popa | 7f699bd | 2019-06-04 17:58:02 +0300 | [diff] [blame] | 576 | indio_dev->name = id->name; |
| 577 | indio_dev->info = &adf4371_info; |
| 578 | indio_dev->modes = INDIO_DIRECT_MODE; |
Stefan Popa | 13a0af4 | 2019-06-24 18:12:12 +0300 | [diff] [blame] | 579 | indio_dev->channels = st->chip_info->channels; |
| 580 | indio_dev->num_channels = st->chip_info->num_channels; |
Stefan Popa | 7f699bd | 2019-06-04 17:58:02 +0300 | [diff] [blame] | 581 | |
| 582 | st->clkin = devm_clk_get(&spi->dev, "clkin"); |
| 583 | if (IS_ERR(st->clkin)) |
| 584 | return PTR_ERR(st->clkin); |
| 585 | |
| 586 | ret = clk_prepare_enable(st->clkin); |
| 587 | if (ret < 0) |
| 588 | return ret; |
| 589 | |
| 590 | ret = devm_add_action_or_reset(&spi->dev, adf4371_clk_disable, st); |
| 591 | if (ret) |
| 592 | return ret; |
| 593 | |
| 594 | st->clkin_freq = clk_get_rate(st->clkin); |
| 595 | |
| 596 | ret = adf4371_setup(st); |
| 597 | if (ret < 0) { |
| 598 | dev_err(&spi->dev, "ADF4371 setup failed\n"); |
| 599 | return ret; |
| 600 | } |
| 601 | |
| 602 | return devm_iio_device_register(&spi->dev, indio_dev); |
| 603 | } |
| 604 | |
| 605 | static const struct spi_device_id adf4371_id_table[] = { |
Stefan Popa | 13a0af4 | 2019-06-24 18:12:12 +0300 | [diff] [blame] | 606 | { "adf4371", ADF4371 }, |
| 607 | { "adf4372", ADF4372 }, |
Stefan Popa | 7f699bd | 2019-06-04 17:58:02 +0300 | [diff] [blame] | 608 | {} |
| 609 | }; |
| 610 | MODULE_DEVICE_TABLE(spi, adf4371_id_table); |
| 611 | |
| 612 | static const struct of_device_id adf4371_of_match[] = { |
| 613 | { .compatible = "adi,adf4371" }, |
Stefan Popa | 13a0af4 | 2019-06-24 18:12:12 +0300 | [diff] [blame] | 614 | { .compatible = "adi,adf4372" }, |
Stefan Popa | 7f699bd | 2019-06-04 17:58:02 +0300 | [diff] [blame] | 615 | { }, |
| 616 | }; |
| 617 | MODULE_DEVICE_TABLE(of, adf4371_of_match); |
| 618 | |
| 619 | static struct spi_driver adf4371_driver = { |
| 620 | .driver = { |
| 621 | .name = "adf4371", |
| 622 | .of_match_table = adf4371_of_match, |
| 623 | }, |
| 624 | .probe = adf4371_probe, |
| 625 | .id_table = adf4371_id_table, |
| 626 | }; |
| 627 | module_spi_driver(adf4371_driver); |
| 628 | |
| 629 | MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>"); |
| 630 | MODULE_DESCRIPTION("Analog Devices ADF4371 SPI PLL"); |
| 631 | MODULE_LICENSE("GPL"); |