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