Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

iio:filter:admv8818: add support for ADMV8818

The ADMV8818-EP is a fully monolithic microwave integrated
circuit (MMIC) that features a digitally selectable frequency of
operation. The device features four independently controlled high-
pass filters (HPFs) and four independently controlled low-pass
filters (LPFs) that span the 2 GHz to 18 GHz frequency range.

Datasheet:
https://www.analog.com/media/en/technical-documentation/data-sheets/admv8818-ep.pdf

Signed-off-by: Antoniu Miclaus <antoniu.miclaus@analog.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>

authored by

Antoniu Miclaus and committed by
Jonathan Cameron
f34fe888 35c35b0c

+676
+10
drivers/iio/filter/Kconfig
··· 5 5 6 6 menu "Filters" 7 7 8 + config ADMV8818 9 + tristate "Analog Devices ADMV8818 High-Pass and Low-Pass Filter" 10 + depends on SPI && COMMON_CLK && 64BIT 11 + help 12 + Say yes here to build support for Analog Devices ADMV8818 13 + 2 GHz to 18 GHz, Digitally Tunable, High-Pass and Low-Pass Filter. 14 + 15 + To compile this driver as a module, choose M here: the 16 + modiule will be called admv8818. 17 + 8 18 endmenu
+1
drivers/iio/filter/Makefile
··· 4 4 # 5 5 6 6 # When adding new entries keep the list in alphabetical order 7 + obj-$(CONFIG_ADMV8818) += admv8818.o
+665
drivers/iio/filter/admv8818.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * ADMV8818 driver 4 + * 5 + * Copyright 2021 Analog Devices Inc. 6 + */ 7 + 8 + #include <linux/bitfield.h> 9 + #include <linux/bits.h> 10 + #include <linux/clk.h> 11 + #include <linux/device.h> 12 + #include <linux/iio/iio.h> 13 + #include <linux/module.h> 14 + #include <linux/mod_devicetable.h> 15 + #include <linux/mutex.h> 16 + #include <linux/notifier.h> 17 + #include <linux/regmap.h> 18 + #include <linux/spi/spi.h> 19 + #include <linux/units.h> 20 + 21 + /* ADMV8818 Register Map */ 22 + #define ADMV8818_REG_SPI_CONFIG_A 0x0 23 + #define ADMV8818_REG_SPI_CONFIG_B 0x1 24 + #define ADMV8818_REG_CHIPTYPE 0x3 25 + #define ADMV8818_REG_PRODUCT_ID_L 0x4 26 + #define ADMV8818_REG_PRODUCT_ID_H 0x5 27 + #define ADMV8818_REG_FAST_LATCH_POINTER 0x10 28 + #define ADMV8818_REG_FAST_LATCH_STOP 0x11 29 + #define ADMV8818_REG_FAST_LATCH_START 0x12 30 + #define ADMV8818_REG_FAST_LATCH_DIRECTION 0x13 31 + #define ADMV8818_REG_FAST_LATCH_STATE 0x14 32 + #define ADMV8818_REG_WR0_SW 0x20 33 + #define ADMV8818_REG_WR0_FILTER 0x21 34 + #define ADMV8818_REG_WR1_SW 0x22 35 + #define ADMV8818_REG_WR1_FILTER 0x23 36 + #define ADMV8818_REG_WR2_SW 0x24 37 + #define ADMV8818_REG_WR2_FILTER 0x25 38 + #define ADMV8818_REG_WR3_SW 0x26 39 + #define ADMV8818_REG_WR3_FILTER 0x27 40 + #define ADMV8818_REG_WR4_SW 0x28 41 + #define ADMV8818_REG_WR4_FILTER 0x29 42 + #define ADMV8818_REG_LUT0_SW 0x100 43 + #define ADMV8818_REG_LUT0_FILTER 0x101 44 + #define ADMV8818_REG_LUT127_SW 0x1FE 45 + #define ADMV8818_REG_LUT127_FILTER 0x1FF 46 + 47 + /* ADMV8818_REG_SPI_CONFIG_A Map */ 48 + #define ADMV8818_SOFTRESET_N_MSK BIT(7) 49 + #define ADMV8818_LSB_FIRST_N_MSK BIT(6) 50 + #define ADMV8818_ENDIAN_N_MSK BIT(5) 51 + #define ADMV8818_SDOACTIVE_N_MSK BIT(4) 52 + #define ADMV8818_SDOACTIVE_MSK BIT(3) 53 + #define ADMV8818_ENDIAN_MSK BIT(2) 54 + #define ADMV8818_LSBFIRST_MSK BIT(1) 55 + #define ADMV8818_SOFTRESET_MSK BIT(0) 56 + 57 + /* ADMV8818_REG_SPI_CONFIG_B Map */ 58 + #define ADMV8818_SINGLE_INSTRUCTION_MSK BIT(7) 59 + #define ADMV8818_CSB_STALL_MSK BIT(6) 60 + #define ADMV8818_MASTER_SLAVE_RB_MSK BIT(5) 61 + #define ADMV8818_MASTER_SLAVE_TRANSFER_MSK BIT(0) 62 + 63 + /* ADMV8818_REG_WR0_SW Map */ 64 + #define ADMV8818_SW_IN_SET_WR0_MSK BIT(7) 65 + #define ADMV8818_SW_OUT_SET_WR0_MSK BIT(6) 66 + #define ADMV8818_SW_IN_WR0_MSK GENMASK(5, 3) 67 + #define ADMV8818_SW_OUT_WR0_MSK GENMASK(2, 0) 68 + 69 + /* ADMV8818_REG_WR0_FILTER Map */ 70 + #define ADMV8818_HPF_WR0_MSK GENMASK(7, 4) 71 + #define ADMV8818_LPF_WR0_MSK GENMASK(3, 0) 72 + 73 + enum { 74 + ADMV8818_BW_FREQ, 75 + ADMV8818_CENTER_FREQ 76 + }; 77 + 78 + enum { 79 + ADMV8818_AUTO_MODE, 80 + ADMV8818_MANUAL_MODE, 81 + }; 82 + 83 + struct admv8818_state { 84 + struct spi_device *spi; 85 + struct regmap *regmap; 86 + struct clk *clkin; 87 + struct notifier_block nb; 88 + /* Protect against concurrent accesses to the device and data content*/ 89 + struct mutex lock; 90 + unsigned int filter_mode; 91 + u64 cf_hz; 92 + }; 93 + 94 + static const unsigned long long freq_range_hpf[4][2] = { 95 + {1750000000ULL, 3550000000ULL}, 96 + {3400000000ULL, 7250000000ULL}, 97 + {6600000000, 12000000000}, 98 + {12500000000, 19900000000} 99 + }; 100 + 101 + static const unsigned long long freq_range_lpf[4][2] = { 102 + {2050000000ULL, 3850000000ULL}, 103 + {3350000000ULL, 7250000000ULL}, 104 + {7000000000, 13000000000}, 105 + {12550000000, 18500000000} 106 + }; 107 + 108 + static const struct regmap_config admv8818_regmap_config = { 109 + .reg_bits = 16, 110 + .val_bits = 8, 111 + .read_flag_mask = 0x80, 112 + .max_register = 0x1FF, 113 + }; 114 + 115 + static const char * const admv8818_modes[] = { 116 + [0] = "auto", 117 + [1] = "manual" 118 + }; 119 + 120 + static int __admv8818_hpf_select(struct admv8818_state *st, u64 freq) 121 + { 122 + unsigned int hpf_step = 0, hpf_band = 0, i, j; 123 + u64 freq_step; 124 + int ret; 125 + 126 + if (freq < freq_range_hpf[0][0]) 127 + goto hpf_write; 128 + 129 + if (freq > freq_range_hpf[3][1]) { 130 + hpf_step = 15; 131 + hpf_band = 4; 132 + 133 + goto hpf_write; 134 + } 135 + 136 + for (i = 0; i < 4; i++) { 137 + freq_step = div_u64((freq_range_hpf[i][1] - 138 + freq_range_hpf[i][0]), 15); 139 + 140 + if (freq > freq_range_hpf[i][0] && 141 + (freq < freq_range_hpf[i][1] + freq_step)) { 142 + hpf_band = i + 1; 143 + 144 + for (j = 1; j <= 16; j++) { 145 + if (freq < (freq_range_hpf[i][0] + (freq_step * j))) { 146 + hpf_step = j - 1; 147 + break; 148 + } 149 + } 150 + break; 151 + } 152 + } 153 + 154 + /* Close HPF frequency gap between 12 and 12.5 GHz */ 155 + if (freq >= 12000 * HZ_PER_MHZ && freq <= 12500 * HZ_PER_MHZ) { 156 + hpf_band = 3; 157 + hpf_step = 15; 158 + } 159 + 160 + hpf_write: 161 + ret = regmap_update_bits(st->regmap, ADMV8818_REG_WR0_SW, 162 + ADMV8818_SW_IN_SET_WR0_MSK | 163 + ADMV8818_SW_IN_WR0_MSK, 164 + FIELD_PREP(ADMV8818_SW_IN_SET_WR0_MSK, 1) | 165 + FIELD_PREP(ADMV8818_SW_IN_WR0_MSK, hpf_band)); 166 + if (ret) 167 + return ret; 168 + 169 + return regmap_update_bits(st->regmap, ADMV8818_REG_WR0_FILTER, 170 + ADMV8818_HPF_WR0_MSK, 171 + FIELD_PREP(ADMV8818_HPF_WR0_MSK, hpf_step)); 172 + } 173 + 174 + static int admv8818_hpf_select(struct admv8818_state *st, u64 freq) 175 + { 176 + int ret; 177 + 178 + mutex_lock(&st->lock); 179 + ret = __admv8818_hpf_select(st, freq); 180 + mutex_unlock(&st->lock); 181 + 182 + return ret; 183 + } 184 + 185 + static int __admv8818_lpf_select(struct admv8818_state *st, u64 freq) 186 + { 187 + unsigned int lpf_step = 0, lpf_band = 0, i, j; 188 + u64 freq_step; 189 + int ret; 190 + 191 + if (freq > freq_range_lpf[3][1]) 192 + goto lpf_write; 193 + 194 + if (freq < freq_range_lpf[0][0]) { 195 + lpf_band = 1; 196 + 197 + goto lpf_write; 198 + } 199 + 200 + for (i = 0; i < 4; i++) { 201 + if (freq > freq_range_lpf[i][0] && freq < freq_range_lpf[i][1]) { 202 + lpf_band = i + 1; 203 + freq_step = div_u64((freq_range_lpf[i][1] - freq_range_lpf[i][0]), 15); 204 + 205 + for (j = 0; j <= 15; j++) { 206 + if (freq < (freq_range_lpf[i][0] + (freq_step * j))) { 207 + lpf_step = j; 208 + break; 209 + } 210 + } 211 + break; 212 + } 213 + } 214 + 215 + lpf_write: 216 + ret = regmap_update_bits(st->regmap, ADMV8818_REG_WR0_SW, 217 + ADMV8818_SW_OUT_SET_WR0_MSK | 218 + ADMV8818_SW_OUT_WR0_MSK, 219 + FIELD_PREP(ADMV8818_SW_OUT_SET_WR0_MSK, 1) | 220 + FIELD_PREP(ADMV8818_SW_OUT_WR0_MSK, lpf_band)); 221 + if (ret) 222 + return ret; 223 + 224 + return regmap_update_bits(st->regmap, ADMV8818_REG_WR0_FILTER, 225 + ADMV8818_LPF_WR0_MSK, 226 + FIELD_PREP(ADMV8818_LPF_WR0_MSK, lpf_step)); 227 + } 228 + 229 + static int admv8818_lpf_select(struct admv8818_state *st, u64 freq) 230 + { 231 + int ret; 232 + 233 + mutex_lock(&st->lock); 234 + ret = __admv8818_lpf_select(st, freq); 235 + mutex_unlock(&st->lock); 236 + 237 + return ret; 238 + } 239 + 240 + static int admv8818_rfin_band_select(struct admv8818_state *st) 241 + { 242 + int ret; 243 + 244 + st->cf_hz = clk_get_rate(st->clkin); 245 + 246 + mutex_lock(&st->lock); 247 + 248 + ret = __admv8818_hpf_select(st, st->cf_hz); 249 + if (ret) 250 + goto exit; 251 + 252 + ret = __admv8818_lpf_select(st, st->cf_hz); 253 + exit: 254 + mutex_unlock(&st->lock); 255 + return ret; 256 + } 257 + 258 + static int __admv8818_read_hpf_freq(struct admv8818_state *st, u64 *hpf_freq) 259 + { 260 + unsigned int data, hpf_band, hpf_state; 261 + int ret; 262 + 263 + ret = regmap_read(st->regmap, ADMV8818_REG_WR0_SW, &data); 264 + if (ret) 265 + return ret; 266 + 267 + hpf_band = FIELD_GET(ADMV8818_SW_IN_WR0_MSK, data); 268 + if (!hpf_band) { 269 + *hpf_freq = 0; 270 + return ret; 271 + } 272 + 273 + ret = regmap_read(st->regmap, ADMV8818_REG_WR0_FILTER, &data); 274 + if (ret) 275 + return ret; 276 + 277 + hpf_state = FIELD_GET(ADMV8818_HPF_WR0_MSK, data); 278 + 279 + *hpf_freq = div_u64(freq_range_hpf[hpf_band - 1][1] - freq_range_hpf[hpf_band - 1][0], 15); 280 + *hpf_freq = freq_range_hpf[hpf_band - 1][0] + (*hpf_freq * hpf_state); 281 + 282 + return ret; 283 + } 284 + 285 + static int admv8818_read_hpf_freq(struct admv8818_state *st, u64 *hpf_freq) 286 + { 287 + int ret; 288 + 289 + mutex_lock(&st->lock); 290 + ret = __admv8818_read_hpf_freq(st, hpf_freq); 291 + mutex_unlock(&st->lock); 292 + 293 + return ret; 294 + } 295 + 296 + static int __admv8818_read_lpf_freq(struct admv8818_state *st, u64 *lpf_freq) 297 + { 298 + unsigned int data, lpf_band, lpf_state; 299 + int ret; 300 + 301 + ret = regmap_read(st->regmap, ADMV8818_REG_WR0_SW, &data); 302 + if (ret) 303 + return ret; 304 + 305 + lpf_band = FIELD_GET(ADMV8818_SW_OUT_WR0_MSK, data); 306 + if (!lpf_band) { 307 + *lpf_freq = 0; 308 + return ret; 309 + } 310 + 311 + ret = regmap_read(st->regmap, ADMV8818_REG_WR0_FILTER, &data); 312 + if (ret) 313 + return ret; 314 + 315 + lpf_state = FIELD_GET(ADMV8818_LPF_WR0_MSK, data); 316 + 317 + *lpf_freq = div_u64(freq_range_lpf[lpf_band - 1][1] - freq_range_lpf[lpf_band - 1][0], 15); 318 + *lpf_freq = freq_range_lpf[lpf_band - 1][0] + (*lpf_freq * lpf_state); 319 + 320 + return ret; 321 + } 322 + 323 + static int admv8818_read_lpf_freq(struct admv8818_state *st, u64 *lpf_freq) 324 + { 325 + int ret; 326 + 327 + mutex_lock(&st->lock); 328 + ret = __admv8818_read_lpf_freq(st, lpf_freq); 329 + mutex_unlock(&st->lock); 330 + 331 + return ret; 332 + } 333 + 334 + static int admv8818_write_raw(struct iio_dev *indio_dev, 335 + struct iio_chan_spec const *chan, 336 + int val, int val2, long info) 337 + { 338 + struct admv8818_state *st = iio_priv(indio_dev); 339 + 340 + u64 freq = ((u64)val2 << 32 | (u32)val); 341 + 342 + switch (info) { 343 + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: 344 + return admv8818_lpf_select(st, freq); 345 + case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY: 346 + return admv8818_hpf_select(st, freq); 347 + default: 348 + return -EINVAL; 349 + } 350 + } 351 + 352 + static int admv8818_read_raw(struct iio_dev *indio_dev, 353 + struct iio_chan_spec const *chan, 354 + int *val, int *val2, long info) 355 + { 356 + struct admv8818_state *st = iio_priv(indio_dev); 357 + int ret; 358 + u64 freq; 359 + 360 + switch (info) { 361 + case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY: 362 + ret = admv8818_read_lpf_freq(st, &freq); 363 + if (ret) 364 + return ret; 365 + 366 + *val = (u32)freq; 367 + *val2 = (u32)(freq >> 32); 368 + 369 + return IIO_VAL_INT_64; 370 + case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY: 371 + ret = admv8818_read_hpf_freq(st, &freq); 372 + if (ret) 373 + return ret; 374 + 375 + *val = (u32)freq; 376 + *val2 = (u32)(freq >> 32); 377 + 378 + return IIO_VAL_INT_64; 379 + default: 380 + return -EINVAL; 381 + } 382 + } 383 + 384 + static int admv8818_reg_access(struct iio_dev *indio_dev, 385 + unsigned int reg, 386 + unsigned int write_val, 387 + unsigned int *read_val) 388 + { 389 + struct admv8818_state *st = iio_priv(indio_dev); 390 + 391 + if (read_val) 392 + return regmap_read(st->regmap, reg, read_val); 393 + else 394 + return regmap_write(st->regmap, reg, write_val); 395 + } 396 + 397 + static int admv8818_get_mode(struct iio_dev *indio_dev, 398 + const struct iio_chan_spec *chan) 399 + { 400 + struct admv8818_state *st = iio_priv(indio_dev); 401 + 402 + return st->filter_mode; 403 + } 404 + 405 + static int admv8818_set_mode(struct iio_dev *indio_dev, 406 + const struct iio_chan_spec *chan, 407 + unsigned int mode) 408 + { 409 + struct admv8818_state *st = iio_priv(indio_dev); 410 + int ret = 0; 411 + 412 + if (!st->clkin) { 413 + if (mode == ADMV8818_MANUAL_MODE) 414 + return 0; 415 + 416 + return -EINVAL; 417 + } 418 + 419 + switch (mode) { 420 + case ADMV8818_AUTO_MODE: 421 + if (!st->filter_mode) 422 + return 0; 423 + 424 + ret = clk_prepare_enable(st->clkin); 425 + if (ret) 426 + return ret; 427 + 428 + ret = clk_notifier_register(st->clkin, &st->nb); 429 + if (ret) { 430 + clk_disable_unprepare(st->clkin); 431 + 432 + return ret; 433 + } 434 + 435 + break; 436 + case ADMV8818_MANUAL_MODE: 437 + if (st->filter_mode) 438 + return 0; 439 + 440 + clk_disable_unprepare(st->clkin); 441 + 442 + ret = clk_notifier_unregister(st->clkin, &st->nb); 443 + if (ret) 444 + return ret; 445 + 446 + break; 447 + default: 448 + return -EINVAL; 449 + } 450 + 451 + st->filter_mode = mode; 452 + 453 + return ret; 454 + } 455 + 456 + static const struct iio_info admv8818_info = { 457 + .write_raw = admv8818_write_raw, 458 + .read_raw = admv8818_read_raw, 459 + .debugfs_reg_access = &admv8818_reg_access, 460 + }; 461 + 462 + static const struct iio_enum admv8818_mode_enum = { 463 + .items = admv8818_modes, 464 + .num_items = ARRAY_SIZE(admv8818_modes), 465 + .get = admv8818_get_mode, 466 + .set = admv8818_set_mode, 467 + }; 468 + 469 + static const struct iio_chan_spec_ext_info admv8818_ext_info[] = { 470 + IIO_ENUM("filter_mode", IIO_SHARED_BY_ALL, &admv8818_mode_enum), 471 + IIO_ENUM_AVAILABLE("filter_mode", IIO_SHARED_BY_ALL, &admv8818_mode_enum), 472 + { }, 473 + }; 474 + 475 + #define ADMV8818_CHAN(_channel) { \ 476 + .type = IIO_ALTVOLTAGE, \ 477 + .output = 1, \ 478 + .indexed = 1, \ 479 + .channel = _channel, \ 480 + .info_mask_separate = \ 481 + BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) | \ 482 + BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY) \ 483 + } 484 + 485 + #define ADMV8818_CHAN_BW_CF(_channel, _admv8818_ext_info) { \ 486 + .type = IIO_ALTVOLTAGE, \ 487 + .output = 1, \ 488 + .indexed = 1, \ 489 + .channel = _channel, \ 490 + .ext_info = _admv8818_ext_info, \ 491 + } 492 + 493 + static const struct iio_chan_spec admv8818_channels[] = { 494 + ADMV8818_CHAN(0), 495 + ADMV8818_CHAN_BW_CF(0, admv8818_ext_info), 496 + }; 497 + 498 + static int admv8818_freq_change(struct notifier_block *nb, unsigned long action, void *data) 499 + { 500 + struct admv8818_state *st = container_of(nb, struct admv8818_state, nb); 501 + 502 + if (action == POST_RATE_CHANGE) 503 + return notifier_from_errno(admv8818_rfin_band_select(st)); 504 + 505 + return NOTIFY_OK; 506 + } 507 + 508 + static void admv8818_clk_notifier_unreg(void *data) 509 + { 510 + struct admv8818_state *st = data; 511 + 512 + if (st->filter_mode == 0) 513 + clk_notifier_unregister(st->clkin, &st->nb); 514 + } 515 + 516 + static void admv8818_clk_disable(void *data) 517 + { 518 + struct admv8818_state *st = data; 519 + 520 + if (st->filter_mode == 0) 521 + clk_disable_unprepare(st->clkin); 522 + } 523 + 524 + static int admv8818_init(struct admv8818_state *st) 525 + { 526 + int ret; 527 + struct spi_device *spi = st->spi; 528 + unsigned int chip_id; 529 + 530 + ret = regmap_update_bits(st->regmap, ADMV8818_REG_SPI_CONFIG_A, 531 + ADMV8818_SOFTRESET_N_MSK | 532 + ADMV8818_SOFTRESET_MSK, 533 + FIELD_PREP(ADMV8818_SOFTRESET_N_MSK, 1) | 534 + FIELD_PREP(ADMV8818_SOFTRESET_MSK, 1)); 535 + if (ret) { 536 + dev_err(&spi->dev, "ADMV8818 Soft Reset failed.\n"); 537 + return ret; 538 + } 539 + 540 + ret = regmap_update_bits(st->regmap, ADMV8818_REG_SPI_CONFIG_A, 541 + ADMV8818_SDOACTIVE_N_MSK | 542 + ADMV8818_SDOACTIVE_MSK, 543 + FIELD_PREP(ADMV8818_SDOACTIVE_N_MSK, 1) | 544 + FIELD_PREP(ADMV8818_SDOACTIVE_MSK, 1)); 545 + if (ret) { 546 + dev_err(&spi->dev, "ADMV8818 SDO Enable failed.\n"); 547 + return ret; 548 + } 549 + 550 + ret = regmap_read(st->regmap, ADMV8818_REG_CHIPTYPE, &chip_id); 551 + if (ret) { 552 + dev_err(&spi->dev, "ADMV8818 Chip ID read failed.\n"); 553 + return ret; 554 + } 555 + 556 + if (chip_id != 0x1) { 557 + dev_err(&spi->dev, "ADMV8818 Invalid Chip ID.\n"); 558 + return -EINVAL; 559 + } 560 + 561 + ret = regmap_update_bits(st->regmap, ADMV8818_REG_SPI_CONFIG_B, 562 + ADMV8818_SINGLE_INSTRUCTION_MSK, 563 + FIELD_PREP(ADMV8818_SINGLE_INSTRUCTION_MSK, 1)); 564 + if (ret) { 565 + dev_err(&spi->dev, "ADMV8818 Single Instruction failed.\n"); 566 + return ret; 567 + } 568 + 569 + if (st->clkin) 570 + return admv8818_rfin_band_select(st); 571 + else 572 + return 0; 573 + } 574 + 575 + static int admv8818_clk_setup(struct admv8818_state *st) 576 + { 577 + struct spi_device *spi = st->spi; 578 + int ret; 579 + 580 + st->clkin = devm_clk_get_optional(&spi->dev, "rf_in"); 581 + if (IS_ERR(st->clkin)) 582 + return dev_err_probe(&spi->dev, PTR_ERR(st->clkin), 583 + "failed to get the input clock\n"); 584 + else if (!st->clkin) 585 + return 0; 586 + 587 + ret = clk_prepare_enable(st->clkin); 588 + if (ret) 589 + return ret; 590 + 591 + ret = devm_add_action_or_reset(&spi->dev, admv8818_clk_disable, st); 592 + if (ret) 593 + return ret; 594 + 595 + st->nb.notifier_call = admv8818_freq_change; 596 + ret = clk_notifier_register(st->clkin, &st->nb); 597 + if (ret < 0) 598 + return ret; 599 + 600 + return devm_add_action_or_reset(&spi->dev, admv8818_clk_notifier_unreg, st); 601 + } 602 + 603 + static int admv8818_probe(struct spi_device *spi) 604 + { 605 + struct iio_dev *indio_dev; 606 + struct regmap *regmap; 607 + struct admv8818_state *st; 608 + int ret; 609 + 610 + indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st)); 611 + if (!indio_dev) 612 + return -ENOMEM; 613 + 614 + regmap = devm_regmap_init_spi(spi, &admv8818_regmap_config); 615 + if (IS_ERR(regmap)) 616 + return PTR_ERR(regmap); 617 + 618 + st = iio_priv(indio_dev); 619 + st->regmap = regmap; 620 + 621 + indio_dev->info = &admv8818_info; 622 + indio_dev->name = "admv8818"; 623 + indio_dev->channels = admv8818_channels; 624 + indio_dev->num_channels = ARRAY_SIZE(admv8818_channels); 625 + 626 + st->spi = spi; 627 + 628 + ret = admv8818_clk_setup(st); 629 + if (ret) 630 + return ret; 631 + 632 + mutex_init(&st->lock); 633 + 634 + ret = admv8818_init(st); 635 + if (ret) 636 + return ret; 637 + 638 + return devm_iio_device_register(&spi->dev, indio_dev); 639 + } 640 + 641 + static const struct spi_device_id admv8818_id[] = { 642 + { "admv8818", 0 }, 643 + {} 644 + }; 645 + MODULE_DEVICE_TABLE(spi, admv8818_id); 646 + 647 + static const struct of_device_id admv8818_of_match[] = { 648 + { .compatible = "adi,admv8818" }, 649 + {} 650 + }; 651 + MODULE_DEVICE_TABLE(of, admv8818_of_match); 652 + 653 + static struct spi_driver admv8818_driver = { 654 + .driver = { 655 + .name = "admv8818", 656 + .of_match_table = admv8818_of_match, 657 + }, 658 + .probe = admv8818_probe, 659 + .id_table = admv8818_id, 660 + }; 661 + module_spi_driver(admv8818_driver); 662 + 663 + MODULE_AUTHOR("Antoniu Miclaus <antoniu.miclaus@analog.com"); 664 + MODULE_DESCRIPTION("Analog Devices ADMV8818"); 665 + MODULE_LICENSE("GPL v2");