diff options
-rw-r--r-- | Documentation/devicetree/bindings/iio/frequency/adf4350.txt | 86 | ||||
-rw-r--r-- | drivers/iio/frequency/adf4350.c | 128 |
2 files changed, 213 insertions, 1 deletions
diff --git a/Documentation/devicetree/bindings/iio/frequency/adf4350.txt b/Documentation/devicetree/bindings/iio/frequency/adf4350.txt new file mode 100644 index 000000000000..f8c181d81d2d --- /dev/null +++ b/Documentation/devicetree/bindings/iio/frequency/adf4350.txt | |||
@@ -0,0 +1,86 @@ | |||
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 | }; | ||
diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index f6849c8b6a90..a4157cdb314d 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c | |||
@@ -18,6 +18,8 @@ | |||
18 | #include <linux/gpio.h> | 18 | #include <linux/gpio.h> |
19 | #include <asm/div64.h> | 19 | #include <asm/div64.h> |
20 | #include <linux/clk.h> | 20 | #include <linux/clk.h> |
21 | #include <linux/of.h> | ||
22 | #include <linux/of_gpio.h> | ||
21 | 23 | ||
22 | #include <linux/iio/iio.h> | 24 | #include <linux/iio/iio.h> |
23 | #include <linux/iio/sysfs.h> | 25 | #include <linux/iio/sysfs.h> |
@@ -375,14 +377,138 @@ static const struct iio_info adf4350_info = { | |||
375 | .driver_module = THIS_MODULE, | 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 | static int adf4350_probe(struct spi_device *spi) | 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 | struct iio_dev *indio_dev; | 499 | struct iio_dev *indio_dev; |
382 | struct adf4350_state *st; | 500 | struct adf4350_state *st; |
383 | struct clk *clk = NULL; | 501 | struct clk *clk = NULL; |
384 | int ret; | 502 | int ret; |
385 | 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 | } | ||
511 | |||
386 | if (!pdata) { | 512 | if (!pdata) { |
387 | dev_warn(&spi->dev, "no platform data? using default\n"); | 513 | dev_warn(&spi->dev, "no platform data? using default\n"); |
388 | pdata = &default_pdata; | 514 | pdata = &default_pdata; |