214
214
#define HMC7044_DYN_DRIVER_EN BIT(5)
215
215
#define HMC7044_FORCE_MUTE_EN BIT(7)
216
216
217
- #define HMC7044_NUM_CHAN 14
217
+ #define HMC7044_NUM_CHAN 15
218
218
219
219
#define HMC7044_LOW_VCO_MIN 2150000
220
220
#define HMC7044_LOW_VCO_MAX 2880000
@@ -309,11 +309,6 @@ struct hmc7044 {
309
309
bool oscout_path_en ;
310
310
bool oscout0_driver_en ;
311
311
bool oscout1_driver_en ;
312
- u32 oscout_divider_ratio ;
313
- u32 oscout0_driver_mode ;
314
- u32 oscout1_driver_mode ;
315
- u32 oscout0_driver_impedance ;
316
- u32 oscout1_driver_impedance ;
317
312
unsigned int sync_pin_mode ;
318
313
unsigned int pulse_gen_mode ;
319
314
unsigned int in_buf_mode [5 ];
@@ -449,6 +444,26 @@ static unsigned int hmc7044_calc_out_div(unsigned long parent_rate,
449
444
return div ;
450
445
}
451
446
447
+ static unsigned int hmc7044_calc_oscout_div (unsigned long parent_rate ,
448
+ unsigned long rate )
449
+ {
450
+ unsigned int div ;
451
+
452
+ div = DIV_ROUND_CLOSEST (parent_rate , rate );
453
+
454
+ /* Supported divide ratios are 1, 2, 4, and 8 */
455
+ if (div == 1 || div == 2 || div == 4 || div == 8 )
456
+ return div ;
457
+
458
+ if (div == 0 )
459
+ return 1 ;
460
+
461
+ if (div % 2 )
462
+ div -- ;
463
+
464
+ return (div == 6 || div > 8 ) ? 8 : div ;
465
+ }
466
+
452
467
static int hmc7044_read_raw (struct iio_dev * indio_dev ,
453
468
struct iio_chan_spec const * chan ,
454
469
int * val ,
@@ -466,13 +481,20 @@ static int hmc7044_read_raw(struct iio_dev *indio_dev,
466
481
467
482
switch (mask ) {
468
483
case IIO_CHAN_INFO_FREQUENCY :
469
- * val = hmc -> pll2_freq / ch -> divider ;
484
+ if (ch -> num == 14 )
485
+ * val = hmc -> vcxo_freq / ch -> divider ;
486
+ else
487
+ * val = hmc -> pll2_freq / ch -> divider ;
470
488
return IIO_VAL_INT ;
471
489
case IIO_CHAN_INFO_PHASE :
472
- hmc7044_read (indio_dev , HMC7044_REG_CH_OUT_CRTL_4 (ch -> num ),
473
- & tmp );
474
- tmp &= 0x1F ;
475
- code = DIV_ROUND_CLOSEST (tmp * 3141592 , ch -> divider );
490
+ if (ch -> num == 14 ) {
491
+ code = 0 ;
492
+ } else {
493
+ hmc7044_read (indio_dev , HMC7044_REG_CH_OUT_CRTL_4 (ch -> num ),
494
+ & tmp );
495
+ tmp &= 0x1F ;
496
+ code = DIV_ROUND_CLOSEST (tmp * 3141592 , ch -> divider );
497
+ }
476
498
* val = code / 1000000 ;
477
499
* val2 = code % 1000000 ;
478
500
return IIO_VAL_INT_PLUS_MICRO ;
@@ -498,22 +520,33 @@ static int hmc7044_write_raw(struct iio_dev *indio_dev,
498
520
499
521
switch (mask ) {
500
522
case IIO_CHAN_INFO_FREQUENCY :
501
- ch -> divider = hmc7044_calc_out_div (hmc -> pll2_freq , val );
502
- mutex_lock (& hmc -> lock );
503
- hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_1 (ch -> num ),
504
- HMC7044_DIV_LSB (ch -> divider ));
505
- hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_2 (ch -> num ),
506
- HMC7044_DIV_MSB (ch -> divider ));
507
- mutex_unlock (& hmc -> lock );
523
+ if (ch -> num == 14 ) {
524
+ ch -> divider = hmc7044_calc_oscout_div (hmc -> vcxo_freq , val );
525
+ mutex_lock (& hmc -> lock );
526
+ hmc7044_write (indio_dev , HMC7044_REG_OSCOUT_PATH ,
527
+ HMC7044_OSCOUT_DIVIDER (ch -> divider <= 4 ? ch -> divider / 2 : 3 ) |
528
+ hmc -> oscout_path_en );
529
+ mutex_unlock (& hmc -> lock );
530
+ } else {
531
+ ch -> divider = hmc7044_calc_out_div (hmc -> pll2_freq , val );
532
+ mutex_lock (& hmc -> lock );
533
+ hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_1 (ch -> num ),
534
+ HMC7044_DIV_LSB (ch -> divider ));
535
+ hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_2 (ch -> num ),
536
+ HMC7044_DIV_MSB (ch -> divider ));
537
+ mutex_unlock (& hmc -> lock );
538
+ }
508
539
break ;
509
540
case IIO_CHAN_INFO_PHASE :
510
- mutex_lock (& hmc -> lock );
511
- code = val * 1000000 + val2 % 1000000 ;
512
- tmp = DIV_ROUND_CLOSEST (code * ch -> divider , 3141592 );
513
- tmp = clamp_t (unsigned int , tmp , 0 , 17 );
514
- hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_4 (ch -> num ),
515
- tmp );
516
- mutex_unlock (& hmc -> lock );
541
+ if (ch -> num != 14 ) {
542
+ mutex_lock (& hmc -> lock );
543
+ code = val * 1000000 + val2 % 1000000 ;
544
+ tmp = DIV_ROUND_CLOSEST (code * ch -> divider , 3141592 );
545
+ tmp = clamp_t (unsigned int , tmp , 0 , 17 );
546
+ hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_4 (ch -> num ),
547
+ tmp );
548
+ mutex_unlock (& hmc -> lock );
549
+ }
517
550
break ;
518
551
default :
519
552
return - EINVAL ;
@@ -801,6 +834,13 @@ static long hmc7044_set_clk_attr(struct clk_hw *hw,
801
834
static unsigned long hmc7044_clk_recalc_rate (struct clk_hw * hw ,
802
835
unsigned long parent_rate )
803
836
{
837
+ struct hmc7044_output * out = to_output (hw );
838
+ struct iio_dev * indio_dev = out -> indio_dev ;
839
+ struct hmc7044 * hmc = iio_priv (indio_dev );
840
+ struct hmc7044_chan_spec * ch ;
841
+
842
+ ch = & hmc -> channels [out -> address ];
843
+
804
844
return hmc7044_get_clk_attr (hw , IIO_CHAN_INFO_FREQUENCY );
805
845
}
806
846
@@ -811,11 +851,21 @@ static long hmc7044_clk_round_rate(struct clk_hw *hw,
811
851
struct hmc7044_output * out = to_output (hw );
812
852
struct iio_dev * indio_dev = out -> indio_dev ;
813
853
struct hmc7044 * hmc = iio_priv (indio_dev );
854
+ struct hmc7044_chan_spec * ch ;
855
+ long rounded_rate ;
814
856
unsigned int div ;
815
857
816
- div = hmc7044_calc_out_div ( hmc -> pll2_freq , rate ) ;
858
+ ch = & hmc -> channels [ out -> address ] ;
817
859
818
- return DIV_ROUND_CLOSEST (hmc -> pll2_freq , div );
860
+ if (ch -> num == 14 ) {
861
+ div = hmc7044_calc_oscout_div (hmc -> vcxo_freq , rate );
862
+ rounded_rate = DIV_ROUND_CLOSEST (hmc -> vcxo_freq , div );
863
+ } else {
864
+ div = hmc7044_calc_out_div (hmc -> vcxo_freq , rate );
865
+ rounded_rate = DIV_ROUND_CLOSEST (hmc -> pll2_freq , div );
866
+ }
867
+
868
+ return rounded_rate ;
819
869
}
820
870
821
871
static int hmc7044_clk_determine_rate (struct clk_hw * hw ,
@@ -824,11 +874,20 @@ static int hmc7044_clk_determine_rate(struct clk_hw *hw,
824
874
struct hmc7044_output * out = to_output (hw );
825
875
struct iio_dev * indio_dev = out -> indio_dev ;
826
876
struct hmc7044 * hmc = iio_priv (indio_dev );
877
+ struct hmc7044_chan_spec * ch ;
827
878
unsigned int div ;
828
879
829
- div = hmc7044_calc_out_div (hmc -> pll2_freq , req -> rate );
880
+ ch = & hmc -> channels [out -> address ];
881
+
882
+ if (ch -> num == 14 ) {
883
+ div = hmc7044_calc_oscout_div (hmc -> vcxo_freq , req -> rate );
884
+
885
+ req -> rate = DIV_ROUND_CLOSEST (hmc -> vcxo_freq , div );
886
+ } else {
887
+ div = hmc7044_calc_out_div (hmc -> pll2_freq , req -> rate );
830
888
831
- req -> rate = DIV_ROUND_CLOSEST (hmc -> pll2_freq , div );
889
+ req -> rate = DIV_ROUND_CLOSEST (hmc -> pll2_freq , div );
890
+ }
832
891
833
892
return 0 ;
834
893
}
@@ -837,6 +896,13 @@ static int hmc7044_clk_set_rate(struct clk_hw *hw,
837
896
unsigned long rate ,
838
897
unsigned long parent_rate )
839
898
{
899
+ struct hmc7044_output * out = to_output (hw );
900
+ struct iio_dev * indio_dev = out -> indio_dev ;
901
+ struct hmc7044 * hmc = iio_priv (indio_dev );
902
+ struct hmc7044_chan_spec * ch ;
903
+
904
+ ch = & hmc -> channels [out -> address ];
905
+
840
906
return hmc7044_set_clk_attr (hw , IIO_CHAN_INFO_FREQUENCY , rate );
841
907
}
842
908
@@ -858,7 +924,7 @@ static int hmc7044_clk_register(struct iio_dev *indio_dev,
858
924
859
925
init .name = hmc -> clk_out_names [num ];
860
926
init .ops = & hmc7044_clk_ops ;
861
- init .flags = 0 ;
927
+ init .flags = CLK_GET_RATE_NOCACHE ;
862
928
init .parent_names = (parent_name ? & parent_name : NULL );
863
929
init .num_parents = (parent_name ? 1 : 0 );
864
930
@@ -1057,6 +1123,12 @@ static int hmc7044_setup(struct iio_dev *indio_dev)
1057
1123
ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_0 (i ), 0 );
1058
1124
if (ret )
1059
1125
return ret ;
1126
+
1127
+ if (i == 14 ) {
1128
+ ret = hmc7044_write (indio_dev , HMC7044_REG_OSCOUT_PATH , 0 );
1129
+ if (ret )
1130
+ return ret ;
1131
+ }
1060
1132
}
1061
1133
1062
1134
/* Load the configuration updates (provided by Analog Devices) */
@@ -1264,43 +1336,75 @@ static int hmc7044_setup(struct iio_dev *indio_dev)
1264
1336
if (chan -> num >= HMC7044_NUM_CHAN || chan -> disable )
1265
1337
continue ;
1266
1338
1267
- ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_1 (chan -> num ),
1268
- HMC7044_DIV_LSB (chan -> divider ));
1269
- if (ret )
1270
- return ret ;
1271
- ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_2 (chan -> num ),
1272
- HMC7044_DIV_MSB (chan -> divider ));
1273
- if (ret )
1274
- return ret ;
1275
- ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_8 (chan -> num ),
1276
- HMC7044_DRIVER_MODE (chan -> driver_mode ) |
1277
- HMC7044_DRIVER_Z_MODE (chan -> driver_impedance ) |
1278
- (chan -> dynamic_driver_enable ?
1279
- HMC7044_DYN_DRIVER_EN : 0 ) |
1280
- (chan -> force_mute_enable ?
1281
- HMC7044_FORCE_MUTE_EN : 0 ));
1282
- if (ret )
1283
- return ret ;
1284
- ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_3 (chan -> num ),
1285
- chan -> fine_delay & 0x1F );
1286
- if (ret )
1287
- return ret ;
1288
- ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_4 (chan -> num ),
1289
- chan -> coarse_delay & 0x1F );
1290
- if (ret )
1291
- return ret ;
1292
- ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_7 (chan -> num ),
1293
- chan -> out_mux_mode & 0x3 );
1294
- if (ret )
1295
- return ret ;
1296
- ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_0 (chan -> num ),
1297
- (chan -> start_up_mode_dynamic_enable ?
1298
- HMC7044_START_UP_MODE_DYN_EN : 0 ) | BIT (4 ) |
1299
- (chan -> high_performance_mode_dis ?
1300
- 0 : HMC7044_HI_PERF_MODE ) | HMC7044_SYNC_EN |
1301
- HMC7044_CH_EN );
1302
- if (ret )
1303
- return ret ;
1339
+ if (chan -> num < (HMC7044_NUM_CHAN - 1 )) {
1340
+ ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_1 (chan -> num ),
1341
+ HMC7044_DIV_LSB (chan -> divider ));
1342
+ if (ret )
1343
+ return ret ;
1344
+ ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_2 (chan -> num ),
1345
+ HMC7044_DIV_MSB (chan -> divider ));
1346
+ if (ret )
1347
+ return ret ;
1348
+ ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_8 (chan -> num ),
1349
+ HMC7044_DRIVER_MODE (chan -> driver_mode ) |
1350
+ HMC7044_DRIVER_Z_MODE (chan -> driver_impedance ) |
1351
+ (chan -> dynamic_driver_enable ?
1352
+ HMC7044_DYN_DRIVER_EN : 0 ) |
1353
+ (chan -> force_mute_enable ?
1354
+ HMC7044_FORCE_MUTE_EN : 0 ));
1355
+ if (ret )
1356
+ return ret ;
1357
+ ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_3 (chan -> num ),
1358
+ chan -> fine_delay & 0x1F );
1359
+ if (ret )
1360
+ return ret ;
1361
+ ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_4 (chan -> num ),
1362
+ chan -> coarse_delay & 0x1F );
1363
+ if (ret )
1364
+ return ret ;
1365
+ ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_7 (chan -> num ),
1366
+ chan -> out_mux_mode & 0x3 );
1367
+ if (ret )
1368
+ return ret ;
1369
+ ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_0 (chan -> num ),
1370
+ (chan -> start_up_mode_dynamic_enable ?
1371
+ HMC7044_START_UP_MODE_DYN_EN : 0 ) | BIT (4 ) |
1372
+ (chan -> high_performance_mode_dis ?
1373
+ 0 : HMC7044_HI_PERF_MODE ) | HMC7044_SYNC_EN |
1374
+ HMC7044_CH_EN );
1375
+ if (ret )
1376
+ return ret ;
1377
+ } else {
1378
+ if (hmc -> oscout_path_en ) {
1379
+ /* Make sure divider has acceptable value */
1380
+ if (chan -> divider != 1 && chan -> divider != 2 &&
1381
+ chan -> divider != 4 && chan -> divider != 8 )
1382
+ return - EINVAL ;
1383
+ ret = hmc7044_write (indio_dev , HMC7044_REG_OSCOUT_PATH ,
1384
+ HMC7044_OSCOUT_DIVIDER (chan -> divider <= 4 ? chan -> divider / 2 : 3 ) |
1385
+ HMC7044_CH_EN );
1386
+ if (ret )
1387
+ return ret ;
1388
+ }
1389
+
1390
+ if (hmc -> oscout0_driver_en ) {
1391
+ hmc7044_write (indio_dev , HMC7044_REG_OSCOUT_DRIVER_0 ,
1392
+ HMC7044_OSCOUT_DRIVER_MODE (chan -> driver_mode ) |
1393
+ HMC7044_OSCOUT_IMPEDANCE (chan -> driver_impedance ) |
1394
+ HMC7044_CH_EN );
1395
+ if (ret )
1396
+ return ret ;
1397
+ }
1398
+
1399
+ if (hmc -> oscout1_driver_en ) {
1400
+ hmc7044_write (indio_dev , HMC7044_REG_OSCOUT_DRIVER_1 ,
1401
+ HMC7044_OSCOUT_DRIVER_MODE (chan -> driver_mode ) |
1402
+ HMC7044_OSCOUT_IMPEDANCE (chan -> driver_impedance ) |
1403
+ HMC7044_CH_EN );
1404
+ if (ret )
1405
+ return ret ;
1406
+ }
1407
+ }
1304
1408
hmc -> iio_channels [i ].type = IIO_ALTVOLTAGE ;
1305
1409
hmc -> iio_channels [i ].output = 1 ;
1306
1410
hmc -> iio_channels [i ].indexed = 1 ;
@@ -1357,32 +1461,6 @@ static int hmc7044_setup(struct iio_dev *indio_dev)
1357
1461
hmc -> clk_data .clks = hmc -> clks ;
1358
1462
hmc -> clk_data .clk_num = HMC7044_NUM_CHAN ;
1359
1463
1360
- if (hmc -> oscout_path_en ) {
1361
- ret = hmc7044_write (indio_dev , HMC7044_REG_OSCOUT_PATH ,
1362
- HMC7044_OSCOUT_DIVIDER (hmc -> oscout_divider_ratio ) |
1363
- hmc -> oscout_path_en );
1364
- if (ret )
1365
- return ret ;
1366
- }
1367
-
1368
- if (hmc -> oscout0_driver_en ) {
1369
- hmc7044_write (indio_dev , HMC7044_REG_OSCOUT_DRIVER_0 ,
1370
- HMC7044_OSCOUT_DRIVER_MODE (hmc -> oscout1_driver_mode ) |
1371
- HMC7044_OSCOUT_IMPEDANCE (hmc -> oscout1_driver_impedance ) |
1372
- hmc -> oscout1_driver_en );
1373
- if (ret )
1374
- return ret ;
1375
- }
1376
-
1377
- if (hmc -> oscout1_driver_en ) {
1378
- hmc7044_write (indio_dev , HMC7044_REG_OSCOUT_DRIVER_1 ,
1379
- HMC7044_OSCOUT_DRIVER_MODE (hmc -> oscout1_driver_mode ) |
1380
- HMC7044_OSCOUT_IMPEDANCE (hmc -> oscout1_driver_impedance ) |
1381
- hmc -> oscout1_driver_en );
1382
- if (ret )
1383
- return ret ;
1384
- }
1385
-
1386
1464
ret = hmc7044_info (indio_dev );
1387
1465
if (ret )
1388
1466
return ret ;
@@ -1707,30 +1785,10 @@ static int hmc7044_parse_dt(struct device *dev,
1707
1785
hmc -> oscout_path_en =
1708
1786
of_property_read_bool (np , "adi,oscillator-output-path-enable" );
1709
1787
1710
- hmc -> oscout_divider_ratio = HMC7044_DIVIDER_RATIO_1 ;
1711
- of_property_read_u32 (np , "adi,oscillator-output-divider-ratio" ,
1712
- & hmc -> oscout_divider_ratio );
1713
-
1714
1788
hmc -> oscout0_driver_en = of_property_read_bool (np , "adi,oscillator-output0-driver-enable" );
1715
1789
1716
- hmc -> oscout0_driver_mode = HMC7044_DRIVER_MODE_CML ;
1717
- of_property_read_u32 (np , "adi,oscillator-output0-driver-mode" ,
1718
- & hmc -> oscout0_driver_mode );
1719
-
1720
- hmc -> oscout0_driver_impedance = HMC7044_DRIVER_IMPEDANCE_DISABLE ;
1721
- of_property_read_u32 (np , "adi,oscillator-output0-driver-impedance" ,
1722
- & hmc -> oscout0_driver_impedance );
1723
-
1724
1790
hmc -> oscout1_driver_en = of_property_read_bool (np , "adi,oscillator-output1-driver-enable" );
1725
1791
1726
- hmc -> oscout1_driver_mode = HMC7044_DRIVER_MODE_CML ;
1727
- of_property_read_u32 (np , "adi,oscillator-output1-driver-mode" ,
1728
- & hmc -> oscout1_driver_mode );
1729
-
1730
- hmc -> oscout1_driver_impedance = HMC7044_DRIVER_IMPEDANCE_DISABLE ;
1731
- of_property_read_u32 (np , "adi,oscillator-output1-driver-impedance" ,
1732
- & hmc -> oscout1_driver_impedance );
1733
-
1734
1792
hmc -> sysref_timer_div = 256 ;
1735
1793
of_property_read_u32 (np , "adi,sysref-timer-divider" ,
1736
1794
& hmc -> sysref_timer_div );
0 commit comments