Commit e764df67963940b4123325710536a9471d1e24ae
Committed by
Jonathan Cameron
1 parent
9404fa15f2
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
iio: frequency: adf4350: Add support for dt bindings
Per review feedback from Lars-Peter Clausen <lars@metafoo.de> Changes since V1: Fix return value handling of adf4350_parse_dt() Use of_get_gpio Avoid abbreviations in devicetree properties Fix typo in docs Signed-off-by: Michael Hennerich <michael.hennerich@analog.com> Reviewed-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
Showing 2 changed files with 213 additions and 1 deletions Side-by-side Diff
Documentation/devicetree/bindings/iio/frequency/adf4350.txt
1 | +Analog Devices ADF4350/ADF4351 device driver | |
2 | + | |
3 | +Required properties: | |
4 | + - compatible: Should be one of | |
5 | + * "adi,adf4350": When using the ADF4350 device | |
6 | + * "adi,adf4351": When using the ADF4351 device | |
7 | + - reg: SPI chip select numbert for the device | |
8 | + - spi-max-frequency: Max SPI frequency to use (< 20000000) | |
9 | + - clocks: From common clock binding. Clock is phandle to clock for | |
10 | + ADF435x Reference Clock (CLKIN). | |
11 | + | |
12 | +Optional properties: | |
13 | + - gpios: GPIO Lock detect - If set with a valid phandle and GPIO number, | |
14 | + pll lock state is tested upon read. | |
15 | + - adi,channel-spacing: Channel spacing in Hz (influences MODULUS). | |
16 | + - adi,power-up-frequency: If set in Hz the PLL tunes to | |
17 | + the desired frequency on probe. | |
18 | + - adi,reference-div-factor: If set the driver skips dynamic calculation | |
19 | + and uses this default value instead. | |
20 | + - adi,reference-doubler-enable: Enables reference doubler. | |
21 | + - adi,reference-div2-enable: Enables reference divider. | |
22 | + - adi,phase-detector-polarity-positive-enable: Enables positive phase | |
23 | + detector polarity. Default = negative. | |
24 | + - adi,lock-detect-precision-6ns-enable: Enables 6ns lock detect precision. | |
25 | + Default = 10ns. | |
26 | + - adi,lock-detect-function-integer-n-enable: Enables lock detect | |
27 | + for integer-N mode. Default = factional-N mode. | |
28 | + - adi,charge-pump-current: Charge pump current in mA. | |
29 | + Default = 2500mA. | |
30 | + - adi,muxout-select: On chip multiplexer output selection. | |
31 | + Valid values for the multiplexer output are: | |
32 | + 0: Three-State Output (default) | |
33 | + 1: DVDD | |
34 | + 2: DGND | |
35 | + 3: R-Counter output | |
36 | + 4: N-Divider output | |
37 | + 5: Analog lock detect | |
38 | + 6: Digital lock detect | |
39 | + - adi,low-spur-mode-enable: Enables low spur mode. | |
40 | + Default = Low noise mode. | |
41 | + - adi,cycle-slip-reduction-enable: Enables cycle slip reduction. | |
42 | + - adi,charge-cancellation-enable: Enabled charge pump | |
43 | + charge cancellation for integer-N modes. | |
44 | + - adi,anti-backlash-3ns-enable: Enables 3ns antibacklash pulse width | |
45 | + for integer-N modes. | |
46 | + - adi,band-select-clock-mode-high-enable: Enables faster band | |
47 | + selection logic. | |
48 | + - adi,12bit-clk-divider: Clock divider value used when | |
49 | + adi,12bit-clkdiv-mode != 0 | |
50 | + - adi,clk-divider-mode: | |
51 | + Valid values for the clkdiv mode are: | |
52 | + 0: Clock divider off (default) | |
53 | + 1: Fast lock enable | |
54 | + 2: Phase resync enable | |
55 | + - adi,aux-output-enable: Enables auxiliary RF output. | |
56 | + - adi,aux-output-fundamental-enable: Selects fundamental VCO output on | |
57 | + the auxiliary RF output. Default = Output of RF dividers. | |
58 | + - adi,mute-till-lock-enable: Enables Mute-Till-Lock-Detect function. | |
59 | + - adi,output-power: Output power selection. | |
60 | + Valid values for the power mode are: | |
61 | + 0: -4dBm (default) | |
62 | + 1: -1dBm | |
63 | + 2: +2dBm | |
64 | + 3: +5dBm | |
65 | + - adi,aux-output-power: Auxiliary output power selection. | |
66 | + Valid values for the power mode are: | |
67 | + 0: -4dBm (default) | |
68 | + 1: -1dBm | |
69 | + 2: +2dBm | |
70 | + 3: +5dBm | |
71 | + | |
72 | + | |
73 | +Example: | |
74 | + lo_pll0_rx_adf4351: adf4351-rx-lpc@4 { | |
75 | + compatible = "adi,adf4351"; | |
76 | + reg = <4>; | |
77 | + spi-max-frequency = <10000000>; | |
78 | + clocks = <&clk0_ad9523 9>; | |
79 | + clock-names = "clkin"; | |
80 | + adi,channel-spacing = <10000>; | |
81 | + adi,power-up-frequency = <2400000000>; | |
82 | + adi,phase-detector-polarity-positive-enable; | |
83 | + adi,charge-pump-current = <2500>; | |
84 | + adi,output-power = <3>; | |
85 | + adi,mute-till-lock-enable; | |
86 | + }; |
drivers/iio/frequency/adf4350.c
... | ... | @@ -18,6 +18,8 @@ |
18 | 18 | #include <linux/gpio.h> |
19 | 19 | #include <asm/div64.h> |
20 | 20 | #include <linux/clk.h> |
21 | +#include <linux/of.h> | |
22 | +#include <linux/of_gpio.h> | |
21 | 23 | |
22 | 24 | #include <linux/iio/iio.h> |
23 | 25 | #include <linux/iio/sysfs.h> |
24 | 26 | |
25 | 27 | |
... | ... | @@ -375,13 +377,137 @@ |
375 | 377 | .driver_module = THIS_MODULE, |
376 | 378 | }; |
377 | 379 | |
380 | +#ifdef CONFIG_OF | |
381 | +static struct adf4350_platform_data *adf4350_parse_dt(struct device *dev) | |
382 | +{ | |
383 | + struct device_node *np = dev->of_node; | |
384 | + struct adf4350_platform_data *pdata; | |
385 | + unsigned int tmp; | |
386 | + int ret; | |
387 | + | |
388 | + pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | |
389 | + if (!pdata) { | |
390 | + dev_err(dev, "could not allocate memory for platform data\n"); | |
391 | + return NULL; | |
392 | + } | |
393 | + | |
394 | + strncpy(&pdata->name[0], np->name, SPI_NAME_SIZE - 1); | |
395 | + | |
396 | + tmp = 10000; | |
397 | + of_property_read_u32(np, "adi,channel-spacing", &tmp); | |
398 | + pdata->channel_spacing = tmp; | |
399 | + | |
400 | + tmp = 0; | |
401 | + of_property_read_u32(np, "adi,power-up-frequency", &tmp); | |
402 | + pdata->power_up_frequency = tmp; | |
403 | + | |
404 | + tmp = 0; | |
405 | + of_property_read_u32(np, "adi,reference-div-factor", &tmp); | |
406 | + pdata->ref_div_factor = tmp; | |
407 | + | |
408 | + ret = of_get_gpio(np, 0); | |
409 | + if (ret < 0) | |
410 | + pdata->gpio_lock_detect = -1; | |
411 | + else | |
412 | + pdata->gpio_lock_detect = ret; | |
413 | + | |
414 | + pdata->ref_doubler_en = of_property_read_bool(np, | |
415 | + "adi,reference-doubler-enable"); | |
416 | + pdata->ref_div2_en = of_property_read_bool(np, | |
417 | + "adi,reference-div2-enable"); | |
418 | + | |
419 | + /* r2_user_settings */ | |
420 | + pdata->r2_user_settings = of_property_read_bool(np, | |
421 | + "adi,phase-detector-polarity-positive-enable") ? | |
422 | + ADF4350_REG2_PD_POLARITY_POS : 0; | |
423 | + pdata->r2_user_settings |= of_property_read_bool(np, | |
424 | + "adi,lock-detect-precision-6ns-enable") ? | |
425 | + ADF4350_REG2_LDP_6ns : 0; | |
426 | + pdata->r2_user_settings |= of_property_read_bool(np, | |
427 | + "adi,lock-detect-function-integer-n-enable") ? | |
428 | + ADF4350_REG2_LDF_INT_N : 0; | |
429 | + | |
430 | + tmp = 2500; | |
431 | + of_property_read_u32(np, "adi,charge-pump-current", &tmp); | |
432 | + pdata->r2_user_settings |= ADF4350_REG2_CHARGE_PUMP_CURR_uA(tmp); | |
433 | + | |
434 | + tmp = 0; | |
435 | + of_property_read_u32(np, "adi,muxout-select", &tmp); | |
436 | + pdata->r2_user_settings |= ADF4350_REG2_MUXOUT(tmp); | |
437 | + | |
438 | + pdata->r2_user_settings |= of_property_read_bool(np, | |
439 | + "adi,low-spur-mode-enable") ? | |
440 | + ADF4350_REG2_NOISE_MODE(0x3) : 0; | |
441 | + | |
442 | + /* r3_user_settings */ | |
443 | + | |
444 | + pdata->r3_user_settings = of_property_read_bool(np, | |
445 | + "adi,cycle-slip-reduction-enable") ? | |
446 | + ADF4350_REG3_12BIT_CSR_EN : 0; | |
447 | + pdata->r3_user_settings |= of_property_read_bool(np, | |
448 | + "adi,charge-cancellation-enable") ? | |
449 | + ADF4351_REG3_CHARGE_CANCELLATION_EN : 0; | |
450 | + | |
451 | + pdata->r3_user_settings |= of_property_read_bool(np, | |
452 | + "adi,anti-backlash-3ns-enable") ? | |
453 | + ADF4351_REG3_ANTI_BACKLASH_3ns_EN : 0; | |
454 | + pdata->r3_user_settings |= of_property_read_bool(np, | |
455 | + "adi,band-select-clock-mode-high-enable") ? | |
456 | + ADF4351_REG3_BAND_SEL_CLOCK_MODE_HIGH : 0; | |
457 | + | |
458 | + tmp = 0; | |
459 | + of_property_read_u32(np, "adi,12bit-clk-divider", &tmp); | |
460 | + pdata->r3_user_settings |= ADF4350_REG3_12BIT_CLKDIV(tmp); | |
461 | + | |
462 | + tmp = 0; | |
463 | + of_property_read_u32(np, "adi,clk-divider-mode", &tmp); | |
464 | + pdata->r3_user_settings |= ADF4350_REG3_12BIT_CLKDIV_MODE(tmp); | |
465 | + | |
466 | + /* r4_user_settings */ | |
467 | + | |
468 | + pdata->r4_user_settings = of_property_read_bool(np, | |
469 | + "adi,aux-output-enable") ? | |
470 | + ADF4350_REG4_AUX_OUTPUT_EN : 0; | |
471 | + pdata->r4_user_settings |= of_property_read_bool(np, | |
472 | + "adi,aux-output-fundamental-enable") ? | |
473 | + ADF4350_REG4_AUX_OUTPUT_FUND : 0; | |
474 | + pdata->r4_user_settings |= of_property_read_bool(np, | |
475 | + "adi,mute-till-lock-enable") ? | |
476 | + ADF4350_REG4_MUTE_TILL_LOCK_EN : 0; | |
477 | + | |
478 | + tmp = 0; | |
479 | + of_property_read_u32(np, "adi,output-power", &tmp); | |
480 | + pdata->r4_user_settings |= ADF4350_REG4_OUTPUT_PWR(tmp); | |
481 | + | |
482 | + tmp = 0; | |
483 | + of_property_read_u32(np, "adi,aux-output-power", &tmp); | |
484 | + pdata->r4_user_settings |= ADF4350_REG4_AUX_OUTPUT_PWR(tmp); | |
485 | + | |
486 | + return pdata; | |
487 | +} | |
488 | +#else | |
489 | +static | |
490 | +struct adf4350_platform_data *adf4350_parse_dt(struct device *dev) | |
491 | +{ | |
492 | + return NULL; | |
493 | +} | |
494 | +#endif | |
495 | + | |
378 | 496 | static int adf4350_probe(struct spi_device *spi) |
379 | 497 | { |
380 | - struct adf4350_platform_data *pdata = spi->dev.platform_data; | |
498 | + struct adf4350_platform_data *pdata; | |
381 | 499 | struct iio_dev *indio_dev; |
382 | 500 | struct adf4350_state *st; |
383 | 501 | struct clk *clk = NULL; |
384 | 502 | int ret; |
503 | + | |
504 | + if (spi->dev.of_node) { | |
505 | + pdata = adf4350_parse_dt(&spi->dev); | |
506 | + if (pdata == NULL) | |
507 | + return -EINVAL; | |
508 | + } else { | |
509 | + pdata = spi->dev.platform_data; | |
510 | + } | |
385 | 511 | |
386 | 512 | if (!pdata) { |
387 | 513 | dev_warn(&spi->dev, "no platform data? using default\n"); |