1 /* SPDX-License-Identifier: GPL-2.0 */
2 /* Copyright (c) 2019, Vladimir Oltean <olteanv@gmail.com>
3  */
4 #ifndef _SJA1105_PTP_H
5 #define _SJA1105_PTP_H
6 
7 #if IS_ENABLED(CONFIG_NET_DSA_SJA1105_PTP)
8 
9 /* Timestamps are in units of 8 ns clock ticks (equivalent to
10  * a fixed 125 MHz clock).
11  */
12 #define SJA1105_TICK_NS			8
13 
14 static inline s64 ns_to_sja1105_ticks(s64 ns)
15 {
16 	return ns / SJA1105_TICK_NS;
17 }
18 
19 static inline s64 sja1105_ticks_to_ns(s64 ticks)
20 {
21 	return ticks * SJA1105_TICK_NS;
22 }
23 
24 /* Calculate the first base_time in the future that satisfies this
25  * relationship:
26  *
27  * future_base_time = base_time + N x cycle_time >= now, or
28  *
29  *      now - base_time
30  * N >= ---------------
31  *         cycle_time
32  *
33  * Because N is an integer, the ceiling value of the above "a / b" ratio
34  * is in fact precisely the floor value of "(a + b - 1) / b", which is
35  * easier to calculate only having integer division tools.
36  */
37 static inline s64 future_base_time(s64 base_time, s64 cycle_time, s64 now)
38 {
39 	s64 a, b, n;
40 
41 	if (base_time >= now)
42 		return base_time;
43 
44 	a = now - base_time;
45 	b = cycle_time;
46 	n = div_s64(a + b - 1, b);
47 
48 	return base_time + n * cycle_time;
49 }
50 
51 /* This is not a preprocessor macro because the "ns" argument may or may not be
52  * s64 at caller side. This ensures it is properly type-cast before div_s64.
53  */
54 static inline s64 ns_to_sja1105_delta(s64 ns)
55 {
56 	return div_s64(ns, 200);
57 }
58 
59 static inline s64 sja1105_delta_to_ns(s64 delta)
60 {
61 	return delta * 200;
62 }
63 
64 struct sja1105_ptp_cmd {
65 	u64 startptpcp;		/* start toggling PTP_CLK pin */
66 	u64 stopptpcp;		/* stop toggling PTP_CLK pin */
67 	u64 ptpstrtsch;		/* start schedule */
68 	u64 ptpstopsch;		/* stop schedule */
69 	u64 resptp;		/* reset */
70 	u64 corrclk4ts;		/* use the corrected clock for timestamps */
71 	u64 ptpclkadd;		/* enum sja1105_ptp_clk_mode */
72 };
73 
74 struct sja1105_ptp_data {
75 	struct delayed_work extts_work;
76 	struct sk_buff_head skb_rxtstamp_queue;
77 	struct ptp_clock_info caps;
78 	struct ptp_clock *clock;
79 	struct sja1105_ptp_cmd cmd;
80 	/* Serializes all operations on the PTP hardware clock */
81 	struct mutex lock;
82 	u64 ptpsyncts;
83 };
84 
85 int sja1105_ptp_clock_register(struct dsa_switch *ds);
86 
87 void sja1105_ptp_clock_unregister(struct dsa_switch *ds);
88 
89 void sja1105et_ptp_cmd_packing(u8 *buf, struct sja1105_ptp_cmd *cmd,
90 			       enum packing_op op);
91 
92 void sja1105pqrs_ptp_cmd_packing(u8 *buf, struct sja1105_ptp_cmd *cmd,
93 				 enum packing_op op);
94 
95 int sja1105_get_ts_info(struct dsa_switch *ds, int port,
96 			struct ethtool_ts_info *ts);
97 
98 void sja1105_ptp_txtstamp_skb(struct dsa_switch *ds, int slot,
99 			      struct sk_buff *clone);
100 
101 bool sja1105_port_rxtstamp(struct dsa_switch *ds, int port,
102 			   struct sk_buff *skb, unsigned int type);
103 
104 bool sja1105_port_txtstamp(struct dsa_switch *ds, int port,
105 			   struct sk_buff *skb, unsigned int type);
106 
107 int sja1105_hwtstamp_get(struct dsa_switch *ds, int port, struct ifreq *ifr);
108 
109 int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr);
110 
111 int __sja1105_ptp_gettimex(struct dsa_switch *ds, u64 *ns,
112 			   struct ptp_system_timestamp *sts);
113 
114 int __sja1105_ptp_settime(struct dsa_switch *ds, u64 ns,
115 			  struct ptp_system_timestamp *ptp_sts);
116 
117 int __sja1105_ptp_adjtime(struct dsa_switch *ds, s64 delta);
118 
119 int sja1105_ptp_commit(struct dsa_switch *ds, struct sja1105_ptp_cmd *cmd,
120 		       sja1105_spi_rw_mode_t rw);
121 
122 #else
123 
124 struct sja1105_ptp_cmd;
125 
126 /* Structures cannot be empty in C. Bah!
127  * Keep the mutex as the only element, which is a bit more difficult to
128  * refactor out of sja1105_main.c anyway.
129  */
130 struct sja1105_ptp_data {
131 	struct mutex lock;
132 };
133 
134 static inline int sja1105_ptp_clock_register(struct dsa_switch *ds)
135 {
136 	return 0;
137 }
138 
139 static inline void sja1105_ptp_clock_unregister(struct dsa_switch *ds) { }
140 
141 static inline void sja1105_ptp_txtstamp_skb(struct dsa_switch *ds, int slot,
142 					    struct sk_buff *clone)
143 {
144 }
145 
146 static inline int __sja1105_ptp_gettimex(struct dsa_switch *ds, u64 *ns,
147 					 struct ptp_system_timestamp *sts)
148 {
149 	return 0;
150 }
151 
152 static inline int __sja1105_ptp_settime(struct dsa_switch *ds, u64 ns,
153 					struct ptp_system_timestamp *ptp_sts)
154 {
155 	return 0;
156 }
157 
158 static inline int __sja1105_ptp_adjtime(struct dsa_switch *ds, s64 delta)
159 {
160 	return 0;
161 }
162 
163 static inline int sja1105_ptp_commit(struct dsa_switch *ds,
164 				     struct sja1105_ptp_cmd *cmd,
165 				     sja1105_spi_rw_mode_t rw)
166 {
167 	return 0;
168 }
169 
170 #define sja1105et_ptp_cmd_packing NULL
171 
172 #define sja1105pqrs_ptp_cmd_packing NULL
173 
174 #define sja1105_get_ts_info NULL
175 
176 #define sja1105_port_rxtstamp NULL
177 
178 #define sja1105_port_txtstamp NULL
179 
180 #define sja1105_hwtstamp_get NULL
181 
182 #define sja1105_hwtstamp_set NULL
183 
184 #endif /* IS_ENABLED(CONFIG_NET_DSA_SJA1105_PTP) */
185 
186 #endif /* _SJA1105_PTP_H */
187