@@ -21,188 +21,66 @@ static int ad9088_jesd204_post_setup_stage2(struct jesd204_dev *jdev,
2121static int ad9088_jesd204_post_setup_stage3 (struct jesd204_dev * jdev ,
2222 enum jesd204_state_op_reason reason );
2323
24- void adi_ad9088_hal_add_128 (u64 ah , uint64_t al , uint64_t bh , uint64_t bl ,
25- u64 * hi , uint64_t * lo )
26- {
27- u64 rl = al + bl , rh = ah + bh ;
28-
29- if (rl < al )
30- rh ++ ;
31- * lo = rl ;
32- * hi = rh ;
33- }
34-
35- void adi_ad9088_hal_sub_128 (u64 ah , uint64_t al , uint64_t bh , uint64_t bl ,
36- u64 * hi , uint64_t * lo )
37- {
38- u64 rl , rh ;
39-
40- if (bl <= al ) {
41- rl = al - bl ;
42- rh = ah - bh ;
43- } else {
44- rl = bl - al - 1 ;
45- rl = 0xffffffffffffffffull - rl ;
46- ah -- ;
47- rh = ah - bh ;
48- }
49- * lo = rl ;
50- * hi = rh ;
51- }
52-
53- void adi_ad9088_hal_mult_128 (u64 a , uint64_t b , uint64_t * hi , uint64_t * lo )
54- {
55- u64 ah = a >> 32 , al = a & 0xffffffff , bh = b >> 32 ,
56- bl = b & 0xffffffff , rh = ah * bh , rl = al * bl , rm1 = ah * bl ,
57- rm2 = al * bh , rm1h = rm1 >> 32 , rm2h = rm2 >> 32 ,
58- rm1l = rm1 & 0xffffffff , rm2l = rm2 & 0xffffffff ,
59- rmh = rm1h + rm2h , rml = rm1l + rm2l ,
60- c = ((rl >> 32 ) + rml ) >> 32 ;
61- rl = rl + (rml << 32 );
62- rh = rh + rmh + c ;
63- * lo = rl ;
64- * hi = rh ;
65- }
66-
67- void adi_ad9088_hal_lshift_128 (u64 * hi , uint64_t * lo )
68- {
69- * hi <<= 1 ;
70- if (* lo & 0x8000000000000000ull )
71- * hi |= 1ull ;
72- * lo <<= 1 ;
73- }
74-
75- void adi_ad9088_hal_rshift_128 (u64 * hi , uint64_t * lo )
76- {
77- * lo >>= 1 ;
78- if (* hi & 1ull )
79- * lo |= 0x8000000000000000ull ;
80- * hi >>= 1 ;
81- }
82-
83- void adi_ad9088_hal_div_128 (u64 a_hi , uint64_t a_lo , uint64_t b_hi ,
84- u64 b_lo , uint64_t * hi , uint64_t * lo )
85- {
86- u64 remain_lo = a_lo , remain_hi = a_hi , part1_lo = b_lo ,
87- part1_hi = b_hi ;
88- u64 result_lo = 0 , result_hi = 0 , mask_lo = 1 , mask_hi = 0 ;
89-
90- while (!(part1_hi & 0x8000000000000000ull )) {
91- adi_ad9088_hal_lshift_128 (& part1_hi , & part1_lo );
92- adi_ad9088_hal_lshift_128 (& mask_hi , & mask_lo );
93- }
94-
95- do {
96- if ((remain_hi > part1_hi ) ||
97- ((remain_hi == part1_hi ) && (remain_lo >= part1_lo ))) {
98- adi_ad9088_hal_sub_128 (remain_hi , remain_lo , part1_hi ,
99- part1_lo , & remain_hi ,
100- & remain_lo );
101- adi_ad9088_hal_add_128 (result_hi , result_lo , mask_hi ,
102- mask_lo , & result_hi , & result_lo );
103- }
104- adi_ad9088_hal_rshift_128 (& part1_hi , & part1_lo );
105- adi_ad9088_hal_rshift_128 (& mask_hi , & mask_lo );
106- } while ((mask_hi != 0 ) || (mask_lo != 0 ));
107- * lo = result_lo ;
108- * hi = result_hi ;
109- }
110-
11124int32_t adi_ad9088_calc_nco_ftw (adi_apollo_device_t * device ,
112- u64 freq , int64_t nco_shift ,
113- uint64_t * ftw )
25+ u64 freq , s64 nco_shift , u32 bits ,
26+ u64 * ftw , u64 * frac_a , u64 * frac_b )
11427{
115- u64 hi , lo ;
28+ bool neg = false;
29+ int ret ;
11630
117- if (!freq )
31+ pr_debug ("adi_ad9088_calc_nco_ftw: freq=%llu, nco_shift=%lld, bits=%u\n" ,
32+ freq , nco_shift , bits );
33+
34+ if (!freq || !bits || (bits > 64 ) || !ftw || !frac_a || !frac_b )
11835 return - EINVAL ;
11936
12037 nco_shift = clamp_t (int64_t , nco_shift , - (freq >> 1 ), freq >> 1 );
12138
122- if (nco_shift >= 0 ) {
123- adi_ad9088_hal_mult_128 (281474976710656ull , nco_shift , & hi ,
124- & lo );
125- adi_ad9088_hal_add_128 (hi , lo , 0 , freq >> 1 , & hi , & lo );
126- adi_ad9088_hal_div_128 (hi , lo , 0 , freq , & hi , ftw );
127- } else {
128- adi_ad9088_hal_mult_128 (281474976710656ull , - nco_shift , & hi ,
129- & lo );
130- adi_ad9088_hal_add_128 (hi , lo , 0 , freq >> 1 , & hi , & lo );
131- adi_ad9088_hal_div_128 (hi , lo , 0 , freq , & hi , ftw );
132- * ftw = 281474976710656ull - * ftw ;
133- }
134-
135- return API_CMS_ERROR_OK ;
136- }
137-
138- int32_t adi_ad9088_calc_nco_freq (adi_apollo_device_t * device ,
139- u64 freq ,
140- u64 ftw , int64_t * nco_shift )
141- {
142- u64 hi , lo ;
143- bool neg = false;
144-
145- if (!freq )
146- return - EINVAL ;
147-
148- if (ftw > 140737488355328ull ) {
149- ftw = 0x1000000000000 - ftw ;
39+ if (nco_shift < 0 ) {
40+ nco_shift = - nco_shift ;
15041 neg = true;
15142 }
15243
153- adi_ad9088_hal_mult_128 (freq , ftw , & hi , & lo );
154- adi_ad9088_hal_add_128 (hi , lo , 0 , 281474976710656ull / 2 , & hi , & lo );
155- adi_ad9088_hal_div_128 (hi , lo , 0 , 281474976710656ull , & hi , nco_shift );
44+ ret = adi_api_utils_ratio_decomposition (nco_shift , freq , bits , ftw , frac_a , frac_b );
45+ if (ret ) {
46+ pr_err ("Error in ratio decomposition: %d\n" , ret );
47+ return ret ;
48+ }
49+ /* frac_a and fact_b are 24-bit registers */
50+ while (* frac_a >= (1 << 24 ) || * frac_b >= (1 << 24 )) {
51+ * frac_a >>= 1 ;
52+ * frac_b >>= 1 ;
53+ };
15654
15755 if (neg )
158- * nco_shift *= -1 ;
56+ * ftw = ( 1ULL << bits ) - * ftw ;
15957
16058 return API_CMS_ERROR_OK ;
16159}
16260
163- int32_t adi_ad9088_calc_nco_ftw32 (adi_apollo_device_t * device ,
164- u64 freq , int64_t nco_shift ,
165- uint64_t * ftw )
166- {
167- u64 hi , lo ;
168-
169- if (!freq )
170- return - EINVAL ;
171-
172- nco_shift = clamp_t (int64_t , nco_shift , - (freq >> 1 ), freq >> 1 );
173-
174- if (nco_shift >= 0 ) {
175- adi_ad9088_hal_mult_128 (4294967296ull , nco_shift , & hi , & lo );
176- adi_ad9088_hal_add_128 (hi , lo , 0 , freq >> 1 , & hi , & lo );
177- adi_ad9088_hal_div_128 (hi , lo , 0 , freq , & hi , ftw );
178- } else {
179- adi_ad9088_hal_mult_128 (4294967296ull , - nco_shift , & hi , & lo );
180- adi_ad9088_hal_add_128 (hi , lo , 0 , freq >> 1 , & hi , & lo );
181- adi_ad9088_hal_div_128 (hi , lo , 0 , freq , & hi , ftw );
182- * ftw = 4294967296ull - * ftw ;
183- }
184-
185- return API_CMS_ERROR_OK ;
186- }
187-
188- int32_t adi_ad9088_calc_nco32_freq (adi_apollo_device_t * device ,
189- u64 freq ,
190- u64 ftw , int64_t * nco_shift )
61+ int32_t adi_ad9088_calc_nco_freq (adi_apollo_device_t * device ,
62+ u64 freq , u64 ftw , u32 a , u32 b ,
63+ u32 bits , s64 * nco_shift )
19164{
192- u64 hi , lo ;
65+ u64 hi , lo , mod ;
19366 bool neg = false;
19467
195- if (!freq )
68+ pr_debug ("adi_ad9088_calc_nco_freq: freq=%llu, ftw=%llu, a=%u, b=%u, bits=%u\n" ,
69+ freq , ftw , a , b , bits );
70+
71+ if (!freq || !bits || (bits > 64 ) || (a > b ) || !b )
19672 return - EINVAL ;
19773
198- if (ftw > 2147483648ull ) {
199- ftw = 0x100000000 - ftw ;
74+ mod = (1ULL << bits );
75+
76+ if (ftw > (mod >> 1 )) {
77+ ftw = mod - ftw ;
20078 neg = true;
20179 }
20280
203- adi_ad9088_hal_mult_128 (freq , ftw , & hi , & lo );
204- adi_ad9088_hal_add_128 (hi , lo , 0 , 4294967296ull / 2 , & hi , & lo );
205- adi_ad9088_hal_div_128 (hi , lo , 0 , 4294967296ull , & hi , nco_shift );
81+ adi_api_utils_mult_128 (freq , ( ftw * 100ULL ) + (( 100 * a ) / b ) , & hi , & lo );
82+ adi_api_utils_add_128 (hi , lo , 0 , ( mod * 100 ) >> 1 , & hi , & lo );
83+ adi_api_utils_div_128 (hi , lo , 0 , ( mod * 100 ) , & hi , nco_shift );
20684
20785 if (neg )
20886 * nco_shift *= -1 ;
@@ -903,36 +781,43 @@ static ssize_t ad9088_ext_info_read(struct iio_dev *indio_dev,
903781
904782 switch (private ) {
905783 case CDDC_NCO_FREQ :
906-
907- if (chan -> output )
908- adi_ad9088_calc_nco32_freq (& phy -> ad9088 , phy -> profile .dac_config [side ].dac_sampling_rate_Hz ,
909- phy -> profile .tx_path [side ].tx_cduc [cddc_num ].nco [0 ].nco_phase_inc , & val );
910- else
911- adi_ad9088_calc_nco32_freq (& phy -> ad9088 , phy -> profile .adc_config [side ].adc_sampling_rate_Hz ,
912- phy -> profile .rx_path [side ].rx_cddc [cddc_num ].nco [0 ].nco_phase_inc , & val );
913-
914- //val = phy->cnco_freq[chan->output][side][cddc_num];
915- ret = 0 ;
784+ if (chan -> output ) {
785+ f = phy -> profile .dac_config [side ].dac_sampling_rate_Hz ;
786+ ret = adi_ad9088_calc_nco_freq (& phy -> ad9088 , f , phy -> profile .tx_path [side ].tx_cduc [cddc_num ].nco [0 ].nco_phase_inc ,
787+ phy -> profile .tx_path [side ].tx_cduc [cddc_num ].nco [0 ].nco_phase_inc_frac_a ,
788+ phy -> profile .tx_path [side ].tx_cduc [cddc_num ].nco [0 ].nco_phase_inc_frac_b , 32 , & val );
789+ } else {
790+ f = phy -> profile .adc_config [side ].adc_sampling_rate_Hz ;
791+ ret = adi_ad9088_calc_nco_freq (& phy -> ad9088 , f , phy -> profile .rx_path [side ].rx_cddc [cddc_num ].nco [0 ].nco_phase_inc ,
792+ phy -> profile .rx_path [side ].rx_cddc [cddc_num ].nco [0 ].nco_phase_inc_frac_a ,
793+ phy -> profile .rx_path [side ].rx_cddc [cddc_num ].nco [0 ].nco_phase_inc_frac_b , 32 , & val );
794+ }
916795 break ;
917796 case FDDC_NCO_FREQ :
918-
919797 if (chan -> output ) {
920798 u32 cddc_dcm ;
921799
922800 adi_apollo_cduc_interp_bf_to_val (& phy -> ad9088 , phy -> profile .tx_path [side ].tx_cduc [cddc_num ].drc_ratio , & cddc_dcm );
923801 f = phy -> profile .dac_config [side ].dac_sampling_rate_Hz ;
924802 do_div (f , cddc_dcm );
925- adi_ad9088_calc_nco_freq (& phy -> ad9088 , f , phy -> profile .tx_path [side ].tx_fduc [fddc_num ].nco [0 ].nco_phase_inc , & val );
803+
804+ ret = adi_ad9088_calc_nco_freq (& phy -> ad9088 , f ,
805+ phy -> profile .tx_path [side ].tx_fduc [fddc_num ].nco [0 ].nco_phase_inc ,
806+ phy -> profile .tx_path [side ].tx_fduc [fddc_num ].nco [0 ].nco_phase_inc_frac_a ,
807+ phy -> profile .tx_path [side ].tx_fduc [fddc_num ].nco [0 ].nco_phase_inc_frac_b ,
808+ 48 , & val );
926809 } else {
927810 u32 cddc_dcm ;
928811
929812 adi_apollo_cddc_dcm_bf_to_val (& phy -> ad9088 , phy -> profile .rx_path [side ].rx_cddc [cddc_num ].drc_ratio , & cddc_dcm );
930813 f = phy -> profile .adc_config [side ].adc_sampling_rate_Hz ;
931814 do_div (f , cddc_dcm );
932- adi_ad9088_calc_nco_freq (& phy -> ad9088 , f , phy -> profile .rx_path [side ].rx_fddc [fddc_num ].nco [0 ].nco_phase_inc , & val );
815+ ret = adi_ad9088_calc_nco_freq (& phy -> ad9088 , f ,
816+ phy -> profile .rx_path [side ].rx_fddc [fddc_num ].nco [0 ].nco_phase_inc ,
817+ phy -> profile .rx_path [side ].rx_fddc [fddc_num ].nco [0 ].nco_phase_inc_frac_a ,
818+ phy -> profile .rx_path [side ].rx_fddc [fddc_num ].nco [0 ].nco_phase_inc_frac_b ,
819+ 48 , & val );
933820 }
934- //val = phy->fnco_freq[chan->output][side][fddc_num];
935- ret = 0 ;
936821 break ;
937822 case CDDC_NCO_FREQ_AVAIL :
938823 if (chan -> output )
@@ -1036,7 +921,7 @@ static ssize_t ad9088_ext_info_write(struct iio_dev *indio_dev,
1036921 u32 cddc_mask , fddc_mask ;
1037922 s32 val32 , tmp ;
1038923 s64 val64 ;
1039- u64 ftw , f ;
924+ u64 ftw , f , frac_a , frac_b ;
1040925 adi_apollo_terminal_e terminal ;
1041926 adi_apollo_cfir_sel_e cfir_sel ;
1042927 adi_apollo_cfir_dp_sel dp_sel ;
@@ -1053,27 +938,33 @@ static ssize_t ad9088_ext_info_write(struct iio_dev *indio_dev,
1053938 return ret ;
1054939
1055940 if (chan -> output )
1056- adi_ad9088_calc_nco_ftw32 ( & phy -> ad9088 , phy -> profile .dac_config [side ].dac_sampling_rate_Hz , readin , & ftw ) ;
941+ f = phy -> profile .dac_config [side ].dac_sampling_rate_Hz ;
1057942 else
1058- adi_ad9088_calc_nco_ftw32 (& phy -> ad9088 , phy -> profile .adc_config [side ].adc_sampling_rate_Hz , readin , & ftw );
943+ f = phy -> profile .adc_config [side ].adc_sampling_rate_Hz ;
944+
945+
946+ ret = adi_ad9088_calc_nco_ftw (& phy -> ad9088 , f , readin , 32 , & ftw , & frac_a , & frac_b );
947+ if (ret )
948+ return ret ;
1059949
1060- ret = adi_apollo_cnco_mode_set (& phy -> ad9088 , chan -> output ? ADI_APOLLO_TX : ADI_APOLLO_RX , cddc_mask ,
1061- readin ? ADI_APOLLO_MXR_VAR_IF_MODE : ADI_APOLLO_MXR_ZERO_IF_MODE );
950+ ret = adi_apollo_cnco_ftw_set (& phy -> ad9088 , chan -> output ? ADI_APOLLO_TX : ADI_APOLLO_RX , cddc_mask , 0 , 1 , (u32 ) ftw );
1062951 if (ret )
1063952 return ret ;
1064953
1065- ret = adi_apollo_cnco_ftw_set (& phy -> ad9088 , chan -> output ? ADI_APOLLO_TX : ADI_APOLLO_RX , cddc_mask , 0 , 1 , ftw );
954+ ret = adi_apollo_cnco_mod_set (& phy -> ad9088 , chan -> output ? ADI_APOLLO_TX : ADI_APOLLO_RX , cddc_mask , ( u32 ) frac_a , ( u32 ) frac_b );
1066955
1067956 if (!ret ) {
1068- if (chan -> output )
957+ if (chan -> output ) {
1069958 phy -> profile .tx_path [side ].tx_cduc [cddc_num ].nco [0 ].nco_phase_inc = ftw ;
1070- else
959+ phy -> profile .tx_path [side ].tx_cduc [cddc_num ].nco [0 ].nco_phase_inc_frac_a = frac_a ;
960+ phy -> profile .tx_path [side ].tx_cduc [cddc_num ].nco [0 ].nco_phase_inc_frac_b = frac_b ;
961+ } else {
1071962 phy -> profile .rx_path [side ].rx_cddc [cddc_num ].nco [0 ].nco_phase_inc = ftw ;
963+ phy -> profile .rx_path [side ].rx_cddc [cddc_num ].nco [0 ].nco_phase_inc_frac_a = frac_a ;
964+ phy -> profile .rx_path [side ].rx_cddc [cddc_num ].nco [0 ].nco_phase_inc_frac_b = frac_b ;
965+ }
1072966 }
1073967
1074- // if (!ret)
1075- // phy->cnco_freq[chan->output][side][cddc_num] = readin;
1076-
1077968 break ;
1078969 case FDDC_NCO_FREQ :
1079970 ret = kstrtoll (buf , 10 , & readin );
@@ -1094,25 +985,30 @@ static ssize_t ad9088_ext_info_write(struct iio_dev *indio_dev,
1094985 do_div (f , cddc_dcm );
1095986 }
1096987
1097- adi_ad9088_calc_nco_ftw (& phy -> ad9088 , f , readin , & ftw );
1098-
1099- ret = adi_apollo_fnco_mode_set (& phy -> ad9088 , chan -> output ? ADI_APOLLO_TX : ADI_APOLLO_RX , fddc_mask ,
1100- readin ? ADI_APOLLO_MXR_VAR_IF_MODE : ADI_APOLLO_MXR_ZERO_IF_MODE );
988+ ret = adi_ad9088_calc_nco_ftw (& phy -> ad9088 , f , readin , 48 , & ftw , & frac_a , & frac_b );
1101989 if (ret )
1102990 return ret ;
1103991
1104- ret = adi_apollo_fnco_main_phase_inc_set (& phy -> ad9088 , chan -> output ? ADI_APOLLO_TX : ADI_APOLLO_RX , fddc_mask , ftw );
992+ adi_apollo_fine_nco_main_pgm_t config = {
993+ .main_phase_inc = ftw ,
994+ .main_phase_offset = div_s64 (phy -> fnco_phase [chan -> output ][side ][fddc_num ] * 14073748835533 , 18000LL ),
995+ .drc_phase_inc_frac_a = frac_a ,
996+ .drc_phase_inc_frac_b = frac_b ,
997+ };
998+
999+ ret = adi_apollo_fnco_main_pgm (& phy -> ad9088 , chan -> output ? ADI_APOLLO_TX : ADI_APOLLO_RX , fddc_mask , & config );
11051000
11061001 if (!ret ) {
1107- if (chan -> output )
1002+ if (chan -> output ) {
11081003 phy -> profile .tx_path [side ].tx_fduc [fddc_num ].nco [0 ].nco_phase_inc = ftw ;
1109- else
1004+ phy -> profile .tx_path [side ].tx_fduc [fddc_num ].nco [0 ].nco_phase_inc_frac_a = frac_a ;
1005+ phy -> profile .tx_path [side ].tx_fduc [fddc_num ].nco [0 ].nco_phase_inc_frac_b = frac_b ;
1006+ } else {
11101007 phy -> profile .rx_path [side ].rx_fddc [fddc_num ].nco [0 ].nco_phase_inc = ftw ;
1008+ phy -> profile .rx_path [side ].rx_fddc [fddc_num ].nco [0 ].nco_phase_inc_frac_a = frac_a ;
1009+ phy -> profile .rx_path [side ].rx_fddc [fddc_num ].nco [0 ].nco_phase_inc_frac_b = frac_b ;
1010+ }
11111011 }
1112-
1113- // if (!ret)
1114- // phy->fnco_freq[chan->output][side][fddc_num] = readin;
1115-
11161012 break ;
11171013 case CDDC_NCO_PHASE :
11181014 ret = kstrtoll (buf , 10 , & readin );
0 commit comments