@@ -669,12 +669,137 @@ zl3073x_dev_state_fetch(struct zl3073x_dev *zldev)
669
669
return rc ;
670
670
}
671
671
672
+ /**
673
+ * zl3073x_ref_phase_offsets_update - update reference phase offsets
674
+ * @zldev: pointer to zl3073x_dev structure
675
+ * @channel: DPLL channel number or -1
676
+ *
677
+ * The function asks device to update phase offsets latch registers with
678
+ * the latest measured values. There are 2 sets of latch registers:
679
+ *
680
+ * 1) Up to 5 DPLL-to-connected-ref registers that contain phase offset
681
+ * values between particular DPLL channel and its *connected* input
682
+ * reference.
683
+ *
684
+ * 2) 10 selected-DPLL-to-all-ref registers that contain phase offset values
685
+ * between selected DPLL channel and all input references.
686
+ *
687
+ * If the caller is interested in 2) then it has to pass DPLL channel number
688
+ * in @channel parameter. If it is interested only in 1) then it should pass
689
+ * @channel parameter with value of -1.
690
+ *
691
+ * Return: 0 on success, <0 on error
692
+ */
693
+ int zl3073x_ref_phase_offsets_update (struct zl3073x_dev * zldev , int channel )
694
+ {
695
+ int rc ;
696
+
697
+ /* Per datasheet we have to wait for 'dpll_ref_phase_err_rqst_rd'
698
+ * to be zero to ensure that the measured data are coherent.
699
+ */
700
+ rc = zl3073x_poll_zero_u8 (zldev , ZL_REG_REF_PHASE_ERR_READ_RQST ,
701
+ ZL_REF_PHASE_ERR_READ_RQST_RD );
702
+ if (rc )
703
+ return rc ;
704
+
705
+ /* Select DPLL channel if it is specified */
706
+ if (channel != -1 ) {
707
+ rc = zl3073x_write_u8 (zldev , ZL_REG_DPLL_MEAS_IDX , channel );
708
+ if (rc )
709
+ return rc ;
710
+ }
711
+
712
+ /* Request to update phase offsets measurement values */
713
+ rc = zl3073x_write_u8 (zldev , ZL_REG_REF_PHASE_ERR_READ_RQST ,
714
+ ZL_REF_PHASE_ERR_READ_RQST_RD );
715
+ if (rc )
716
+ return rc ;
717
+
718
+ /* Wait for finish */
719
+ return zl3073x_poll_zero_u8 (zldev , ZL_REG_REF_PHASE_ERR_READ_RQST ,
720
+ ZL_REF_PHASE_ERR_READ_RQST_RD );
721
+ }
722
+
723
+ /**
724
+ * zl3073x_ref_ffo_update - update reference fractional frequency offsets
725
+ * @zldev: pointer to zl3073x_dev structure
726
+ *
727
+ * The function asks device to update fractional frequency offsets latch
728
+ * registers the latest measured values, reads and stores them into
729
+ *
730
+ * Return: 0 on success, <0 on error
731
+ */
732
+ static int
733
+ zl3073x_ref_ffo_update (struct zl3073x_dev * zldev )
734
+ {
735
+ int i , rc ;
736
+
737
+ /* Per datasheet we have to wait for 'ref_freq_meas_ctrl' to be zero
738
+ * to ensure that the measured data are coherent.
739
+ */
740
+ rc = zl3073x_poll_zero_u8 (zldev , ZL_REG_REF_FREQ_MEAS_CTRL ,
741
+ ZL_REF_FREQ_MEAS_CTRL );
742
+ if (rc )
743
+ return rc ;
744
+
745
+ /* Select all references for measurement */
746
+ rc = zl3073x_write_u8 (zldev , ZL_REG_REF_FREQ_MEAS_MASK_3_0 ,
747
+ GENMASK (7 , 0 )); /* REF0P..REF3N */
748
+ if (rc )
749
+ return rc ;
750
+ rc = zl3073x_write_u8 (zldev , ZL_REG_REF_FREQ_MEAS_MASK_4 ,
751
+ GENMASK (1 , 0 )); /* REF4P..REF4N */
752
+ if (rc )
753
+ return rc ;
754
+
755
+ /* Request frequency offset measurement */
756
+ rc = zl3073x_write_u8 (zldev , ZL_REG_REF_FREQ_MEAS_CTRL ,
757
+ ZL_REF_FREQ_MEAS_CTRL_REF_FREQ_OFF );
758
+ if (rc )
759
+ return rc ;
760
+
761
+ /* Wait for finish */
762
+ rc = zl3073x_poll_zero_u8 (zldev , ZL_REG_REF_FREQ_MEAS_CTRL ,
763
+ ZL_REF_FREQ_MEAS_CTRL );
764
+ if (rc )
765
+ return rc ;
766
+
767
+ /* Read DPLL-to-REFx frequency offset measurements */
768
+ for (i = 0 ; i < ZL3073X_NUM_REFS ; i ++ ) {
769
+ s32 value ;
770
+
771
+ /* Read value stored in units of 2^-32 signed */
772
+ rc = zl3073x_read_u32 (zldev , ZL_REG_REF_FREQ (i ), & value );
773
+ if (rc )
774
+ return rc ;
775
+
776
+ /* Convert to ppm -> ffo = (10^6 * value) / 2^32 */
777
+ zldev -> ref [i ].ffo = mul_s64_u64_shr (value , 1000000 , 32 );
778
+ }
779
+
780
+ return 0 ;
781
+ }
782
+
672
783
static void
673
784
zl3073x_dev_periodic_work (struct kthread_work * work )
674
785
{
675
786
struct zl3073x_dev * zldev = container_of (work , struct zl3073x_dev ,
676
787
work .work );
677
788
struct zl3073x_dpll * zldpll ;
789
+ int rc ;
790
+
791
+ /* Update DPLL-to-connected-ref phase offsets registers */
792
+ rc = zl3073x_ref_phase_offsets_update (zldev , -1 );
793
+ if (rc )
794
+ dev_warn (zldev -> dev , "Failed to update phase offsets: %pe\n" ,
795
+ ERR_PTR (rc ));
796
+
797
+ /* Update references' fractional frequency offsets */
798
+ rc = zl3073x_ref_ffo_update (zldev );
799
+ if (rc )
800
+ dev_warn (zldev -> dev ,
801
+ "Failed to update fractional frequency offsets: %pe\n" ,
802
+ ERR_PTR (rc ));
678
803
679
804
list_for_each_entry (zldpll , & zldev -> dplls , list )
680
805
zl3073x_dpll_changes_check (zldpll );
@@ -767,6 +892,46 @@ zl3073x_devm_dpll_init(struct zl3073x_dev *zldev, u8 num_dplls)
767
892
return rc ;
768
893
}
769
894
895
+ /**
896
+ * zl3073x_dev_phase_meas_setup - setup phase offset measurement
897
+ * @zldev: pointer to zl3073x_dev structure
898
+ * @num_channels: number of DPLL channels
899
+ *
900
+ * Enable phase offset measurement block, set measurement averaging factor
901
+ * and enable DPLL-to-its-ref phase measurement for all DPLLs.
902
+ *
903
+ * Returns: 0 on success, <0 on error
904
+ */
905
+ static int
906
+ zl3073x_dev_phase_meas_setup (struct zl3073x_dev * zldev , int num_channels )
907
+ {
908
+ u8 dpll_meas_ctrl , mask ;
909
+ int i , rc ;
910
+
911
+ /* Read DPLL phase measurement control register */
912
+ rc = zl3073x_read_u8 (zldev , ZL_REG_DPLL_MEAS_CTRL , & dpll_meas_ctrl );
913
+ if (rc )
914
+ return rc ;
915
+
916
+ /* Setup phase measurement averaging factor */
917
+ dpll_meas_ctrl &= ~ZL_DPLL_MEAS_CTRL_AVG_FACTOR ;
918
+ dpll_meas_ctrl |= FIELD_PREP (ZL_DPLL_MEAS_CTRL_AVG_FACTOR , 3 );
919
+
920
+ /* Enable DPLL measurement block */
921
+ dpll_meas_ctrl |= ZL_DPLL_MEAS_CTRL_EN ;
922
+
923
+ /* Update phase measurement control register */
924
+ rc = zl3073x_write_u8 (zldev , ZL_REG_DPLL_MEAS_CTRL , dpll_meas_ctrl );
925
+ if (rc )
926
+ return rc ;
927
+
928
+ /* Enable DPLL-to-connected-ref measurement for each channel */
929
+ for (i = 0 , mask = 0 ; i < num_channels ; i ++ )
930
+ mask |= BIT (i );
931
+
932
+ return zl3073x_write_u8 (zldev , ZL_REG_DPLL_PHASE_ERR_READ_MASK , mask );
933
+ }
934
+
770
935
/**
771
936
* zl3073x_dev_probe - initialize zl3073x device
772
937
* @zldev: pointer to zl3073x device
@@ -839,6 +1004,12 @@ int zl3073x_dev_probe(struct zl3073x_dev *zldev,
839
1004
if (rc )
840
1005
return rc ;
841
1006
1007
+ /* Setup phase offset measurement block */
1008
+ rc = zl3073x_dev_phase_meas_setup (zldev , chip_info -> num_channels );
1009
+ if (rc )
1010
+ return dev_err_probe (zldev -> dev , rc ,
1011
+ "Failed to setup phase measurement\n" );
1012
+
842
1013
/* Register DPLL channels */
843
1014
rc = zl3073x_devm_dpll_init (zldev , chip_info -> num_channels );
844
1015
if (rc )
0 commit comments