44#include "idpf.h"
55#include "idpf_ptp.h"
66
7+ /**
8+ * idpf_ptp_get_access - Determine the access type of the PTP features
9+ * @adapter: Driver specific private structure
10+ * @direct: Capability that indicates the direct access
11+ * @mailbox: Capability that indicates the mailbox access
12+ *
13+ * Return: the type of supported access for the PTP feature.
14+ */
15+ static enum idpf_ptp_access
16+ idpf_ptp_get_access (const struct idpf_adapter * adapter , u32 direct , u32 mailbox )
17+ {
18+ if (adapter -> ptp -> caps & direct )
19+ return IDPF_PTP_DIRECT ;
20+ else if (adapter -> ptp -> caps & mailbox )
21+ return IDPF_PTP_MAILBOX ;
22+ else
23+ return IDPF_PTP_NONE ;
24+ }
25+
26+ /**
27+ * idpf_ptp_get_features_access - Determine the access type of PTP features
28+ * @adapter: Driver specific private structure
29+ *
30+ * Fulfill the adapter structure with type of the supported PTP features
31+ * access.
32+ */
33+ void idpf_ptp_get_features_access (const struct idpf_adapter * adapter )
34+ {
35+ struct idpf_ptp * ptp = adapter -> ptp ;
36+ u32 direct , mailbox ;
37+
38+ /* Get the device clock time */
39+ direct = VIRTCHNL2_CAP_PTP_GET_DEVICE_CLK_TIME ;
40+ mailbox = VIRTCHNL2_CAP_PTP_GET_DEVICE_CLK_TIME_MB ;
41+ ptp -> get_dev_clk_time_access = idpf_ptp_get_access (adapter ,
42+ direct ,
43+ mailbox );
44+ }
45+
46+ /**
47+ * idpf_ptp_enable_shtime - Enable shadow time and execute a command
48+ * @adapter: Driver specific private structure
49+ */
50+ static void idpf_ptp_enable_shtime (struct idpf_adapter * adapter )
51+ {
52+ u32 shtime_enable , exec_cmd ;
53+
54+ /* Get offsets */
55+ shtime_enable = adapter -> ptp -> cmd .shtime_enable_mask ;
56+ exec_cmd = adapter -> ptp -> cmd .exec_cmd_mask ;
57+
58+ /* Set the shtime en and the sync field */
59+ writel (shtime_enable , adapter -> ptp -> dev_clk_regs .cmd_sync );
60+ writel (exec_cmd | shtime_enable , adapter -> ptp -> dev_clk_regs .cmd_sync );
61+ }
62+
63+ /**
64+ * idpf_ptp_read_src_clk_reg_direct - Read directly the main timer value
65+ * @adapter: Driver specific private structure
66+ * @sts: Optional parameter for holding a pair of system timestamps from
67+ * the system clock. Will be ignored when NULL is given.
68+ *
69+ * Return: the device clock time.
70+ */
71+ static u64 idpf_ptp_read_src_clk_reg_direct (struct idpf_adapter * adapter ,
72+ struct ptp_system_timestamp * sts )
73+ {
74+ struct idpf_ptp * ptp = adapter -> ptp ;
75+ u32 hi , lo ;
76+
77+ spin_lock (& ptp -> read_dev_clk_lock );
78+
79+ /* Read the system timestamp pre PHC read */
80+ ptp_read_system_prets (sts );
81+
82+ idpf_ptp_enable_shtime (adapter );
83+
84+ /* Read the system timestamp post PHC read */
85+ ptp_read_system_postts (sts );
86+
87+ lo = readl (ptp -> dev_clk_regs .dev_clk_ns_l );
88+ hi = readl (ptp -> dev_clk_regs .dev_clk_ns_h );
89+
90+ spin_unlock (& ptp -> read_dev_clk_lock );
91+
92+ return ((u64 )hi << 32 ) | lo ;
93+ }
94+
95+ /**
96+ * idpf_ptp_read_src_clk_reg - Read the main timer value
97+ * @adapter: Driver specific private structure
98+ * @src_clk: Returned main timer value in nanoseconds unit
99+ * @sts: Optional parameter for holding a pair of system timestamps from
100+ * the system clock. Will be ignored if NULL is given.
101+ *
102+ * Return: the device clock time on success, -errno otherwise.
103+ */
104+ static int idpf_ptp_read_src_clk_reg (struct idpf_adapter * adapter , u64 * src_clk ,
105+ struct ptp_system_timestamp * sts )
106+ {
107+ switch (adapter -> ptp -> get_dev_clk_time_access ) {
108+ case IDPF_PTP_NONE :
109+ return - EOPNOTSUPP ;
110+ case IDPF_PTP_DIRECT :
111+ * src_clk = idpf_ptp_read_src_clk_reg_direct (adapter , sts );
112+ break ;
113+ default :
114+ return - EOPNOTSUPP ;
115+ }
116+
117+ return 0 ;
118+ }
119+
120+ /**
121+ * idpf_ptp_gettimex64 - Get the time of the clock
122+ * @info: the driver's PTP info structure
123+ * @ts: timespec64 structure to hold the current time value
124+ * @sts: Optional parameter for holding a pair of system timestamps from
125+ * the system clock. Will be ignored if NULL is given.
126+ *
127+ * Return: the device clock value in ns, after converting it into a timespec
128+ * struct on success, -errno otherwise.
129+ */
130+ static int idpf_ptp_gettimex64 (struct ptp_clock_info * info ,
131+ struct timespec64 * ts ,
132+ struct ptp_system_timestamp * sts )
133+ {
134+ struct idpf_adapter * adapter = idpf_ptp_info_to_adapter (info );
135+ u64 time_ns ;
136+ int err ;
137+
138+ err = idpf_ptp_read_src_clk_reg (adapter , & time_ns , sts );
139+ if (err )
140+ return - EACCES ;
141+
142+ * ts = ns_to_timespec64 (time_ns );
143+
144+ return 0 ;
145+ }
146+
147+ /**
148+ * idpf_ptp_set_caps - Set PTP capabilities
149+ * @adapter: Driver specific private structure
150+ *
151+ * This function sets the PTP functions.
152+ */
153+ static void idpf_ptp_set_caps (const struct idpf_adapter * adapter )
154+ {
155+ struct ptp_clock_info * info = & adapter -> ptp -> info ;
156+
157+ snprintf (info -> name , sizeof (info -> name ), "%s-%s-clk" ,
158+ KBUILD_MODNAME , pci_name (adapter -> pdev ));
159+
160+ info -> owner = THIS_MODULE ;
161+ info -> gettimex64 = idpf_ptp_gettimex64 ;
162+ }
163+
7164/**
8165 * idpf_ptp_create_clock - Create PTP clock device for userspace
9166 * @adapter: Driver specific private structure
@@ -16,6 +173,8 @@ static int idpf_ptp_create_clock(const struct idpf_adapter *adapter)
16173{
17174 struct ptp_clock * clock ;
18175
176+ idpf_ptp_set_caps (adapter );
177+
19178 /* Attempt to register the clock before enabling the hardware. */
20179 clock = ptp_clock_register (& adapter -> ptp -> info ,
21180 & adapter -> pdev -> dev );
@@ -56,10 +215,21 @@ int idpf_ptp_init(struct idpf_adapter *adapter)
56215 /* add a back pointer to adapter */
57216 adapter -> ptp -> adapter = adapter ;
58217
218+ if (adapter -> dev_ops .reg_ops .ptp_reg_init )
219+ adapter -> dev_ops .reg_ops .ptp_reg_init (adapter );
220+
221+ err = idpf_ptp_get_caps (adapter );
222+ if (err ) {
223+ pci_err (adapter -> pdev , "Failed to get PTP caps err %d\n" , err );
224+ goto free_ptp ;
225+ }
226+
59227 err = idpf_ptp_create_clock (adapter );
60228 if (err )
61229 goto free_ptp ;
62230
231+ spin_lock_init (& adapter -> ptp -> read_dev_clk_lock );
232+
63233 pci_dbg (adapter -> pdev , "PTP init successful\n" );
64234
65235 return 0 ;
0 commit comments