713 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * ADMV8818 driver4 *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 0x023#define ADMV8818_REG_SPI_CONFIG_B 0x124#define ADMV8818_REG_CHIPTYPE 0x325#define ADMV8818_REG_PRODUCT_ID_L 0x426#define ADMV8818_REG_PRODUCT_ID_H 0x527#define ADMV8818_REG_FAST_LATCH_POINTER 0x1028#define ADMV8818_REG_FAST_LATCH_STOP 0x1129#define ADMV8818_REG_FAST_LATCH_START 0x1230#define ADMV8818_REG_FAST_LATCH_DIRECTION 0x1331#define ADMV8818_REG_FAST_LATCH_STATE 0x1432#define ADMV8818_REG_WR0_SW 0x2033#define ADMV8818_REG_WR0_FILTER 0x2134#define ADMV8818_REG_WR1_SW 0x2235#define ADMV8818_REG_WR1_FILTER 0x2336#define ADMV8818_REG_WR2_SW 0x2437#define ADMV8818_REG_WR2_FILTER 0x2538#define ADMV8818_REG_WR3_SW 0x2639#define ADMV8818_REG_WR3_FILTER 0x2740#define ADMV8818_REG_WR4_SW 0x2841#define ADMV8818_REG_WR4_FILTER 0x2942#define ADMV8818_REG_LUT0_SW 0x10043#define ADMV8818_REG_LUT0_FILTER 0x10144#define ADMV8818_REG_LUT127_SW 0x1FE45#define ADMV8818_REG_LUT127_FILTER 0x1FF46 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 73enum {74 ADMV8818_BW_FREQ,75 ADMV8818_CENTER_FREQ76};77 78enum {79 ADMV8818_AUTO_MODE,80 ADMV8818_MANUAL_MODE,81 ADMV8818_BYPASS_MODE,82};83 84struct admv8818_state {85 struct spi_device *spi;86 struct regmap *regmap;87 struct clk *clkin;88 struct notifier_block nb;89 /* Protect against concurrent accesses to the device and data content*/90 struct mutex lock;91 unsigned int filter_mode;92 u64 cf_hz;93};94 95static const unsigned long long freq_range_hpf[4][2] = {96 {1750000000ULL, 3550000000ULL},97 {3400000000ULL, 7250000000ULL},98 {6600000000, 12000000000},99 {12500000000, 19900000000}100};101 102static const unsigned long long freq_range_lpf[4][2] = {103 {2050000000ULL, 3850000000ULL},104 {3350000000ULL, 7250000000ULL},105 {7000000000, 13000000000},106 {12550000000, 18500000000}107};108 109static const struct regmap_config admv8818_regmap_config = {110 .reg_bits = 16,111 .val_bits = 8,112 .read_flag_mask = 0x80,113 .max_register = 0x1FF,114};115 116static const char * const admv8818_modes[] = {117 [0] = "auto",118 [1] = "manual",119 [2] = "bypass"120};121 122static int __admv8818_hpf_select(struct admv8818_state *st, u64 freq)123{124 unsigned int hpf_step = 0, hpf_band = 0, i, j;125 u64 freq_step;126 int ret;127 128 if (freq < freq_range_hpf[0][0])129 goto hpf_write;130 131 if (freq > freq_range_hpf[3][1]) {132 hpf_step = 15;133 hpf_band = 4;134 135 goto hpf_write;136 }137 138 for (i = 0; i < 4; i++) {139 freq_step = div_u64((freq_range_hpf[i][1] -140 freq_range_hpf[i][0]), 15);141 142 if (freq > freq_range_hpf[i][0] &&143 (freq < freq_range_hpf[i][1] + freq_step)) {144 hpf_band = i + 1;145 146 for (j = 1; j <= 16; j++) {147 if (freq < (freq_range_hpf[i][0] + (freq_step * j))) {148 hpf_step = j - 1;149 break;150 }151 }152 break;153 }154 }155 156 /* Close HPF frequency gap between 12 and 12.5 GHz */157 if (freq >= 12000 * HZ_PER_MHZ && freq <= 12500 * HZ_PER_MHZ) {158 hpf_band = 3;159 hpf_step = 15;160 }161 162hpf_write:163 ret = regmap_update_bits(st->regmap, ADMV8818_REG_WR0_SW,164 ADMV8818_SW_IN_SET_WR0_MSK |165 ADMV8818_SW_IN_WR0_MSK,166 FIELD_PREP(ADMV8818_SW_IN_SET_WR0_MSK, 1) |167 FIELD_PREP(ADMV8818_SW_IN_WR0_MSK, hpf_band));168 if (ret)169 return ret;170 171 return regmap_update_bits(st->regmap, ADMV8818_REG_WR0_FILTER,172 ADMV8818_HPF_WR0_MSK,173 FIELD_PREP(ADMV8818_HPF_WR0_MSK, hpf_step));174}175 176static int admv8818_hpf_select(struct admv8818_state *st, u64 freq)177{178 int ret;179 180 mutex_lock(&st->lock);181 ret = __admv8818_hpf_select(st, freq);182 mutex_unlock(&st->lock);183 184 return ret;185}186 187static int __admv8818_lpf_select(struct admv8818_state *st, u64 freq)188{189 unsigned int lpf_step = 0, lpf_band = 0, i, j;190 u64 freq_step;191 int ret;192 193 if (freq > freq_range_lpf[3][1])194 goto lpf_write;195 196 if (freq < freq_range_lpf[0][0]) {197 lpf_band = 1;198 199 goto lpf_write;200 }201 202 for (i = 0; i < 4; i++) {203 if (freq > freq_range_lpf[i][0] && freq < freq_range_lpf[i][1]) {204 lpf_band = i + 1;205 freq_step = div_u64((freq_range_lpf[i][1] - freq_range_lpf[i][0]), 15);206 207 for (j = 0; j <= 15; j++) {208 if (freq < (freq_range_lpf[i][0] + (freq_step * j))) {209 lpf_step = j;210 break;211 }212 }213 break;214 }215 }216 217lpf_write:218 ret = regmap_update_bits(st->regmap, ADMV8818_REG_WR0_SW,219 ADMV8818_SW_OUT_SET_WR0_MSK |220 ADMV8818_SW_OUT_WR0_MSK,221 FIELD_PREP(ADMV8818_SW_OUT_SET_WR0_MSK, 1) |222 FIELD_PREP(ADMV8818_SW_OUT_WR0_MSK, lpf_band));223 if (ret)224 return ret;225 226 return regmap_update_bits(st->regmap, ADMV8818_REG_WR0_FILTER,227 ADMV8818_LPF_WR0_MSK,228 FIELD_PREP(ADMV8818_LPF_WR0_MSK, lpf_step));229}230 231static int admv8818_lpf_select(struct admv8818_state *st, u64 freq)232{233 int ret;234 235 mutex_lock(&st->lock);236 ret = __admv8818_lpf_select(st, freq);237 mutex_unlock(&st->lock);238 239 return ret;240}241 242static int admv8818_rfin_band_select(struct admv8818_state *st)243{244 int ret;245 246 st->cf_hz = clk_get_rate(st->clkin);247 248 mutex_lock(&st->lock);249 250 ret = __admv8818_hpf_select(st, st->cf_hz);251 if (ret)252 goto exit;253 254 ret = __admv8818_lpf_select(st, st->cf_hz);255exit:256 mutex_unlock(&st->lock);257 return ret;258}259 260static int __admv8818_read_hpf_freq(struct admv8818_state *st, u64 *hpf_freq)261{262 unsigned int data, hpf_band, hpf_state;263 int ret;264 265 ret = regmap_read(st->regmap, ADMV8818_REG_WR0_SW, &data);266 if (ret)267 return ret;268 269 hpf_band = FIELD_GET(ADMV8818_SW_IN_WR0_MSK, data);270 if (!hpf_band || hpf_band > 4) {271 *hpf_freq = 0;272 return ret;273 }274 275 ret = regmap_read(st->regmap, ADMV8818_REG_WR0_FILTER, &data);276 if (ret)277 return ret;278 279 hpf_state = FIELD_GET(ADMV8818_HPF_WR0_MSK, data);280 281 *hpf_freq = div_u64(freq_range_hpf[hpf_band - 1][1] - freq_range_hpf[hpf_band - 1][0], 15);282 *hpf_freq = freq_range_hpf[hpf_band - 1][0] + (*hpf_freq * hpf_state);283 284 return ret;285}286 287static int admv8818_read_hpf_freq(struct admv8818_state *st, u64 *hpf_freq)288{289 int ret;290 291 mutex_lock(&st->lock);292 ret = __admv8818_read_hpf_freq(st, hpf_freq);293 mutex_unlock(&st->lock);294 295 return ret;296}297 298static int __admv8818_read_lpf_freq(struct admv8818_state *st, u64 *lpf_freq)299{300 unsigned int data, lpf_band, lpf_state;301 int ret;302 303 ret = regmap_read(st->regmap, ADMV8818_REG_WR0_SW, &data);304 if (ret)305 return ret;306 307 lpf_band = FIELD_GET(ADMV8818_SW_OUT_WR0_MSK, data);308 if (!lpf_band || lpf_band > 4) {309 *lpf_freq = 0;310 return ret;311 }312 313 ret = regmap_read(st->regmap, ADMV8818_REG_WR0_FILTER, &data);314 if (ret)315 return ret;316 317 lpf_state = FIELD_GET(ADMV8818_LPF_WR0_MSK, data);318 319 *lpf_freq = div_u64(freq_range_lpf[lpf_band - 1][1] - freq_range_lpf[lpf_band - 1][0], 15);320 *lpf_freq = freq_range_lpf[lpf_band - 1][0] + (*lpf_freq * lpf_state);321 322 return ret;323}324 325static int admv8818_read_lpf_freq(struct admv8818_state *st, u64 *lpf_freq)326{327 int ret;328 329 mutex_lock(&st->lock);330 ret = __admv8818_read_lpf_freq(st, lpf_freq);331 mutex_unlock(&st->lock);332 333 return ret;334}335 336static int admv8818_write_raw(struct iio_dev *indio_dev,337 struct iio_chan_spec const *chan,338 int val, int val2, long info)339{340 struct admv8818_state *st = iio_priv(indio_dev);341 342 u64 freq = ((u64)val2 << 32 | (u32)val);343 344 switch (info) {345 case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:346 return admv8818_lpf_select(st, freq);347 case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:348 return admv8818_hpf_select(st, freq);349 default:350 return -EINVAL;351 }352}353 354static int admv8818_read_raw(struct iio_dev *indio_dev,355 struct iio_chan_spec const *chan,356 int *val, int *val2, long info)357{358 struct admv8818_state *st = iio_priv(indio_dev);359 int ret;360 u64 freq;361 362 switch (info) {363 case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:364 ret = admv8818_read_lpf_freq(st, &freq);365 if (ret)366 return ret;367 368 *val = (u32)freq;369 *val2 = (u32)(freq >> 32);370 371 return IIO_VAL_INT_64;372 case IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY:373 ret = admv8818_read_hpf_freq(st, &freq);374 if (ret)375 return ret;376 377 *val = (u32)freq;378 *val2 = (u32)(freq >> 32);379 380 return IIO_VAL_INT_64;381 default:382 return -EINVAL;383 }384}385 386static int admv8818_reg_access(struct iio_dev *indio_dev,387 unsigned int reg,388 unsigned int write_val,389 unsigned int *read_val)390{391 struct admv8818_state *st = iio_priv(indio_dev);392 393 if (read_val)394 return regmap_read(st->regmap, reg, read_val);395 else396 return regmap_write(st->regmap, reg, write_val);397}398 399static int admv8818_filter_bypass(struct admv8818_state *st)400{401 int ret;402 403 mutex_lock(&st->lock);404 405 ret = regmap_update_bits(st->regmap, ADMV8818_REG_WR0_SW,406 ADMV8818_SW_IN_SET_WR0_MSK |407 ADMV8818_SW_IN_WR0_MSK |408 ADMV8818_SW_OUT_SET_WR0_MSK |409 ADMV8818_SW_OUT_WR0_MSK,410 FIELD_PREP(ADMV8818_SW_IN_SET_WR0_MSK, 1) |411 FIELD_PREP(ADMV8818_SW_IN_WR0_MSK, 0) |412 FIELD_PREP(ADMV8818_SW_OUT_SET_WR0_MSK, 1) |413 FIELD_PREP(ADMV8818_SW_OUT_WR0_MSK, 0));414 if (ret)415 goto exit;416 417 ret = regmap_update_bits(st->regmap, ADMV8818_REG_WR0_FILTER,418 ADMV8818_HPF_WR0_MSK |419 ADMV8818_LPF_WR0_MSK,420 FIELD_PREP(ADMV8818_HPF_WR0_MSK, 0) |421 FIELD_PREP(ADMV8818_LPF_WR0_MSK, 0));422 423exit:424 mutex_unlock(&st->lock);425 426 return ret;427}428 429static int admv8818_get_mode(struct iio_dev *indio_dev,430 const struct iio_chan_spec *chan)431{432 struct admv8818_state *st = iio_priv(indio_dev);433 434 return st->filter_mode;435}436 437static int admv8818_set_mode(struct iio_dev *indio_dev,438 const struct iio_chan_spec *chan,439 unsigned int mode)440{441 struct admv8818_state *st = iio_priv(indio_dev);442 int ret = 0;443 444 if (!st->clkin) {445 if (mode == ADMV8818_MANUAL_MODE)446 goto set_mode;447 448 if (mode == ADMV8818_BYPASS_MODE) {449 ret = admv8818_filter_bypass(st);450 if (ret)451 return ret;452 453 goto set_mode;454 }455 456 return -EINVAL;457 }458 459 switch (mode) {460 case ADMV8818_AUTO_MODE:461 if (st->filter_mode == ADMV8818_AUTO_MODE)462 return 0;463 464 ret = clk_prepare_enable(st->clkin);465 if (ret)466 return ret;467 468 ret = clk_notifier_register(st->clkin, &st->nb);469 if (ret) {470 clk_disable_unprepare(st->clkin);471 472 return ret;473 }474 475 break;476 case ADMV8818_MANUAL_MODE:477 case ADMV8818_BYPASS_MODE:478 if (st->filter_mode == ADMV8818_AUTO_MODE) {479 clk_disable_unprepare(st->clkin);480 481 ret = clk_notifier_unregister(st->clkin, &st->nb);482 if (ret)483 return ret;484 }485 486 if (mode == ADMV8818_BYPASS_MODE) {487 ret = admv8818_filter_bypass(st);488 if (ret)489 return ret;490 }491 492 break;493 default:494 return -EINVAL;495 }496 497set_mode:498 st->filter_mode = mode;499 500 return ret;501}502 503static const struct iio_info admv8818_info = {504 .write_raw = admv8818_write_raw,505 .read_raw = admv8818_read_raw,506 .debugfs_reg_access = &admv8818_reg_access,507};508 509static const struct iio_enum admv8818_mode_enum = {510 .items = admv8818_modes,511 .num_items = ARRAY_SIZE(admv8818_modes),512 .get = admv8818_get_mode,513 .set = admv8818_set_mode,514};515 516static const struct iio_chan_spec_ext_info admv8818_ext_info[] = {517 IIO_ENUM("filter_mode", IIO_SHARED_BY_ALL, &admv8818_mode_enum),518 IIO_ENUM_AVAILABLE("filter_mode", IIO_SHARED_BY_ALL, &admv8818_mode_enum),519 { },520};521 522#define ADMV8818_CHAN(_channel) { \523 .type = IIO_ALTVOLTAGE, \524 .output = 1, \525 .indexed = 1, \526 .channel = _channel, \527 .info_mask_separate = \528 BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY) | \529 BIT(IIO_CHAN_INFO_HIGH_PASS_FILTER_3DB_FREQUENCY) \530}531 532#define ADMV8818_CHAN_BW_CF(_channel, _admv8818_ext_info) { \533 .type = IIO_ALTVOLTAGE, \534 .output = 1, \535 .indexed = 1, \536 .channel = _channel, \537 .ext_info = _admv8818_ext_info, \538}539 540static const struct iio_chan_spec admv8818_channels[] = {541 ADMV8818_CHAN(0),542 ADMV8818_CHAN_BW_CF(0, admv8818_ext_info),543};544 545static int admv8818_freq_change(struct notifier_block *nb, unsigned long action, void *data)546{547 struct admv8818_state *st = container_of(nb, struct admv8818_state, nb);548 549 if (action == POST_RATE_CHANGE)550 return notifier_from_errno(admv8818_rfin_band_select(st));551 552 return NOTIFY_OK;553}554 555static void admv8818_clk_notifier_unreg(void *data)556{557 struct admv8818_state *st = data;558 559 if (st->filter_mode == 0)560 clk_notifier_unregister(st->clkin, &st->nb);561}562 563static void admv8818_clk_disable(void *data)564{565 struct admv8818_state *st = data;566 567 if (st->filter_mode == 0)568 clk_disable_unprepare(st->clkin);569}570 571static int admv8818_init(struct admv8818_state *st)572{573 int ret;574 struct spi_device *spi = st->spi;575 unsigned int chip_id;576 577 ret = regmap_update_bits(st->regmap, ADMV8818_REG_SPI_CONFIG_A,578 ADMV8818_SOFTRESET_N_MSK |579 ADMV8818_SOFTRESET_MSK,580 FIELD_PREP(ADMV8818_SOFTRESET_N_MSK, 1) |581 FIELD_PREP(ADMV8818_SOFTRESET_MSK, 1));582 if (ret) {583 dev_err(&spi->dev, "ADMV8818 Soft Reset failed.\n");584 return ret;585 }586 587 ret = regmap_update_bits(st->regmap, ADMV8818_REG_SPI_CONFIG_A,588 ADMV8818_SDOACTIVE_N_MSK |589 ADMV8818_SDOACTIVE_MSK,590 FIELD_PREP(ADMV8818_SDOACTIVE_N_MSK, 1) |591 FIELD_PREP(ADMV8818_SDOACTIVE_MSK, 1));592 if (ret) {593 dev_err(&spi->dev, "ADMV8818 SDO Enable failed.\n");594 return ret;595 }596 597 ret = regmap_read(st->regmap, ADMV8818_REG_CHIPTYPE, &chip_id);598 if (ret) {599 dev_err(&spi->dev, "ADMV8818 Chip ID read failed.\n");600 return ret;601 }602 603 if (chip_id != 0x1) {604 dev_err(&spi->dev, "ADMV8818 Invalid Chip ID.\n");605 return -EINVAL;606 }607 608 ret = regmap_update_bits(st->regmap, ADMV8818_REG_SPI_CONFIG_B,609 ADMV8818_SINGLE_INSTRUCTION_MSK,610 FIELD_PREP(ADMV8818_SINGLE_INSTRUCTION_MSK, 1));611 if (ret) {612 dev_err(&spi->dev, "ADMV8818 Single Instruction failed.\n");613 return ret;614 }615 616 if (st->clkin)617 return admv8818_rfin_band_select(st);618 else619 return 0;620}621 622static int admv8818_clk_setup(struct admv8818_state *st)623{624 struct spi_device *spi = st->spi;625 int ret;626 627 st->clkin = devm_clk_get_optional(&spi->dev, "rf_in");628 if (IS_ERR(st->clkin))629 return dev_err_probe(&spi->dev, PTR_ERR(st->clkin),630 "failed to get the input clock\n");631 else if (!st->clkin)632 return 0;633 634 ret = clk_prepare_enable(st->clkin);635 if (ret)636 return ret;637 638 ret = devm_add_action_or_reset(&spi->dev, admv8818_clk_disable, st);639 if (ret)640 return ret;641 642 st->nb.notifier_call = admv8818_freq_change;643 ret = clk_notifier_register(st->clkin, &st->nb);644 if (ret < 0)645 return ret;646 647 return devm_add_action_or_reset(&spi->dev, admv8818_clk_notifier_unreg, st);648}649 650static int admv8818_probe(struct spi_device *spi)651{652 struct iio_dev *indio_dev;653 struct regmap *regmap;654 struct admv8818_state *st;655 int ret;656 657 indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));658 if (!indio_dev)659 return -ENOMEM;660 661 regmap = devm_regmap_init_spi(spi, &admv8818_regmap_config);662 if (IS_ERR(regmap))663 return PTR_ERR(regmap);664 665 st = iio_priv(indio_dev);666 st->regmap = regmap;667 668 indio_dev->info = &admv8818_info;669 indio_dev->name = "admv8818";670 indio_dev->channels = admv8818_channels;671 indio_dev->num_channels = ARRAY_SIZE(admv8818_channels);672 673 st->spi = spi;674 675 ret = admv8818_clk_setup(st);676 if (ret)677 return ret;678 679 mutex_init(&st->lock);680 681 ret = admv8818_init(st);682 if (ret)683 return ret;684 685 return devm_iio_device_register(&spi->dev, indio_dev);686}687 688static const struct spi_device_id admv8818_id[] = {689 { "admv8818", 0 },690 {}691};692MODULE_DEVICE_TABLE(spi, admv8818_id);693 694static const struct of_device_id admv8818_of_match[] = {695 { .compatible = "adi,admv8818" },696 {}697};698MODULE_DEVICE_TABLE(of, admv8818_of_match);699 700static struct spi_driver admv8818_driver = {701 .driver = {702 .name = "admv8818",703 .of_match_table = admv8818_of_match,704 },705 .probe = admv8818_probe,706 .id_table = admv8818_id,707};708module_spi_driver(admv8818_driver);709 710MODULE_AUTHOR("Antoniu Miclaus <antoniu.miclaus@analog.com");711MODULE_DESCRIPTION("Analog Devices ADMV8818");712MODULE_LICENSE("GPL v2");713