xref: /linux/drivers/net/dsa/sja1105/sja1105_ptp.h (revision 834f8933d5ddd732274cb6050252bd1c7cc7349d)
1b790b554SNishad Kamdar /* SPDX-License-Identifier: GPL-2.0 */
2b790b554SNishad Kamdar /* Copyright (c) 2019, Vladimir Oltean <olteanv@gmail.com>
3bb77f36aSVladimir Oltean  */
4bb77f36aSVladimir Oltean #ifndef _SJA1105_PTP_H
5bb77f36aSVladimir Oltean #define _SJA1105_PTP_H
6bb77f36aSVladimir Oltean 
7bb77f36aSVladimir Oltean #if IS_ENABLED(CONFIG_NET_DSA_SJA1105_PTP)
8bb77f36aSVladimir Oltean 
92fb079a2SVladimir Oltean /* Timestamps are in units of 8 ns clock ticks (equivalent to
102fb079a2SVladimir Oltean  * a fixed 125 MHz clock).
112fb079a2SVladimir Oltean  */
122fb079a2SVladimir Oltean #define SJA1105_TICK_NS			8
132fb079a2SVladimir Oltean 
142fb079a2SVladimir Oltean static inline s64 ns_to_sja1105_ticks(s64 ns)
152fb079a2SVladimir Oltean {
162fb079a2SVladimir Oltean 	return ns / SJA1105_TICK_NS;
172fb079a2SVladimir Oltean }
182fb079a2SVladimir Oltean 
192fb079a2SVladimir Oltean static inline s64 sja1105_ticks_to_ns(s64 ticks)
202fb079a2SVladimir Oltean {
212fb079a2SVladimir Oltean 	return ticks * SJA1105_TICK_NS;
222fb079a2SVladimir Oltean }
232fb079a2SVladimir Oltean 
244bfa1616SVladimir Oltean /* Calculate the first base_time in the future that satisfies this
254bfa1616SVladimir Oltean  * relationship:
264bfa1616SVladimir Oltean  *
274bfa1616SVladimir Oltean  * future_base_time = base_time + N x cycle_time >= now, or
284bfa1616SVladimir Oltean  *
294bfa1616SVladimir Oltean  *      now - base_time
304bfa1616SVladimir Oltean  * N >= ---------------
314bfa1616SVladimir Oltean  *         cycle_time
324bfa1616SVladimir Oltean  *
334bfa1616SVladimir Oltean  * Because N is an integer, the ceiling value of the above "a / b" ratio
344bfa1616SVladimir Oltean  * is in fact precisely the floor value of "(a + b - 1) / b", which is
354bfa1616SVladimir Oltean  * easier to calculate only having integer division tools.
364bfa1616SVladimir Oltean  */
374bfa1616SVladimir Oltean static inline s64 future_base_time(s64 base_time, s64 cycle_time, s64 now)
384bfa1616SVladimir Oltean {
394bfa1616SVladimir Oltean 	s64 a, b, n;
404bfa1616SVladimir Oltean 
414bfa1616SVladimir Oltean 	if (base_time >= now)
424bfa1616SVladimir Oltean 		return base_time;
434bfa1616SVladimir Oltean 
444bfa1616SVladimir Oltean 	a = now - base_time;
454bfa1616SVladimir Oltean 	b = cycle_time;
464bfa1616SVladimir Oltean 	n = div_s64(a + b - 1, b);
474bfa1616SVladimir Oltean 
484bfa1616SVladimir Oltean 	return base_time + n * cycle_time;
494bfa1616SVladimir Oltean }
504bfa1616SVladimir Oltean 
51*834f8933SVladimir Oltean /* This is not a preprocessor macro because the "ns" argument may or may not be
52*834f8933SVladimir Oltean  * s64 at caller side. This ensures it is properly type-cast before div_s64.
53*834f8933SVladimir Oltean  */
54*834f8933SVladimir Oltean static inline s64 ns_to_sja1105_delta(s64 ns)
55*834f8933SVladimir Oltean {
56*834f8933SVladimir Oltean 	return div_s64(ns, 200);
57*834f8933SVladimir Oltean }
58*834f8933SVladimir Oltean 
59*834f8933SVladimir Oltean static inline s64 sja1105_delta_to_ns(s64 delta)
60*834f8933SVladimir Oltean {
61*834f8933SVladimir Oltean 	return delta * 200;
62*834f8933SVladimir Oltean }
63*834f8933SVladimir Oltean 
6466427778SVladimir Oltean struct sja1105_ptp_cmd {
65747e5eb3SVladimir Oltean 	u64 startptpcp;		/* start toggling PTP_CLK pin */
66747e5eb3SVladimir Oltean 	u64 stopptpcp;		/* stop toggling PTP_CLK pin */
6786db36a3SVladimir Oltean 	u64 ptpstrtsch;		/* start schedule */
6886db36a3SVladimir Oltean 	u64 ptpstopsch;		/* stop schedule */
6966427778SVladimir Oltean 	u64 resptp;		/* reset */
702fb079a2SVladimir Oltean 	u64 corrclk4ts;		/* use the corrected clock for timestamps */
712fb079a2SVladimir Oltean 	u64 ptpclkadd;		/* enum sja1105_ptp_clk_mode */
7266427778SVladimir Oltean };
7366427778SVladimir Oltean 
74a9d6ed7aSVladimir Oltean struct sja1105_ptp_data {
75747e5eb3SVladimir Oltean 	struct delayed_work extts_work;
761e762bd2SVladimir Oltean 	struct sk_buff_head skb_rxtstamp_queue;
77a9d6ed7aSVladimir Oltean 	struct ptp_clock_info caps;
78a9d6ed7aSVladimir Oltean 	struct ptp_clock *clock;
7966427778SVladimir Oltean 	struct sja1105_ptp_cmd cmd;
802fb079a2SVladimir Oltean 	/* Serializes all operations on the PTP hardware clock */
81a9d6ed7aSVladimir Oltean 	struct mutex lock;
82747e5eb3SVladimir Oltean 	u64 ptpsyncts;
83a9d6ed7aSVladimir Oltean };
84a9d6ed7aSVladimir Oltean 
8561c77126SVladimir Oltean int sja1105_ptp_clock_register(struct dsa_switch *ds);
86bb77f36aSVladimir Oltean 
8761c77126SVladimir Oltean void sja1105_ptp_clock_unregister(struct dsa_switch *ds);
88bb77f36aSVladimir Oltean 
8941603d78SVladimir Oltean void sja1105et_ptp_cmd_packing(u8 *buf, struct sja1105_ptp_cmd *cmd,
9041603d78SVladimir Oltean 			       enum packing_op op);
91bb77f36aSVladimir Oltean 
9241603d78SVladimir Oltean void sja1105pqrs_ptp_cmd_packing(u8 *buf, struct sja1105_ptp_cmd *cmd,
9341603d78SVladimir Oltean 				 enum packing_op op);
94bb77f36aSVladimir Oltean 
95bb77f36aSVladimir Oltean int sja1105_get_ts_info(struct dsa_switch *ds, int port,
96bb77f36aSVladimir Oltean 			struct ethtool_ts_info *ts);
97bb77f36aSVladimir Oltean 
98a9d6ed7aSVladimir Oltean void sja1105_ptp_txtstamp_skb(struct dsa_switch *ds, int slot,
99a9d6ed7aSVladimir Oltean 			      struct sk_buff *clone);
10047ed985eSVladimir Oltean 
101a9d6ed7aSVladimir Oltean bool sja1105_port_rxtstamp(struct dsa_switch *ds, int port,
102a9d6ed7aSVladimir Oltean 			   struct sk_buff *skb, unsigned int type);
103a9d6ed7aSVladimir Oltean 
104a9d6ed7aSVladimir Oltean bool sja1105_port_txtstamp(struct dsa_switch *ds, int port,
105a9d6ed7aSVladimir Oltean 			   struct sk_buff *skb, unsigned int type);
106a9d6ed7aSVladimir Oltean 
107a9d6ed7aSVladimir Oltean int sja1105_hwtstamp_get(struct dsa_switch *ds, int port, struct ifreq *ifr);
108a9d6ed7aSVladimir Oltean 
109a9d6ed7aSVladimir Oltean int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr);
110a9d6ed7aSVladimir Oltean 
1116cf99c13SVladimir Oltean int __sja1105_ptp_gettimex(struct dsa_switch *ds, u64 *ns,
1126cf99c13SVladimir Oltean 			   struct ptp_system_timestamp *sts);
1136cf99c13SVladimir Oltean 
1146cf99c13SVladimir Oltean int __sja1105_ptp_settime(struct dsa_switch *ds, u64 ns,
1156cf99c13SVladimir Oltean 			  struct ptp_system_timestamp *ptp_sts);
1166cf99c13SVladimir Oltean 
1176cf99c13SVladimir Oltean int __sja1105_ptp_adjtime(struct dsa_switch *ds, s64 delta);
1186cf99c13SVladimir Oltean 
11986db36a3SVladimir Oltean int sja1105_ptp_commit(struct dsa_switch *ds, struct sja1105_ptp_cmd *cmd,
12086db36a3SVladimir Oltean 		       sja1105_spi_rw_mode_t rw);
12186db36a3SVladimir Oltean 
122bb77f36aSVladimir Oltean #else
123bb77f36aSVladimir Oltean 
12466427778SVladimir Oltean struct sja1105_ptp_cmd;
12566427778SVladimir Oltean 
126a9d6ed7aSVladimir Oltean /* Structures cannot be empty in C. Bah!
127a9d6ed7aSVladimir Oltean  * Keep the mutex as the only element, which is a bit more difficult to
128a9d6ed7aSVladimir Oltean  * refactor out of sja1105_main.c anyway.
129a9d6ed7aSVladimir Oltean  */
130a9d6ed7aSVladimir Oltean struct sja1105_ptp_data {
131a9d6ed7aSVladimir Oltean 	struct mutex lock;
132a9d6ed7aSVladimir Oltean };
133a9d6ed7aSVladimir Oltean 
13461c77126SVladimir Oltean static inline int sja1105_ptp_clock_register(struct dsa_switch *ds)
135bb77f36aSVladimir Oltean {
136bb77f36aSVladimir Oltean 	return 0;
137bb77f36aSVladimir Oltean }
138bb77f36aSVladimir Oltean 
13961c77126SVladimir Oltean static inline void sja1105_ptp_clock_unregister(struct dsa_switch *ds) { }
140bb77f36aSVladimir Oltean 
141a9d6ed7aSVladimir Oltean static inline void sja1105_ptp_txtstamp_skb(struct dsa_switch *ds, int slot,
142a9d6ed7aSVladimir Oltean 					    struct sk_buff *clone)
14347ed985eSVladimir Oltean {
14447ed985eSVladimir Oltean }
14547ed985eSVladimir Oltean 
1466cf99c13SVladimir Oltean static inline int __sja1105_ptp_gettimex(struct dsa_switch *ds, u64 *ns,
1476cf99c13SVladimir Oltean 					 struct ptp_system_timestamp *sts)
1486cf99c13SVladimir Oltean {
1496cf99c13SVladimir Oltean 	return 0;
1506cf99c13SVladimir Oltean }
1516cf99c13SVladimir Oltean 
1526cf99c13SVladimir Oltean static inline int __sja1105_ptp_settime(struct dsa_switch *ds, u64 ns,
1536cf99c13SVladimir Oltean 					struct ptp_system_timestamp *ptp_sts)
1546cf99c13SVladimir Oltean {
1556cf99c13SVladimir Oltean 	return 0;
1566cf99c13SVladimir Oltean }
1576cf99c13SVladimir Oltean 
1586cf99c13SVladimir Oltean static inline int __sja1105_ptp_adjtime(struct dsa_switch *ds, s64 delta)
159bb77f36aSVladimir Oltean {
160bb77f36aSVladimir Oltean 	return 0;
161bb77f36aSVladimir Oltean }
162bb77f36aSVladimir Oltean 
16386db36a3SVladimir Oltean static inline int sja1105_ptp_commit(struct dsa_switch *ds,
16486db36a3SVladimir Oltean 				     struct sja1105_ptp_cmd *cmd,
16586db36a3SVladimir Oltean 				     sja1105_spi_rw_mode_t rw)
16686db36a3SVladimir Oltean {
16786db36a3SVladimir Oltean 	return 0;
16886db36a3SVladimir Oltean }
16986db36a3SVladimir Oltean 
17041603d78SVladimir Oltean #define sja1105et_ptp_cmd_packing NULL
171bb77f36aSVladimir Oltean 
17241603d78SVladimir Oltean #define sja1105pqrs_ptp_cmd_packing NULL
173bb77f36aSVladimir Oltean 
174bb77f36aSVladimir Oltean #define sja1105_get_ts_info NULL
175bb77f36aSVladimir Oltean 
176a9d6ed7aSVladimir Oltean #define sja1105_port_rxtstamp NULL
177a9d6ed7aSVladimir Oltean 
178a9d6ed7aSVladimir Oltean #define sja1105_port_txtstamp NULL
179a9d6ed7aSVladimir Oltean 
180a9d6ed7aSVladimir Oltean #define sja1105_hwtstamp_get NULL
181a9d6ed7aSVladimir Oltean 
182a9d6ed7aSVladimir Oltean #define sja1105_hwtstamp_set NULL
183a9d6ed7aSVladimir Oltean 
184bb77f36aSVladimir Oltean #endif /* IS_ENABLED(CONFIG_NET_DSA_SJA1105_PTP) */
185bb77f36aSVladimir Oltean 
186bb77f36aSVladimir Oltean #endif /* _SJA1105_PTP_H */
187