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,23 @@ 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 % 2 )
459
+ div -- ;
460
+
461
+ return (div == 6 || div > 8 ) ? 8 : div ;
462
+ }
463
+
452
464
static int hmc7044_read_raw (struct iio_dev * indio_dev ,
453
465
struct iio_chan_spec const * chan ,
454
466
int * val ,
@@ -801,7 +813,17 @@ static long hmc7044_set_clk_attr(struct clk_hw *hw,
801
813
static unsigned long hmc7044_clk_recalc_rate (struct clk_hw * hw ,
802
814
unsigned long parent_rate )
803
815
{
804
- return hmc7044_get_clk_attr (hw , IIO_CHAN_INFO_FREQUENCY );
816
+ struct hmc7044_output * out = to_output (hw );
817
+ struct iio_dev * indio_dev = out -> indio_dev ;
818
+ struct hmc7044 * hmc = iio_priv (indio_dev );
819
+ struct hmc7044_chan_spec * ch ;
820
+
821
+ ch = & hmc -> channels [out -> address ];
822
+
823
+ if (ch -> num == 14 )
824
+ return (hmc -> vcxo_freq / ch -> divider );
825
+ else
826
+ return hmc7044_get_clk_attr (hw , IIO_CHAN_INFO_FREQUENCY );
805
827
}
806
828
807
829
static long hmc7044_clk_round_rate (struct clk_hw * hw ,
@@ -811,11 +833,21 @@ static long hmc7044_clk_round_rate(struct clk_hw *hw,
811
833
struct hmc7044_output * out = to_output (hw );
812
834
struct iio_dev * indio_dev = out -> indio_dev ;
813
835
struct hmc7044 * hmc = iio_priv (indio_dev );
836
+ struct hmc7044_chan_spec * ch ;
837
+ long rounded_rate ;
814
838
unsigned int div ;
815
839
816
- div = hmc7044_calc_out_div ( hmc -> pll2_freq , rate ) ;
840
+ ch = & hmc -> channels [ out -> address ] ;
817
841
818
- return DIV_ROUND_CLOSEST (hmc -> pll2_freq , div );
842
+ if (ch -> num == 14 ) {
843
+ div = hmc7044_calc_oscout_div (hmc -> vcxo_freq , rate );
844
+ rounded_rate = DIV_ROUND_CLOSEST (hmc -> vcxo_freq , div );
845
+ } else {
846
+ div = hmc7044_calc_out_div (hmc -> vcxo_freq , rate );
847
+ rounded_rate = DIV_ROUND_CLOSEST (hmc -> pll2_freq , div );
848
+ }
849
+
850
+ return rounded_rate ;
819
851
}
820
852
821
853
static int hmc7044_clk_determine_rate (struct clk_hw * hw ,
@@ -824,11 +856,20 @@ static int hmc7044_clk_determine_rate(struct clk_hw *hw,
824
856
struct hmc7044_output * out = to_output (hw );
825
857
struct iio_dev * indio_dev = out -> indio_dev ;
826
858
struct hmc7044 * hmc = iio_priv (indio_dev );
859
+ struct hmc7044_chan_spec * ch ;
827
860
unsigned int div ;
828
861
829
- div = hmc7044_calc_out_div ( hmc -> pll2_freq , req -> rate ) ;
862
+ ch = & hmc -> channels [ out -> address ] ;
830
863
831
- req -> rate = DIV_ROUND_CLOSEST (hmc -> pll2_freq , div );
864
+ if (ch -> num == 14 ) {
865
+ div = hmc7044_calc_oscout_div (hmc -> vcxo_freq , req -> rate );
866
+
867
+ req -> rate = DIV_ROUND_CLOSEST (hmc -> vcxo_freq , div );
868
+ } else {
869
+ div = hmc7044_calc_out_div (hmc -> pll2_freq , req -> rate );
870
+
871
+ req -> rate = DIV_ROUND_CLOSEST (hmc -> pll2_freq , div );
872
+ }
832
873
833
874
return 0 ;
834
875
}
@@ -837,7 +878,25 @@ static int hmc7044_clk_set_rate(struct clk_hw *hw,
837
878
unsigned long rate ,
838
879
unsigned long parent_rate )
839
880
{
840
- return hmc7044_set_clk_attr (hw , IIO_CHAN_INFO_FREQUENCY , rate );
881
+ struct hmc7044_output * out = to_output (hw );
882
+ struct iio_dev * indio_dev = out -> indio_dev ;
883
+ struct hmc7044 * hmc = iio_priv (indio_dev );
884
+ struct hmc7044_chan_spec * ch ;
885
+
886
+ ch = & hmc -> channels [out -> address ];
887
+
888
+ if (ch -> num == 14 ) {
889
+ ch -> divider = hmc7044_calc_oscout_div (hmc -> vcxo_freq , rate );
890
+ mutex_lock (& hmc -> lock );
891
+ hmc7044_write (indio_dev , HMC7044_REG_OSCOUT_PATH ,
892
+ HMC7044_OSCOUT_DIVIDER (ch -> divider <= 4 ? ch -> divider / 2 : 3 ) |
893
+ hmc -> oscout_path_en );
894
+ mutex_unlock (& hmc -> lock );
895
+
896
+ return 0 ;
897
+ } else {
898
+ return hmc7044_set_clk_attr (hw , IIO_CHAN_INFO_FREQUENCY , rate );
899
+ }
841
900
}
842
901
843
902
static const struct clk_ops hmc7044_clk_ops = {
@@ -1057,6 +1116,12 @@ static int hmc7044_setup(struct iio_dev *indio_dev)
1057
1116
ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_0 (i ), 0 );
1058
1117
if (ret )
1059
1118
return ret ;
1119
+
1120
+ if (i == 14 ) {
1121
+ ret = hmc7044_write (indio_dev , HMC7044_REG_OSCOUT_PATH , 0 );
1122
+ if (ret )
1123
+ return ret ;
1124
+ }
1060
1125
}
1061
1126
1062
1127
/* Load the configuration updates (provided by Analog Devices) */
@@ -1264,52 +1329,84 @@ static int hmc7044_setup(struct iio_dev *indio_dev)
1264
1329
if (chan -> num >= HMC7044_NUM_CHAN || chan -> disable )
1265
1330
continue ;
1266
1331
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 ;
1304
- hmc -> iio_channels [i ].type = IIO_ALTVOLTAGE ;
1305
- hmc -> iio_channels [i ].output = 1 ;
1306
- hmc -> iio_channels [i ].indexed = 1 ;
1307
- hmc -> iio_channels [i ].channel = chan -> num ;
1308
- hmc -> iio_channels [i ].address = i ;
1309
- hmc -> iio_channels [i ].extend_name = chan -> extended_name ;
1310
- hmc -> iio_channels [i ].info_mask_separate =
1311
- BIT (IIO_CHAN_INFO_FREQUENCY ) |
1312
- BIT (IIO_CHAN_INFO_PHASE );
1332
+ if (chan -> num < (HMC7044_NUM_CHAN - 1 )) {
1333
+ ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_1 (chan -> num ),
1334
+ HMC7044_DIV_LSB (chan -> divider ));
1335
+ if (ret )
1336
+ return ret ;
1337
+ ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_2 (chan -> num ),
1338
+ HMC7044_DIV_MSB (chan -> divider ));
1339
+ if (ret )
1340
+ return ret ;
1341
+ ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_8 (chan -> num ),
1342
+ HMC7044_DRIVER_MODE (chan -> driver_mode ) |
1343
+ HMC7044_DRIVER_Z_MODE (chan -> driver_impedance ) |
1344
+ (chan -> dynamic_driver_enable ?
1345
+ HMC7044_DYN_DRIVER_EN : 0 ) |
1346
+ (chan -> force_mute_enable ?
1347
+ HMC7044_FORCE_MUTE_EN : 0 ));
1348
+ if (ret )
1349
+ return ret ;
1350
+ ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_3 (chan -> num ),
1351
+ chan -> fine_delay & 0x1F );
1352
+ if (ret )
1353
+ return ret ;
1354
+ ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_4 (chan -> num ),
1355
+ chan -> coarse_delay & 0x1F );
1356
+ if (ret )
1357
+ return ret ;
1358
+ ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_7 (chan -> num ),
1359
+ chan -> out_mux_mode & 0x3 );
1360
+ if (ret )
1361
+ return ret ;
1362
+ ret = hmc7044_write (indio_dev , HMC7044_REG_CH_OUT_CRTL_0 (chan -> num ),
1363
+ (chan -> start_up_mode_dynamic_enable ?
1364
+ HMC7044_START_UP_MODE_DYN_EN : 0 ) | BIT (4 ) |
1365
+ (chan -> high_performance_mode_dis ?
1366
+ 0 : HMC7044_HI_PERF_MODE ) | HMC7044_SYNC_EN |
1367
+ HMC7044_CH_EN );
1368
+ if (ret )
1369
+ return ret ;
1370
+ hmc -> iio_channels [i ].type = IIO_ALTVOLTAGE ;
1371
+ hmc -> iio_channels [i ].output = 1 ;
1372
+ hmc -> iio_channels [i ].indexed = 1 ;
1373
+ hmc -> iio_channels [i ].channel = chan -> num ;
1374
+ hmc -> iio_channels [i ].address = i ;
1375
+ hmc -> iio_channels [i ].extend_name = chan -> extended_name ;
1376
+ hmc -> iio_channels [i ].info_mask_separate =
1377
+ BIT (IIO_CHAN_INFO_FREQUENCY ) |
1378
+ BIT (IIO_CHAN_INFO_PHASE );
1379
+ } else {
1380
+ if (hmc -> oscout_path_en ) {
1381
+ /* Make sure divider has acceptable value */
1382
+ if (chan -> divider != 1 && chan -> divider != 2 &&
1383
+ chan -> divider != 4 && chan -> divider != 8 )
1384
+ return - EINVAL ;
1385
+ ret = hmc7044_write (indio_dev , HMC7044_REG_OSCOUT_PATH ,
1386
+ HMC7044_OSCOUT_DIVIDER (chan -> divider <= 4 ? chan -> divider / 2 : 3 ) |
1387
+ HMC7044_CH_EN );
1388
+ if (ret )
1389
+ return ret ;
1390
+ }
1391
+
1392
+ if (hmc -> oscout0_driver_en ) {
1393
+ hmc7044_write (indio_dev , HMC7044_REG_OSCOUT_DRIVER_0 ,
1394
+ HMC7044_OSCOUT_DRIVER_MODE (chan -> driver_mode ) |
1395
+ HMC7044_OSCOUT_IMPEDANCE (chan -> driver_impedance ) |
1396
+ HMC7044_CH_EN );
1397
+ if (ret )
1398
+ return ret ;
1399
+ }
1400
+
1401
+ if (hmc -> oscout1_driver_en ) {
1402
+ hmc7044_write (indio_dev , HMC7044_REG_OSCOUT_DRIVER_1 ,
1403
+ HMC7044_OSCOUT_DRIVER_MODE (chan -> driver_mode ) |
1404
+ HMC7044_OSCOUT_IMPEDANCE (chan -> driver_impedance ) |
1405
+ HMC7044_CH_EN );
1406
+ if (ret )
1407
+ return ret ;
1408
+ }
1409
+ }
1313
1410
}
1314
1411
mdelay (10 );
1315
1412
@@ -1357,32 +1454,6 @@ static int hmc7044_setup(struct iio_dev *indio_dev)
1357
1454
hmc -> clk_data .clks = hmc -> clks ;
1358
1455
hmc -> clk_data .clk_num = HMC7044_NUM_CHAN ;
1359
1456
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
1457
ret = hmc7044_info (indio_dev );
1387
1458
if (ret )
1388
1459
return ret ;
@@ -1707,30 +1778,10 @@ static int hmc7044_parse_dt(struct device *dev,
1707
1778
hmc -> oscout_path_en =
1708
1779
of_property_read_bool (np , "adi,oscillator-output-path-enable" );
1709
1780
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
1781
hmc -> oscout0_driver_en = of_property_read_bool (np , "adi,oscillator-output0-driver-enable" );
1715
1782
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
1783
hmc -> oscout1_driver_en = of_property_read_bool (np , "adi,oscillator-output1-driver-enable" );
1725
1784
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
1785
hmc -> sysref_timer_div = 256 ;
1735
1786
of_property_read_u32 (np , "adi,sysref-timer-divider" ,
1736
1787
& hmc -> sysref_timer_div );
0 commit comments