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 ;
@@ -811,11 +844,21 @@ static long hmc7044_clk_round_rate(struct clk_hw *hw,
811
844
struct hmc7044_output * out = to_output (hw );
812
845
struct iio_dev * indio_dev = out -> indio_dev ;
813
846
struct hmc7044 * hmc = iio_priv (indio_dev );
847
+ struct hmc7044_chan_spec * ch ;
848
+ long rounded_rate ;
814
849
unsigned int div ;
815
850
816
- div = hmc7044_calc_out_div (hmc -> pll2_freq , rate );
851
+ ch = & hmc -> channels [out -> address ];
852
+
853
+ if (ch -> num == 14 ) {
854
+ div = hmc7044_calc_oscout_div (hmc -> vcxo_freq , rate );
855
+ rounded_rate = DIV_ROUND_CLOSEST (hmc -> vcxo_freq , div );
856
+ } else {
857
+ div = hmc7044_calc_out_div (hmc -> vcxo_freq , rate );
858
+ rounded_rate = DIV_ROUND_CLOSEST (hmc -> pll2_freq , div );
859
+ }
817
860
818
- return DIV_ROUND_CLOSEST ( hmc -> pll2_freq , div ) ;
861
+ return rounded_rate ;
819
862
}
820
863
821
864
static int hmc7044_clk_determine_rate (struct clk_hw * hw ,
@@ -824,17 +867,25 @@ static int hmc7044_clk_determine_rate(struct clk_hw *hw,
824
867
struct hmc7044_output * out = to_output (hw );
825
868
struct iio_dev * indio_dev = out -> indio_dev ;
826
869
struct hmc7044 * hmc = iio_priv (indio_dev );
870
+ struct hmc7044_chan_spec * ch ;
827
871
unsigned int div ;
828
872
829
- div = hmc7044_calc_out_div (hmc -> pll2_freq , req -> rate );
873
+ ch = & hmc -> channels [out -> address ];
874
+
875
+ if (ch -> num == 14 ) {
876
+ div = hmc7044_calc_oscout_div (hmc -> vcxo_freq , req -> rate );
877
+
878
+ req -> rate = DIV_ROUND_CLOSEST (hmc -> vcxo_freq , div );
879
+ } else {
880
+ div = hmc7044_calc_out_div (hmc -> pll2_freq , req -> rate );
830
881
831
- req -> rate = DIV_ROUND_CLOSEST (hmc -> pll2_freq , div );
882
+ req -> rate = DIV_ROUND_CLOSEST (hmc -> pll2_freq , div );
883
+ }
832
884
833
885
return 0 ;
834
886
}
835
887
836
- static int hmc7044_clk_set_rate (struct clk_hw * hw ,
837
- unsigned long rate ,
888
+ static int hmc7044_clk_set_rate (struct clk_hw * hw , unsigned long rate ,
838
889
unsigned long parent_rate )
839
890
{
840
891
return hmc7044_set_clk_attr (hw , IIO_CHAN_INFO_FREQUENCY , rate );
@@ -858,7 +909,7 @@ static int hmc7044_clk_register(struct iio_dev *indio_dev,
858
909
859
910
init .name = hmc -> clk_out_names [num ];
860
911
init .ops = & hmc7044_clk_ops ;
861
- init .flags = 0 ;
912
+ init .flags = CLK_GET_RATE_NOCACHE ;
862
913
init .parent_names = (parent_name ? & parent_name : NULL );
863
914
init .num_parents = (parent_name ? 1 : 0 );
864
915
@@ -1057,6 +1108,12 @@ static int hmc7044_setup(struct iio_dev *indio_dev)
1057
1108
ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_0 (i ), 0 );
1058
1109
if (ret )
1059
1110
return ret ;
1111
+
1112
+ if (i == 14 ) {
1113
+ ret = hmc7044_write (indio_dev , HMC7044_REG_OSCOUT_PATH , 0 );
1114
+ if (ret )
1115
+ return ret ;
1116
+ }
1060
1117
}
1061
1118
1062
1119
/* Load the configuration updates (provided by Analog Devices) */
@@ -1264,43 +1321,75 @@ static int hmc7044_setup(struct iio_dev *indio_dev)
1264
1321
if (chan -> num >= HMC7044_NUM_CHAN || chan -> disable )
1265
1322
continue ;
1266
1323
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 ;
1324
+ if (chan -> num < (HMC7044_NUM_CHAN - 1 )) {
1325
+ ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_1 (chan -> num ),
1326
+ HMC7044_DIV_LSB (chan -> divider ));
1327
+ if (ret )
1328
+ return ret ;
1329
+ ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_2 (chan -> num ),
1330
+ HMC7044_DIV_MSB (chan -> divider ));
1331
+ if (ret )
1332
+ return ret ;
1333
+ ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_8 (chan -> num ),
1334
+ HMC7044_DRIVER_MODE (chan -> driver_mode ) |
1335
+ HMC7044_DRIVER_Z_MODE (chan -> driver_impedance ) |
1336
+ (chan -> dynamic_driver_enable ?
1337
+ HMC7044_DYN_DRIVER_EN : 0 ) |
1338
+ (chan -> force_mute_enable ?
1339
+ HMC7044_FORCE_MUTE_EN : 0 ));
1340
+ if (ret )
1341
+ return ret ;
1342
+ ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_3 (chan -> num ),
1343
+ chan -> fine_delay & 0x1F );
1344
+ if (ret )
1345
+ return ret ;
1346
+ ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_4 (chan -> num ),
1347
+ chan -> coarse_delay & 0x1F );
1348
+ if (ret )
1349
+ return ret ;
1350
+ ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_7 (chan -> num ),
1351
+ chan -> out_mux_mode & 0x3 );
1352
+ if (ret )
1353
+ return ret ;
1354
+ ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_0 (chan -> num ),
1355
+ (chan -> start_up_mode_dynamic_enable ?
1356
+ HMC7044_START_UP_MODE_DYN_EN : 0 ) | BIT (4 ) |
1357
+ (chan -> high_performance_mode_dis ?
1358
+ 0 : HMC7044_HI_PERF_MODE ) | HMC7044_SYNC_EN |
1359
+ HMC7044_CH_EN );
1360
+ if (ret )
1361
+ return ret ;
1362
+ } else {
1363
+ if (hmc -> oscout_path_en ) {
1364
+ /* Make sure divider has acceptable value */
1365
+ if (chan -> divider != 1 && chan -> divider != 2 &&
1366
+ chan -> divider != 4 && chan -> divider != 8 )
1367
+ return - EINVAL ;
1368
+ ret = hmc7044_write (indio_dev , HMC7044_REG_OSCOUT_PATH ,
1369
+ HMC7044_OSCOUT_DIVIDER (chan -> divider <= 4 ? chan -> divider / 2 : 3 ) |
1370
+ HMC7044_CH_EN );
1371
+ if (ret )
1372
+ return ret ;
1373
+ }
1374
+
1375
+ if (hmc -> oscout0_driver_en ) {
1376
+ hmc7044_write (indio_dev , HMC7044_REG_OSCOUT_DRIVER_0 ,
1377
+ HMC7044_OSCOUT_DRIVER_MODE (chan -> driver_mode ) |
1378
+ HMC7044_OSCOUT_IMPEDANCE (chan -> driver_impedance ) |
1379
+ HMC7044_CH_EN );
1380
+ if (ret )
1381
+ return ret ;
1382
+ }
1383
+
1384
+ if (hmc -> oscout1_driver_en ) {
1385
+ hmc7044_write (indio_dev , HMC7044_REG_OSCOUT_DRIVER_1 ,
1386
+ HMC7044_OSCOUT_DRIVER_MODE (chan -> driver_mode ) |
1387
+ HMC7044_OSCOUT_IMPEDANCE (chan -> driver_impedance ) |
1388
+ HMC7044_CH_EN );
1389
+ if (ret )
1390
+ return ret ;
1391
+ }
1392
+ }
1304
1393
hmc -> iio_channels [i ].type = IIO_ALTVOLTAGE ;
1305
1394
hmc -> iio_channels [i ].output = 1 ;
1306
1395
hmc -> iio_channels [i ].indexed = 1 ;
@@ -1357,32 +1446,6 @@ static int hmc7044_setup(struct iio_dev *indio_dev)
1357
1446
hmc -> clk_data .clks = hmc -> clks ;
1358
1447
hmc -> clk_data .clk_num = HMC7044_NUM_CHAN ;
1359
1448
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
1449
ret = hmc7044_info (indio_dev );
1387
1450
if (ret )
1388
1451
return ret ;
@@ -1707,30 +1770,10 @@ static int hmc7044_parse_dt(struct device *dev,
1707
1770
hmc -> oscout_path_en =
1708
1771
of_property_read_bool (np , "adi,oscillator-output-path-enable" );
1709
1772
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
1773
hmc -> oscout0_driver_en = of_property_read_bool (np , "adi,oscillator-output0-driver-enable" );
1715
1774
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
1775
hmc -> oscout1_driver_en = of_property_read_bool (np , "adi,oscillator-output1-driver-enable" );
1725
1776
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
1777
hmc -> sysref_timer_div = 256 ;
1735
1778
of_property_read_u32 (np , "adi,sysref-timer-divider" ,
1736
1779
& hmc -> sysref_timer_div );
0 commit comments