10
10
#include <linux/module.h>
11
11
#include <linux/ptp_clock_kernel.h>
12
12
#include <linux/delay.h>
13
+ #include <linux/jiffies.h>
13
14
#include <linux/kernel.h>
14
15
#include <linux/timekeeping.h>
15
16
@@ -24,6 +25,16 @@ MODULE_LICENSE("GPL");
24
25
25
26
#define SETTIME_CORRECTION (0)
26
27
28
+ static long set_write_phase_ready (struct ptp_clock_info * ptp )
29
+ {
30
+ struct idtcm_channel * channel =
31
+ container_of (ptp , struct idtcm_channel , caps );
32
+
33
+ channel -> write_phase_ready = 1 ;
34
+
35
+ return 0 ;
36
+ }
37
+
27
38
static int char_array_to_timespec (u8 * buf ,
28
39
u8 count ,
29
40
struct timespec64 * ts )
@@ -871,6 +882,64 @@ static int idtcm_set_pll_mode(struct idtcm_channel *channel,
871
882
872
883
/* PTP Hardware Clock interface */
873
884
885
+ /**
886
+ * @brief Maximum absolute value for write phase offset in picoseconds
887
+ *
888
+ * Destination signed register is 32-bit register in resolution of 50ps
889
+ *
890
+ * 0x7fffffff * 50 = 2147483647 * 50 = 107374182350
891
+ */
892
+ static int _idtcm_adjphase (struct idtcm_channel * channel , s32 delta_ns )
893
+ {
894
+ struct idtcm * idtcm = channel -> idtcm ;
895
+
896
+ int err ;
897
+ u8 i ;
898
+ u8 buf [4 ] = {0 };
899
+ s32 phase_50ps ;
900
+ s64 offset_ps ;
901
+
902
+ if (channel -> pll_mode != PLL_MODE_WRITE_PHASE ) {
903
+
904
+ err = idtcm_set_pll_mode (channel , PLL_MODE_WRITE_PHASE );
905
+
906
+ if (err )
907
+ return err ;
908
+
909
+ channel -> write_phase_ready = 0 ;
910
+
911
+ ptp_schedule_worker (channel -> ptp_clock ,
912
+ msecs_to_jiffies (WR_PHASE_SETUP_MS ));
913
+ }
914
+
915
+ if (!channel -> write_phase_ready )
916
+ delta_ns = 0 ;
917
+
918
+ offset_ps = (s64 )delta_ns * 1000 ;
919
+
920
+ /*
921
+ * Check for 32-bit signed max * 50:
922
+ *
923
+ * 0x7fffffff * 50 = 2147483647 * 50 = 107374182350
924
+ */
925
+ if (offset_ps > MAX_ABS_WRITE_PHASE_PICOSECONDS )
926
+ offset_ps = MAX_ABS_WRITE_PHASE_PICOSECONDS ;
927
+ else if (offset_ps < - MAX_ABS_WRITE_PHASE_PICOSECONDS )
928
+ offset_ps = - MAX_ABS_WRITE_PHASE_PICOSECONDS ;
929
+
930
+ phase_50ps = DIV_ROUND_CLOSEST (div64_s64 (offset_ps , 50 ), 1 );
931
+
932
+ for (i = 0 ; i < 4 ; i ++ ) {
933
+ buf [i ] = phase_50ps & 0xff ;
934
+ phase_50ps >>= 8 ;
935
+ }
936
+
937
+ err = idtcm_write (idtcm , channel -> dpll_phase , DPLL_WR_PHASE ,
938
+ buf , sizeof (buf ));
939
+
940
+ return err ;
941
+ }
942
+
874
943
static int idtcm_adjfreq (struct ptp_clock_info * ptp , s32 ppb )
875
944
{
876
945
struct idtcm_channel * channel =
@@ -977,6 +1046,24 @@ static int idtcm_adjtime(struct ptp_clock_info *ptp, s64 delta)
977
1046
return err ;
978
1047
}
979
1048
1049
+ static int idtcm_adjphase (struct ptp_clock_info * ptp , s32 delta )
1050
+ {
1051
+ struct idtcm_channel * channel =
1052
+ container_of (ptp , struct idtcm_channel , caps );
1053
+
1054
+ struct idtcm * idtcm = channel -> idtcm ;
1055
+
1056
+ int err ;
1057
+
1058
+ mutex_lock (& idtcm -> reg_lock );
1059
+
1060
+ err = _idtcm_adjphase (channel , delta );
1061
+
1062
+ mutex_unlock (& idtcm -> reg_lock );
1063
+
1064
+ return err ;
1065
+ }
1066
+
980
1067
static int idtcm_enable (struct ptp_clock_info * ptp ,
981
1068
struct ptp_clock_request * rq , int on )
982
1069
{
@@ -1055,13 +1142,16 @@ static const struct ptp_clock_info idtcm_caps = {
1055
1142
.owner = THIS_MODULE ,
1056
1143
.max_adj = 244000 ,
1057
1144
.n_per_out = 1 ,
1145
+ .adjphase = & idtcm_adjphase ,
1058
1146
.adjfreq = & idtcm_adjfreq ,
1059
1147
.adjtime = & idtcm_adjtime ,
1060
1148
.gettime64 = & idtcm_gettime ,
1061
1149
.settime64 = & idtcm_settime ,
1062
1150
.enable = & idtcm_enable ,
1151
+ .do_aux_work = & set_write_phase_ready ,
1063
1152
};
1064
1153
1154
+
1065
1155
static int idtcm_enable_channel (struct idtcm * idtcm , u32 index )
1066
1156
{
1067
1157
struct idtcm_channel * channel ;
@@ -1146,6 +1236,8 @@ static int idtcm_enable_channel(struct idtcm *idtcm, u32 index)
1146
1236
if (!channel -> ptp_clock )
1147
1237
return - ENOTSUPP ;
1148
1238
1239
+ channel -> write_phase_ready = 0 ;
1240
+
1149
1241
dev_info (& idtcm -> client -> dev , "PLL%d registered as ptp%d\n" ,
1150
1242
index , channel -> ptp_clock -> index );
1151
1243
0 commit comments