@@ -419,12 +419,11 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq)
419
419
int rc , i ;
420
420
unsigned sleep_time = 10000 ;
421
421
uint64_t vco_freq ;
422
- uint32_t vco_fra ; /* VCO contribution by SDM (kHz) */
423
- uint32_t vco_min = 1770000 ;
424
- uint32_t vco_max = vco_min * 2 ;
425
- uint32_t freq_khz , pll_ref , pll_ref_khz ;
426
- uint16_t n_sdm = 2 ;
427
- uint16_t sdm = 0 ;
422
+ uint64_t vco_div ;
423
+ uint32_t vco_min = 1770000 ; /* kHz */
424
+ uint32_t vco_max = vco_min * 2 ; /* kHz */
425
+ uint32_t freq_khz , pll_ref ;
426
+ uint32_t sdm = 0 ;
428
427
uint8_t mix_div = 2 ;
429
428
uint8_t div_buf = 0 ;
430
429
uint8_t div_num = 0 ;
@@ -436,7 +435,6 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq)
436
435
/* Frequency in kHz */
437
436
freq_khz = (freq + 500 ) / 1000 ;
438
437
pll_ref = priv -> cfg -> xtal ;
439
- pll_ref_khz = (priv -> cfg -> xtal + 500 ) / 1000 ;
440
438
441
439
rc = r82xx_write_reg_mask (priv , 0x10 , refdiv2 , 0x10 );
442
440
if (rc < 0 )
@@ -485,8 +483,35 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq)
485
483
return rc ;
486
484
487
485
vco_freq = (uint64_t )freq * (uint64_t )mix_div ;
488
- nint = vco_freq / (2 * pll_ref );
489
- vco_fra = (vco_freq - 2 * pll_ref * nint ) / 1000 ;
486
+
487
+ /*
488
+ * We want to approximate:
489
+ *
490
+ * vco_freq / (2 * pll_ref)
491
+ *
492
+ * in the form:
493
+ *
494
+ * nint + sdm/65536
495
+ *
496
+ * where nint,sdm are integers and 0 < nint, 0 <= sdm < 65536
497
+ *
498
+ * Scaling to fixed point and rounding:
499
+ *
500
+ * vco_div = 65536*(nint + sdm/65536) = int( 0.5 + 65536 * vco_freq / (2 * pll_ref) )
501
+ * vco_div = 65536*nint + sdm = int( (pll_ref + 65536 * vco_freq) / (2 * pll_ref) )
502
+ */
503
+
504
+ vco_div = (pll_ref + 65536 * vco_freq ) / (2 * pll_ref );
505
+ nint = (uint32_t ) (vco_div / 65536 );
506
+ sdm = (uint32_t ) (vco_div % 65536 );
507
+
508
+ #if 0
509
+ {
510
+ uint64_t actual_vco = (uint64_t )2 * pll_ref * nint + (uint64_t )2 * pll_ref * sdm / 65536 ;
511
+ fprintf (stderr , "[R82XX] requested %uHz; selected mix_div=%u vco_freq=%lu nint=%u sdm=%u; actual_vco=%lu; tuning error=%+dHz\n" ,
512
+ freq , mix_div , vco_freq , nint , sdm , actual_vco , (int32_t ) (actual_vco - vco_freq ) / mix_div );
513
+ }
514
+ #endif
490
515
491
516
if (nint > ((128 / vco_power_ref ) - 1 )) {
492
517
fprintf (stderr , "[R82XX] No valid PLL values for %u Hz!\n" , freq );
@@ -501,7 +526,7 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq)
501
526
return rc ;
502
527
503
528
/* pw_sdm */
504
- if (! vco_fra )
529
+ if (sdm == 0 )
505
530
val = 0x08 ;
506
531
else
507
532
val = 0x00 ;
@@ -510,17 +535,6 @@ static int r82xx_set_pll(struct r82xx_priv *priv, uint32_t freq)
510
535
if (rc < 0 )
511
536
return rc ;
512
537
513
- /* sdm calculator */
514
- while (vco_fra > 1 ) {
515
- if (vco_fra > (2 * pll_ref_khz / n_sdm )) {
516
- sdm = sdm + 32768 / (n_sdm / 2 );
517
- vco_fra = vco_fra - 2 * pll_ref_khz / n_sdm ;
518
- if (n_sdm >= 0x8000 )
519
- break ;
520
- }
521
- n_sdm <<= 1 ;
522
- }
523
-
524
538
rc = r82xx_write_reg (priv , 0x16 , sdm >> 8 );
525
539
if (rc < 0 )
526
540
return rc ;
0 commit comments