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