1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /* Copyright (c) 2019, Vladimir Oltean <olteanv@gmail.com>
3*4882a593Smuzhiyun */
4*4882a593Smuzhiyun #include <linux/spi/spi.h>
5*4882a593Smuzhiyun #include "sja1105.h"
6*4882a593Smuzhiyun
7*4882a593Smuzhiyun /* The adjfine API clamps ppb between [-32,768,000, 32,768,000], and
8*4882a593Smuzhiyun * therefore scaled_ppm between [-2,147,483,648, 2,147,483,647].
9*4882a593Smuzhiyun * Set the maximum supported ppb to a round value smaller than the maximum.
10*4882a593Smuzhiyun *
11*4882a593Smuzhiyun * Percentually speaking, this is a +/- 0.032x adjustment of the
12*4882a593Smuzhiyun * free-running counter (0.968x to 1.032x).
13*4882a593Smuzhiyun */
14*4882a593Smuzhiyun #define SJA1105_MAX_ADJ_PPB 32000000
15*4882a593Smuzhiyun #define SJA1105_SIZE_PTP_CMD 4
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun /* PTPSYNCTS has no interrupt or update mechanism, because the intended
18*4882a593Smuzhiyun * hardware use case is for the timestamp to be collected synchronously,
19*4882a593Smuzhiyun * immediately after the CAS_MASTER SJA1105 switch has performed a CASSYNC
20*4882a593Smuzhiyun * one-shot toggle (no return to level) on the PTP_CLK pin. When used as a
21*4882a593Smuzhiyun * generic extts source, the PTPSYNCTS register needs polling and a comparison
22*4882a593Smuzhiyun * with the old value. The polling interval is configured as the Nyquist rate
23*4882a593Smuzhiyun * of a signal with 50% duty cycle and 1Hz frequency, which is sadly all that
24*4882a593Smuzhiyun * this hardware can do (but may be enough for some setups). Anything of higher
25*4882a593Smuzhiyun * frequency than 1 Hz will be lost, since there is no timestamp FIFO.
26*4882a593Smuzhiyun */
27*4882a593Smuzhiyun #define SJA1105_EXTTS_INTERVAL (HZ / 6)
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun /* This range is actually +/- SJA1105_MAX_ADJ_PPB
30*4882a593Smuzhiyun * divided by 1000 (ppb -> ppm) and with a 16-bit
31*4882a593Smuzhiyun * "fractional" part (actually fixed point).
32*4882a593Smuzhiyun * |
33*4882a593Smuzhiyun * v
34*4882a593Smuzhiyun * Convert scaled_ppm from the +/- ((10^6) << 16) range
35*4882a593Smuzhiyun * into the +/- (1 << 31) range.
36*4882a593Smuzhiyun *
37*4882a593Smuzhiyun * This forgoes a "ppb" numeric representation (up to NSEC_PER_SEC)
38*4882a593Smuzhiyun * and defines the scaling factor between scaled_ppm and the actual
39*4882a593Smuzhiyun * frequency adjustments of the PHC.
40*4882a593Smuzhiyun *
41*4882a593Smuzhiyun * ptpclkrate = scaled_ppm * 2^31 / (10^6 * 2^16)
42*4882a593Smuzhiyun * simplifies to
43*4882a593Smuzhiyun * ptpclkrate = scaled_ppm * 2^9 / 5^6
44*4882a593Smuzhiyun */
45*4882a593Smuzhiyun #define SJA1105_CC_MULT_NUM (1 << 9)
46*4882a593Smuzhiyun #define SJA1105_CC_MULT_DEM 15625
47*4882a593Smuzhiyun #define SJA1105_CC_MULT 0x80000000
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun enum sja1105_ptp_clk_mode {
50*4882a593Smuzhiyun PTP_ADD_MODE = 1,
51*4882a593Smuzhiyun PTP_SET_MODE = 0,
52*4882a593Smuzhiyun };
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun #define extts_to_data(t) \
55*4882a593Smuzhiyun container_of((t), struct sja1105_ptp_data, extts_timer)
56*4882a593Smuzhiyun #define ptp_caps_to_data(d) \
57*4882a593Smuzhiyun container_of((d), struct sja1105_ptp_data, caps)
58*4882a593Smuzhiyun #define ptp_data_to_sja1105(d) \
59*4882a593Smuzhiyun container_of((d), struct sja1105_private, ptp_data)
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun /* Must be called only with priv->tagger_data.state bit
62*4882a593Smuzhiyun * SJA1105_HWTS_RX_EN cleared
63*4882a593Smuzhiyun */
sja1105_change_rxtstamping(struct sja1105_private * priv,bool on)64*4882a593Smuzhiyun static int sja1105_change_rxtstamping(struct sja1105_private *priv,
65*4882a593Smuzhiyun bool on)
66*4882a593Smuzhiyun {
67*4882a593Smuzhiyun struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
68*4882a593Smuzhiyun struct sja1105_general_params_entry *general_params;
69*4882a593Smuzhiyun struct sja1105_table *table;
70*4882a593Smuzhiyun
71*4882a593Smuzhiyun table = &priv->static_config.tables[BLK_IDX_GENERAL_PARAMS];
72*4882a593Smuzhiyun general_params = table->entries;
73*4882a593Smuzhiyun general_params->send_meta1 = on;
74*4882a593Smuzhiyun general_params->send_meta0 = on;
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun /* Initialize the meta state machine to a known state */
77*4882a593Smuzhiyun if (priv->tagger_data.stampable_skb) {
78*4882a593Smuzhiyun kfree_skb(priv->tagger_data.stampable_skb);
79*4882a593Smuzhiyun priv->tagger_data.stampable_skb = NULL;
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun ptp_cancel_worker_sync(ptp_data->clock);
82*4882a593Smuzhiyun skb_queue_purge(&ptp_data->skb_rxtstamp_queue);
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun return sja1105_static_config_reload(priv, SJA1105_RX_HWTSTAMPING);
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun
sja1105_hwtstamp_set(struct dsa_switch * ds,int port,struct ifreq * ifr)87*4882a593Smuzhiyun int sja1105_hwtstamp_set(struct dsa_switch *ds, int port, struct ifreq *ifr)
88*4882a593Smuzhiyun {
89*4882a593Smuzhiyun struct sja1105_private *priv = ds->priv;
90*4882a593Smuzhiyun struct hwtstamp_config config;
91*4882a593Smuzhiyun bool rx_on;
92*4882a593Smuzhiyun int rc;
93*4882a593Smuzhiyun
94*4882a593Smuzhiyun if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
95*4882a593Smuzhiyun return -EFAULT;
96*4882a593Smuzhiyun
97*4882a593Smuzhiyun switch (config.tx_type) {
98*4882a593Smuzhiyun case HWTSTAMP_TX_OFF:
99*4882a593Smuzhiyun priv->ports[port].hwts_tx_en = false;
100*4882a593Smuzhiyun break;
101*4882a593Smuzhiyun case HWTSTAMP_TX_ON:
102*4882a593Smuzhiyun priv->ports[port].hwts_tx_en = true;
103*4882a593Smuzhiyun break;
104*4882a593Smuzhiyun default:
105*4882a593Smuzhiyun return -ERANGE;
106*4882a593Smuzhiyun }
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun switch (config.rx_filter) {
109*4882a593Smuzhiyun case HWTSTAMP_FILTER_NONE:
110*4882a593Smuzhiyun rx_on = false;
111*4882a593Smuzhiyun break;
112*4882a593Smuzhiyun default:
113*4882a593Smuzhiyun rx_on = true;
114*4882a593Smuzhiyun break;
115*4882a593Smuzhiyun }
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun if (rx_on != test_bit(SJA1105_HWTS_RX_EN, &priv->tagger_data.state)) {
118*4882a593Smuzhiyun clear_bit(SJA1105_HWTS_RX_EN, &priv->tagger_data.state);
119*4882a593Smuzhiyun
120*4882a593Smuzhiyun rc = sja1105_change_rxtstamping(priv, rx_on);
121*4882a593Smuzhiyun if (rc < 0) {
122*4882a593Smuzhiyun dev_err(ds->dev,
123*4882a593Smuzhiyun "Failed to change RX timestamping: %d\n", rc);
124*4882a593Smuzhiyun return rc;
125*4882a593Smuzhiyun }
126*4882a593Smuzhiyun if (rx_on)
127*4882a593Smuzhiyun set_bit(SJA1105_HWTS_RX_EN, &priv->tagger_data.state);
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun if (copy_to_user(ifr->ifr_data, &config, sizeof(config)))
131*4882a593Smuzhiyun return -EFAULT;
132*4882a593Smuzhiyun return 0;
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun
sja1105_hwtstamp_get(struct dsa_switch * ds,int port,struct ifreq * ifr)135*4882a593Smuzhiyun int sja1105_hwtstamp_get(struct dsa_switch *ds, int port, struct ifreq *ifr)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun struct sja1105_private *priv = ds->priv;
138*4882a593Smuzhiyun struct hwtstamp_config config;
139*4882a593Smuzhiyun
140*4882a593Smuzhiyun config.flags = 0;
141*4882a593Smuzhiyun if (priv->ports[port].hwts_tx_en)
142*4882a593Smuzhiyun config.tx_type = HWTSTAMP_TX_ON;
143*4882a593Smuzhiyun else
144*4882a593Smuzhiyun config.tx_type = HWTSTAMP_TX_OFF;
145*4882a593Smuzhiyun if (test_bit(SJA1105_HWTS_RX_EN, &priv->tagger_data.state))
146*4882a593Smuzhiyun config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
147*4882a593Smuzhiyun else
148*4882a593Smuzhiyun config.rx_filter = HWTSTAMP_FILTER_NONE;
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ?
151*4882a593Smuzhiyun -EFAULT : 0;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun
sja1105_get_ts_info(struct dsa_switch * ds,int port,struct ethtool_ts_info * info)154*4882a593Smuzhiyun int sja1105_get_ts_info(struct dsa_switch *ds, int port,
155*4882a593Smuzhiyun struct ethtool_ts_info *info)
156*4882a593Smuzhiyun {
157*4882a593Smuzhiyun struct sja1105_private *priv = ds->priv;
158*4882a593Smuzhiyun struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
159*4882a593Smuzhiyun
160*4882a593Smuzhiyun /* Called during cleanup */
161*4882a593Smuzhiyun if (!ptp_data->clock)
162*4882a593Smuzhiyun return -ENODEV;
163*4882a593Smuzhiyun
164*4882a593Smuzhiyun info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
165*4882a593Smuzhiyun SOF_TIMESTAMPING_RX_HARDWARE |
166*4882a593Smuzhiyun SOF_TIMESTAMPING_RAW_HARDWARE;
167*4882a593Smuzhiyun info->tx_types = (1 << HWTSTAMP_TX_OFF) |
168*4882a593Smuzhiyun (1 << HWTSTAMP_TX_ON);
169*4882a593Smuzhiyun info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
170*4882a593Smuzhiyun (1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT);
171*4882a593Smuzhiyun info->phc_index = ptp_clock_index(ptp_data->clock);
172*4882a593Smuzhiyun return 0;
173*4882a593Smuzhiyun }
174*4882a593Smuzhiyun
sja1105et_ptp_cmd_packing(u8 * buf,struct sja1105_ptp_cmd * cmd,enum packing_op op)175*4882a593Smuzhiyun void sja1105et_ptp_cmd_packing(u8 *buf, struct sja1105_ptp_cmd *cmd,
176*4882a593Smuzhiyun enum packing_op op)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun const int size = SJA1105_SIZE_PTP_CMD;
179*4882a593Smuzhiyun /* No need to keep this as part of the structure */
180*4882a593Smuzhiyun u64 valid = 1;
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun sja1105_packing(buf, &valid, 31, 31, size, op);
183*4882a593Smuzhiyun sja1105_packing(buf, &cmd->ptpstrtsch, 30, 30, size, op);
184*4882a593Smuzhiyun sja1105_packing(buf, &cmd->ptpstopsch, 29, 29, size, op);
185*4882a593Smuzhiyun sja1105_packing(buf, &cmd->startptpcp, 28, 28, size, op);
186*4882a593Smuzhiyun sja1105_packing(buf, &cmd->stopptpcp, 27, 27, size, op);
187*4882a593Smuzhiyun sja1105_packing(buf, &cmd->resptp, 2, 2, size, op);
188*4882a593Smuzhiyun sja1105_packing(buf, &cmd->corrclk4ts, 1, 1, size, op);
189*4882a593Smuzhiyun sja1105_packing(buf, &cmd->ptpclkadd, 0, 0, size, op);
190*4882a593Smuzhiyun }
191*4882a593Smuzhiyun
sja1105pqrs_ptp_cmd_packing(u8 * buf,struct sja1105_ptp_cmd * cmd,enum packing_op op)192*4882a593Smuzhiyun void sja1105pqrs_ptp_cmd_packing(u8 *buf, struct sja1105_ptp_cmd *cmd,
193*4882a593Smuzhiyun enum packing_op op)
194*4882a593Smuzhiyun {
195*4882a593Smuzhiyun const int size = SJA1105_SIZE_PTP_CMD;
196*4882a593Smuzhiyun /* No need to keep this as part of the structure */
197*4882a593Smuzhiyun u64 valid = 1;
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun sja1105_packing(buf, &valid, 31, 31, size, op);
200*4882a593Smuzhiyun sja1105_packing(buf, &cmd->ptpstrtsch, 30, 30, size, op);
201*4882a593Smuzhiyun sja1105_packing(buf, &cmd->ptpstopsch, 29, 29, size, op);
202*4882a593Smuzhiyun sja1105_packing(buf, &cmd->startptpcp, 28, 28, size, op);
203*4882a593Smuzhiyun sja1105_packing(buf, &cmd->stopptpcp, 27, 27, size, op);
204*4882a593Smuzhiyun sja1105_packing(buf, &cmd->resptp, 3, 3, size, op);
205*4882a593Smuzhiyun sja1105_packing(buf, &cmd->corrclk4ts, 2, 2, size, op);
206*4882a593Smuzhiyun sja1105_packing(buf, &cmd->ptpclkadd, 0, 0, size, op);
207*4882a593Smuzhiyun }
208*4882a593Smuzhiyun
sja1105_ptp_commit(struct dsa_switch * ds,struct sja1105_ptp_cmd * cmd,sja1105_spi_rw_mode_t rw)209*4882a593Smuzhiyun int sja1105_ptp_commit(struct dsa_switch *ds, struct sja1105_ptp_cmd *cmd,
210*4882a593Smuzhiyun sja1105_spi_rw_mode_t rw)
211*4882a593Smuzhiyun {
212*4882a593Smuzhiyun const struct sja1105_private *priv = ds->priv;
213*4882a593Smuzhiyun const struct sja1105_regs *regs = priv->info->regs;
214*4882a593Smuzhiyun u8 buf[SJA1105_SIZE_PTP_CMD] = {0};
215*4882a593Smuzhiyun int rc;
216*4882a593Smuzhiyun
217*4882a593Smuzhiyun if (rw == SPI_WRITE)
218*4882a593Smuzhiyun priv->info->ptp_cmd_packing(buf, cmd, PACK);
219*4882a593Smuzhiyun
220*4882a593Smuzhiyun rc = sja1105_xfer_buf(priv, rw, regs->ptp_control, buf,
221*4882a593Smuzhiyun SJA1105_SIZE_PTP_CMD);
222*4882a593Smuzhiyun
223*4882a593Smuzhiyun if (rw == SPI_READ)
224*4882a593Smuzhiyun priv->info->ptp_cmd_packing(buf, cmd, UNPACK);
225*4882a593Smuzhiyun
226*4882a593Smuzhiyun return rc;
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun /* The switch returns partial timestamps (24 bits for SJA1105 E/T, which wrap
230*4882a593Smuzhiyun * around in 0.135 seconds, and 32 bits for P/Q/R/S, wrapping around in 34.35
231*4882a593Smuzhiyun * seconds).
232*4882a593Smuzhiyun *
233*4882a593Smuzhiyun * This receives the RX or TX MAC timestamps, provided by hardware as
234*4882a593Smuzhiyun * the lower bits of the cycle counter, sampled at the time the timestamp was
235*4882a593Smuzhiyun * collected.
236*4882a593Smuzhiyun *
237*4882a593Smuzhiyun * To reconstruct into a full 64-bit-wide timestamp, the cycle counter is
238*4882a593Smuzhiyun * read and the high-order bits are filled in.
239*4882a593Smuzhiyun *
240*4882a593Smuzhiyun * Must be called within one wraparound period of the partial timestamp since
241*4882a593Smuzhiyun * it was generated by the MAC.
242*4882a593Smuzhiyun */
sja1105_tstamp_reconstruct(struct dsa_switch * ds,u64 now,u64 ts_partial)243*4882a593Smuzhiyun static u64 sja1105_tstamp_reconstruct(struct dsa_switch *ds, u64 now,
244*4882a593Smuzhiyun u64 ts_partial)
245*4882a593Smuzhiyun {
246*4882a593Smuzhiyun struct sja1105_private *priv = ds->priv;
247*4882a593Smuzhiyun u64 partial_tstamp_mask = CYCLECOUNTER_MASK(priv->info->ptp_ts_bits);
248*4882a593Smuzhiyun u64 ts_reconstructed;
249*4882a593Smuzhiyun
250*4882a593Smuzhiyun ts_reconstructed = (now & ~partial_tstamp_mask) | ts_partial;
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun /* Check lower bits of current cycle counter against the timestamp.
253*4882a593Smuzhiyun * If the current cycle counter is lower than the partial timestamp,
254*4882a593Smuzhiyun * then wraparound surely occurred and must be accounted for.
255*4882a593Smuzhiyun */
256*4882a593Smuzhiyun if ((now & partial_tstamp_mask) <= ts_partial)
257*4882a593Smuzhiyun ts_reconstructed -= (partial_tstamp_mask + 1);
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun return ts_reconstructed;
260*4882a593Smuzhiyun }
261*4882a593Smuzhiyun
262*4882a593Smuzhiyun /* Reads the SPI interface for an egress timestamp generated by the switch
263*4882a593Smuzhiyun * for frames sent using management routes.
264*4882a593Smuzhiyun *
265*4882a593Smuzhiyun * SJA1105 E/T layout of the 4-byte SPI payload:
266*4882a593Smuzhiyun *
267*4882a593Smuzhiyun * 31 23 15 7 0
268*4882a593Smuzhiyun * | | | | |
269*4882a593Smuzhiyun * +-----+-----+-----+ ^
270*4882a593Smuzhiyun * ^ |
271*4882a593Smuzhiyun * | |
272*4882a593Smuzhiyun * 24-bit timestamp Update bit
273*4882a593Smuzhiyun *
274*4882a593Smuzhiyun *
275*4882a593Smuzhiyun * SJA1105 P/Q/R/S layout of the 8-byte SPI payload:
276*4882a593Smuzhiyun *
277*4882a593Smuzhiyun * 31 23 15 7 0 63 55 47 39 32
278*4882a593Smuzhiyun * | | | | | | | | | |
279*4882a593Smuzhiyun * ^ +-----+-----+-----+-----+
280*4882a593Smuzhiyun * | ^
281*4882a593Smuzhiyun * | |
282*4882a593Smuzhiyun * Update bit 32-bit timestamp
283*4882a593Smuzhiyun *
284*4882a593Smuzhiyun * Notice that the update bit is in the same place.
285*4882a593Smuzhiyun * To have common code for E/T and P/Q/R/S for reading the timestamp,
286*4882a593Smuzhiyun * we need to juggle with the offset and the bit indices.
287*4882a593Smuzhiyun */
sja1105_ptpegr_ts_poll(struct dsa_switch * ds,int port,u64 * ts)288*4882a593Smuzhiyun static int sja1105_ptpegr_ts_poll(struct dsa_switch *ds, int port, u64 *ts)
289*4882a593Smuzhiyun {
290*4882a593Smuzhiyun struct sja1105_private *priv = ds->priv;
291*4882a593Smuzhiyun const struct sja1105_regs *regs = priv->info->regs;
292*4882a593Smuzhiyun int tstamp_bit_start, tstamp_bit_end;
293*4882a593Smuzhiyun int timeout = 10;
294*4882a593Smuzhiyun u8 packed_buf[8];
295*4882a593Smuzhiyun u64 update;
296*4882a593Smuzhiyun int rc;
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun do {
299*4882a593Smuzhiyun rc = sja1105_xfer_buf(priv, SPI_READ, regs->ptpegr_ts[port],
300*4882a593Smuzhiyun packed_buf, priv->info->ptpegr_ts_bytes);
301*4882a593Smuzhiyun if (rc < 0)
302*4882a593Smuzhiyun return rc;
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun sja1105_unpack(packed_buf, &update, 0, 0,
305*4882a593Smuzhiyun priv->info->ptpegr_ts_bytes);
306*4882a593Smuzhiyun if (update)
307*4882a593Smuzhiyun break;
308*4882a593Smuzhiyun
309*4882a593Smuzhiyun usleep_range(10, 50);
310*4882a593Smuzhiyun } while (--timeout);
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun if (!timeout)
313*4882a593Smuzhiyun return -ETIMEDOUT;
314*4882a593Smuzhiyun
315*4882a593Smuzhiyun /* Point the end bit to the second 32-bit word on P/Q/R/S,
316*4882a593Smuzhiyun * no-op on E/T.
317*4882a593Smuzhiyun */
318*4882a593Smuzhiyun tstamp_bit_end = (priv->info->ptpegr_ts_bytes - 4) * 8;
319*4882a593Smuzhiyun /* Shift the 24-bit timestamp on E/T to be collected from 31:8.
320*4882a593Smuzhiyun * No-op on P/Q/R/S.
321*4882a593Smuzhiyun */
322*4882a593Smuzhiyun tstamp_bit_end += 32 - priv->info->ptp_ts_bits;
323*4882a593Smuzhiyun tstamp_bit_start = tstamp_bit_end + priv->info->ptp_ts_bits - 1;
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun *ts = 0;
326*4882a593Smuzhiyun
327*4882a593Smuzhiyun sja1105_unpack(packed_buf, ts, tstamp_bit_start, tstamp_bit_end,
328*4882a593Smuzhiyun priv->info->ptpegr_ts_bytes);
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun return 0;
331*4882a593Smuzhiyun }
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun /* Caller must hold ptp_data->lock */
sja1105_ptpclkval_read(struct sja1105_private * priv,u64 * ticks,struct ptp_system_timestamp * ptp_sts)334*4882a593Smuzhiyun static int sja1105_ptpclkval_read(struct sja1105_private *priv, u64 *ticks,
335*4882a593Smuzhiyun struct ptp_system_timestamp *ptp_sts)
336*4882a593Smuzhiyun {
337*4882a593Smuzhiyun const struct sja1105_regs *regs = priv->info->regs;
338*4882a593Smuzhiyun
339*4882a593Smuzhiyun return sja1105_xfer_u64(priv, SPI_READ, regs->ptpclkval, ticks,
340*4882a593Smuzhiyun ptp_sts);
341*4882a593Smuzhiyun }
342*4882a593Smuzhiyun
343*4882a593Smuzhiyun /* Caller must hold ptp_data->lock */
sja1105_ptpclkval_write(struct sja1105_private * priv,u64 ticks,struct ptp_system_timestamp * ptp_sts)344*4882a593Smuzhiyun static int sja1105_ptpclkval_write(struct sja1105_private *priv, u64 ticks,
345*4882a593Smuzhiyun struct ptp_system_timestamp *ptp_sts)
346*4882a593Smuzhiyun {
347*4882a593Smuzhiyun const struct sja1105_regs *regs = priv->info->regs;
348*4882a593Smuzhiyun
349*4882a593Smuzhiyun return sja1105_xfer_u64(priv, SPI_WRITE, regs->ptpclkval, &ticks,
350*4882a593Smuzhiyun ptp_sts);
351*4882a593Smuzhiyun }
352*4882a593Smuzhiyun
sja1105_extts_poll(struct sja1105_private * priv)353*4882a593Smuzhiyun static void sja1105_extts_poll(struct sja1105_private *priv)
354*4882a593Smuzhiyun {
355*4882a593Smuzhiyun struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
356*4882a593Smuzhiyun const struct sja1105_regs *regs = priv->info->regs;
357*4882a593Smuzhiyun struct ptp_clock_event event;
358*4882a593Smuzhiyun u64 ptpsyncts = 0;
359*4882a593Smuzhiyun int rc;
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun rc = sja1105_xfer_u64(priv, SPI_READ, regs->ptpsyncts, &ptpsyncts,
362*4882a593Smuzhiyun NULL);
363*4882a593Smuzhiyun if (rc < 0)
364*4882a593Smuzhiyun dev_err_ratelimited(priv->ds->dev,
365*4882a593Smuzhiyun "Failed to read PTPSYNCTS: %d\n", rc);
366*4882a593Smuzhiyun
367*4882a593Smuzhiyun if (ptpsyncts && ptp_data->ptpsyncts != ptpsyncts) {
368*4882a593Smuzhiyun event.index = 0;
369*4882a593Smuzhiyun event.type = PTP_CLOCK_EXTTS;
370*4882a593Smuzhiyun event.timestamp = ns_to_ktime(sja1105_ticks_to_ns(ptpsyncts));
371*4882a593Smuzhiyun ptp_clock_event(ptp_data->clock, &event);
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun ptp_data->ptpsyncts = ptpsyncts;
374*4882a593Smuzhiyun }
375*4882a593Smuzhiyun }
376*4882a593Smuzhiyun
sja1105_rxtstamp_work(struct ptp_clock_info * ptp)377*4882a593Smuzhiyun static long sja1105_rxtstamp_work(struct ptp_clock_info *ptp)
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun struct sja1105_ptp_data *ptp_data = ptp_caps_to_data(ptp);
380*4882a593Smuzhiyun struct sja1105_private *priv = ptp_data_to_sja1105(ptp_data);
381*4882a593Smuzhiyun struct dsa_switch *ds = priv->ds;
382*4882a593Smuzhiyun struct sk_buff *skb;
383*4882a593Smuzhiyun
384*4882a593Smuzhiyun mutex_lock(&ptp_data->lock);
385*4882a593Smuzhiyun
386*4882a593Smuzhiyun while ((skb = skb_dequeue(&ptp_data->skb_rxtstamp_queue)) != NULL) {
387*4882a593Smuzhiyun struct skb_shared_hwtstamps *shwt = skb_hwtstamps(skb);
388*4882a593Smuzhiyun u64 ticks, ts;
389*4882a593Smuzhiyun int rc;
390*4882a593Smuzhiyun
391*4882a593Smuzhiyun rc = sja1105_ptpclkval_read(priv, &ticks, NULL);
392*4882a593Smuzhiyun if (rc < 0) {
393*4882a593Smuzhiyun dev_err(ds->dev, "Failed to read PTP clock: %d\n", rc);
394*4882a593Smuzhiyun kfree_skb(skb);
395*4882a593Smuzhiyun continue;
396*4882a593Smuzhiyun }
397*4882a593Smuzhiyun
398*4882a593Smuzhiyun *shwt = (struct skb_shared_hwtstamps) {0};
399*4882a593Smuzhiyun
400*4882a593Smuzhiyun ts = SJA1105_SKB_CB(skb)->meta_tstamp;
401*4882a593Smuzhiyun ts = sja1105_tstamp_reconstruct(ds, ticks, ts);
402*4882a593Smuzhiyun
403*4882a593Smuzhiyun shwt->hwtstamp = ns_to_ktime(sja1105_ticks_to_ns(ts));
404*4882a593Smuzhiyun netif_rx_ni(skb);
405*4882a593Smuzhiyun }
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun if (ptp_data->extts_enabled)
408*4882a593Smuzhiyun sja1105_extts_poll(priv);
409*4882a593Smuzhiyun
410*4882a593Smuzhiyun mutex_unlock(&ptp_data->lock);
411*4882a593Smuzhiyun
412*4882a593Smuzhiyun /* Don't restart */
413*4882a593Smuzhiyun return -1;
414*4882a593Smuzhiyun }
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun /* Called from dsa_skb_defer_rx_timestamp */
sja1105_port_rxtstamp(struct dsa_switch * ds,int port,struct sk_buff * skb,unsigned int type)417*4882a593Smuzhiyun bool sja1105_port_rxtstamp(struct dsa_switch *ds, int port,
418*4882a593Smuzhiyun struct sk_buff *skb, unsigned int type)
419*4882a593Smuzhiyun {
420*4882a593Smuzhiyun struct sja1105_private *priv = ds->priv;
421*4882a593Smuzhiyun struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun if (!test_bit(SJA1105_HWTS_RX_EN, &priv->tagger_data.state))
424*4882a593Smuzhiyun return false;
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun /* We need to read the full PTP clock to reconstruct the Rx
427*4882a593Smuzhiyun * timestamp. For that we need a sleepable context.
428*4882a593Smuzhiyun */
429*4882a593Smuzhiyun skb_queue_tail(&ptp_data->skb_rxtstamp_queue, skb);
430*4882a593Smuzhiyun ptp_schedule_worker(ptp_data->clock, 0);
431*4882a593Smuzhiyun return true;
432*4882a593Smuzhiyun }
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun /* Called from dsa_skb_tx_timestamp. This callback is just to make DSA clone
435*4882a593Smuzhiyun * the skb and have it available in DSA_SKB_CB in the .port_deferred_xmit
436*4882a593Smuzhiyun * callback, where we will timestamp it synchronously.
437*4882a593Smuzhiyun */
sja1105_port_txtstamp(struct dsa_switch * ds,int port,struct sk_buff * skb,unsigned int type)438*4882a593Smuzhiyun bool sja1105_port_txtstamp(struct dsa_switch *ds, int port,
439*4882a593Smuzhiyun struct sk_buff *skb, unsigned int type)
440*4882a593Smuzhiyun {
441*4882a593Smuzhiyun struct sja1105_private *priv = ds->priv;
442*4882a593Smuzhiyun struct sja1105_port *sp = &priv->ports[port];
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun if (!sp->hwts_tx_en)
445*4882a593Smuzhiyun return false;
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun return true;
448*4882a593Smuzhiyun }
449*4882a593Smuzhiyun
sja1105_ptp_reset(struct dsa_switch * ds)450*4882a593Smuzhiyun static int sja1105_ptp_reset(struct dsa_switch *ds)
451*4882a593Smuzhiyun {
452*4882a593Smuzhiyun struct sja1105_private *priv = ds->priv;
453*4882a593Smuzhiyun struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
454*4882a593Smuzhiyun struct sja1105_ptp_cmd cmd = ptp_data->cmd;
455*4882a593Smuzhiyun int rc;
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun mutex_lock(&ptp_data->lock);
458*4882a593Smuzhiyun
459*4882a593Smuzhiyun cmd.resptp = 1;
460*4882a593Smuzhiyun
461*4882a593Smuzhiyun dev_dbg(ds->dev, "Resetting PTP clock\n");
462*4882a593Smuzhiyun rc = sja1105_ptp_commit(ds, &cmd, SPI_WRITE);
463*4882a593Smuzhiyun
464*4882a593Smuzhiyun sja1105_tas_clockstep(priv->ds);
465*4882a593Smuzhiyun
466*4882a593Smuzhiyun mutex_unlock(&ptp_data->lock);
467*4882a593Smuzhiyun
468*4882a593Smuzhiyun return rc;
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun
471*4882a593Smuzhiyun /* Caller must hold ptp_data->lock */
__sja1105_ptp_gettimex(struct dsa_switch * ds,u64 * ns,struct ptp_system_timestamp * ptp_sts)472*4882a593Smuzhiyun int __sja1105_ptp_gettimex(struct dsa_switch *ds, u64 *ns,
473*4882a593Smuzhiyun struct ptp_system_timestamp *ptp_sts)
474*4882a593Smuzhiyun {
475*4882a593Smuzhiyun struct sja1105_private *priv = ds->priv;
476*4882a593Smuzhiyun u64 ticks;
477*4882a593Smuzhiyun int rc;
478*4882a593Smuzhiyun
479*4882a593Smuzhiyun rc = sja1105_ptpclkval_read(priv, &ticks, ptp_sts);
480*4882a593Smuzhiyun if (rc < 0) {
481*4882a593Smuzhiyun dev_err(ds->dev, "Failed to read PTP clock: %d\n", rc);
482*4882a593Smuzhiyun return rc;
483*4882a593Smuzhiyun }
484*4882a593Smuzhiyun
485*4882a593Smuzhiyun *ns = sja1105_ticks_to_ns(ticks);
486*4882a593Smuzhiyun
487*4882a593Smuzhiyun return 0;
488*4882a593Smuzhiyun }
489*4882a593Smuzhiyun
sja1105_ptp_gettimex(struct ptp_clock_info * ptp,struct timespec64 * ts,struct ptp_system_timestamp * ptp_sts)490*4882a593Smuzhiyun static int sja1105_ptp_gettimex(struct ptp_clock_info *ptp,
491*4882a593Smuzhiyun struct timespec64 *ts,
492*4882a593Smuzhiyun struct ptp_system_timestamp *ptp_sts)
493*4882a593Smuzhiyun {
494*4882a593Smuzhiyun struct sja1105_ptp_data *ptp_data = ptp_caps_to_data(ptp);
495*4882a593Smuzhiyun struct sja1105_private *priv = ptp_data_to_sja1105(ptp_data);
496*4882a593Smuzhiyun u64 now = 0;
497*4882a593Smuzhiyun int rc;
498*4882a593Smuzhiyun
499*4882a593Smuzhiyun mutex_lock(&ptp_data->lock);
500*4882a593Smuzhiyun
501*4882a593Smuzhiyun rc = __sja1105_ptp_gettimex(priv->ds, &now, ptp_sts);
502*4882a593Smuzhiyun *ts = ns_to_timespec64(now);
503*4882a593Smuzhiyun
504*4882a593Smuzhiyun mutex_unlock(&ptp_data->lock);
505*4882a593Smuzhiyun
506*4882a593Smuzhiyun return rc;
507*4882a593Smuzhiyun }
508*4882a593Smuzhiyun
509*4882a593Smuzhiyun /* Caller must hold ptp_data->lock */
sja1105_ptp_mode_set(struct sja1105_private * priv,enum sja1105_ptp_clk_mode mode)510*4882a593Smuzhiyun static int sja1105_ptp_mode_set(struct sja1105_private *priv,
511*4882a593Smuzhiyun enum sja1105_ptp_clk_mode mode)
512*4882a593Smuzhiyun {
513*4882a593Smuzhiyun struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
514*4882a593Smuzhiyun
515*4882a593Smuzhiyun if (ptp_data->cmd.ptpclkadd == mode)
516*4882a593Smuzhiyun return 0;
517*4882a593Smuzhiyun
518*4882a593Smuzhiyun ptp_data->cmd.ptpclkadd = mode;
519*4882a593Smuzhiyun
520*4882a593Smuzhiyun return sja1105_ptp_commit(priv->ds, &ptp_data->cmd, SPI_WRITE);
521*4882a593Smuzhiyun }
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun /* Write to PTPCLKVAL while PTPCLKADD is 0 */
__sja1105_ptp_settime(struct dsa_switch * ds,u64 ns,struct ptp_system_timestamp * ptp_sts)524*4882a593Smuzhiyun int __sja1105_ptp_settime(struct dsa_switch *ds, u64 ns,
525*4882a593Smuzhiyun struct ptp_system_timestamp *ptp_sts)
526*4882a593Smuzhiyun {
527*4882a593Smuzhiyun struct sja1105_private *priv = ds->priv;
528*4882a593Smuzhiyun u64 ticks = ns_to_sja1105_ticks(ns);
529*4882a593Smuzhiyun int rc;
530*4882a593Smuzhiyun
531*4882a593Smuzhiyun rc = sja1105_ptp_mode_set(priv, PTP_SET_MODE);
532*4882a593Smuzhiyun if (rc < 0) {
533*4882a593Smuzhiyun dev_err(priv->ds->dev, "Failed to put PTPCLK in set mode\n");
534*4882a593Smuzhiyun return rc;
535*4882a593Smuzhiyun }
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun rc = sja1105_ptpclkval_write(priv, ticks, ptp_sts);
538*4882a593Smuzhiyun
539*4882a593Smuzhiyun sja1105_tas_clockstep(priv->ds);
540*4882a593Smuzhiyun
541*4882a593Smuzhiyun return rc;
542*4882a593Smuzhiyun }
543*4882a593Smuzhiyun
sja1105_ptp_settime(struct ptp_clock_info * ptp,const struct timespec64 * ts)544*4882a593Smuzhiyun static int sja1105_ptp_settime(struct ptp_clock_info *ptp,
545*4882a593Smuzhiyun const struct timespec64 *ts)
546*4882a593Smuzhiyun {
547*4882a593Smuzhiyun struct sja1105_ptp_data *ptp_data = ptp_caps_to_data(ptp);
548*4882a593Smuzhiyun struct sja1105_private *priv = ptp_data_to_sja1105(ptp_data);
549*4882a593Smuzhiyun u64 ns = timespec64_to_ns(ts);
550*4882a593Smuzhiyun int rc;
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun mutex_lock(&ptp_data->lock);
553*4882a593Smuzhiyun
554*4882a593Smuzhiyun rc = __sja1105_ptp_settime(priv->ds, ns, NULL);
555*4882a593Smuzhiyun
556*4882a593Smuzhiyun mutex_unlock(&ptp_data->lock);
557*4882a593Smuzhiyun
558*4882a593Smuzhiyun return rc;
559*4882a593Smuzhiyun }
560*4882a593Smuzhiyun
sja1105_ptp_adjfine(struct ptp_clock_info * ptp,long scaled_ppm)561*4882a593Smuzhiyun static int sja1105_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
562*4882a593Smuzhiyun {
563*4882a593Smuzhiyun struct sja1105_ptp_data *ptp_data = ptp_caps_to_data(ptp);
564*4882a593Smuzhiyun struct sja1105_private *priv = ptp_data_to_sja1105(ptp_data);
565*4882a593Smuzhiyun const struct sja1105_regs *regs = priv->info->regs;
566*4882a593Smuzhiyun u32 clkrate32;
567*4882a593Smuzhiyun s64 clkrate;
568*4882a593Smuzhiyun int rc;
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun clkrate = (s64)scaled_ppm * SJA1105_CC_MULT_NUM;
571*4882a593Smuzhiyun clkrate = div_s64(clkrate, SJA1105_CC_MULT_DEM);
572*4882a593Smuzhiyun
573*4882a593Smuzhiyun /* Take a +/- value and re-center it around 2^31. */
574*4882a593Smuzhiyun clkrate = SJA1105_CC_MULT + clkrate;
575*4882a593Smuzhiyun WARN_ON(abs(clkrate) >= GENMASK_ULL(31, 0));
576*4882a593Smuzhiyun clkrate32 = clkrate;
577*4882a593Smuzhiyun
578*4882a593Smuzhiyun mutex_lock(&ptp_data->lock);
579*4882a593Smuzhiyun
580*4882a593Smuzhiyun rc = sja1105_xfer_u32(priv, SPI_WRITE, regs->ptpclkrate, &clkrate32,
581*4882a593Smuzhiyun NULL);
582*4882a593Smuzhiyun
583*4882a593Smuzhiyun sja1105_tas_adjfreq(priv->ds);
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun mutex_unlock(&ptp_data->lock);
586*4882a593Smuzhiyun
587*4882a593Smuzhiyun return rc;
588*4882a593Smuzhiyun }
589*4882a593Smuzhiyun
590*4882a593Smuzhiyun /* Write to PTPCLKVAL while PTPCLKADD is 1 */
__sja1105_ptp_adjtime(struct dsa_switch * ds,s64 delta)591*4882a593Smuzhiyun int __sja1105_ptp_adjtime(struct dsa_switch *ds, s64 delta)
592*4882a593Smuzhiyun {
593*4882a593Smuzhiyun struct sja1105_private *priv = ds->priv;
594*4882a593Smuzhiyun s64 ticks = ns_to_sja1105_ticks(delta);
595*4882a593Smuzhiyun int rc;
596*4882a593Smuzhiyun
597*4882a593Smuzhiyun rc = sja1105_ptp_mode_set(priv, PTP_ADD_MODE);
598*4882a593Smuzhiyun if (rc < 0) {
599*4882a593Smuzhiyun dev_err(priv->ds->dev, "Failed to put PTPCLK in add mode\n");
600*4882a593Smuzhiyun return rc;
601*4882a593Smuzhiyun }
602*4882a593Smuzhiyun
603*4882a593Smuzhiyun rc = sja1105_ptpclkval_write(priv, ticks, NULL);
604*4882a593Smuzhiyun
605*4882a593Smuzhiyun sja1105_tas_clockstep(priv->ds);
606*4882a593Smuzhiyun
607*4882a593Smuzhiyun return rc;
608*4882a593Smuzhiyun }
609*4882a593Smuzhiyun
sja1105_ptp_adjtime(struct ptp_clock_info * ptp,s64 delta)610*4882a593Smuzhiyun static int sja1105_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)
611*4882a593Smuzhiyun {
612*4882a593Smuzhiyun struct sja1105_ptp_data *ptp_data = ptp_caps_to_data(ptp);
613*4882a593Smuzhiyun struct sja1105_private *priv = ptp_data_to_sja1105(ptp_data);
614*4882a593Smuzhiyun int rc;
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun mutex_lock(&ptp_data->lock);
617*4882a593Smuzhiyun
618*4882a593Smuzhiyun rc = __sja1105_ptp_adjtime(priv->ds, delta);
619*4882a593Smuzhiyun
620*4882a593Smuzhiyun mutex_unlock(&ptp_data->lock);
621*4882a593Smuzhiyun
622*4882a593Smuzhiyun return rc;
623*4882a593Smuzhiyun }
624*4882a593Smuzhiyun
sja1105_ptp_extts_setup_timer(struct sja1105_ptp_data * ptp_data)625*4882a593Smuzhiyun static void sja1105_ptp_extts_setup_timer(struct sja1105_ptp_data *ptp_data)
626*4882a593Smuzhiyun {
627*4882a593Smuzhiyun unsigned long expires = ((jiffies / SJA1105_EXTTS_INTERVAL) + 1) *
628*4882a593Smuzhiyun SJA1105_EXTTS_INTERVAL;
629*4882a593Smuzhiyun
630*4882a593Smuzhiyun mod_timer(&ptp_data->extts_timer, expires);
631*4882a593Smuzhiyun }
632*4882a593Smuzhiyun
sja1105_ptp_extts_timer(struct timer_list * t)633*4882a593Smuzhiyun static void sja1105_ptp_extts_timer(struct timer_list *t)
634*4882a593Smuzhiyun {
635*4882a593Smuzhiyun struct sja1105_ptp_data *ptp_data = extts_to_data(t);
636*4882a593Smuzhiyun
637*4882a593Smuzhiyun ptp_schedule_worker(ptp_data->clock, 0);
638*4882a593Smuzhiyun
639*4882a593Smuzhiyun sja1105_ptp_extts_setup_timer(ptp_data);
640*4882a593Smuzhiyun }
641*4882a593Smuzhiyun
sja1105_change_ptp_clk_pin_func(struct sja1105_private * priv,enum ptp_pin_function func)642*4882a593Smuzhiyun static int sja1105_change_ptp_clk_pin_func(struct sja1105_private *priv,
643*4882a593Smuzhiyun enum ptp_pin_function func)
644*4882a593Smuzhiyun {
645*4882a593Smuzhiyun struct sja1105_avb_params_entry *avb;
646*4882a593Smuzhiyun enum ptp_pin_function old_func;
647*4882a593Smuzhiyun
648*4882a593Smuzhiyun avb = priv->static_config.tables[BLK_IDX_AVB_PARAMS].entries;
649*4882a593Smuzhiyun
650*4882a593Smuzhiyun if (priv->info->device_id == SJA1105E_DEVICE_ID ||
651*4882a593Smuzhiyun priv->info->device_id == SJA1105T_DEVICE_ID ||
652*4882a593Smuzhiyun avb->cas_master)
653*4882a593Smuzhiyun old_func = PTP_PF_PEROUT;
654*4882a593Smuzhiyun else
655*4882a593Smuzhiyun old_func = PTP_PF_EXTTS;
656*4882a593Smuzhiyun
657*4882a593Smuzhiyun if (func == old_func)
658*4882a593Smuzhiyun return 0;
659*4882a593Smuzhiyun
660*4882a593Smuzhiyun avb->cas_master = (func == PTP_PF_PEROUT);
661*4882a593Smuzhiyun
662*4882a593Smuzhiyun return sja1105_dynamic_config_write(priv, BLK_IDX_AVB_PARAMS, 0, avb,
663*4882a593Smuzhiyun true);
664*4882a593Smuzhiyun }
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun /* The PTP_CLK pin may be configured to toggle with a 50% duty cycle and a
667*4882a593Smuzhiyun * frequency f:
668*4882a593Smuzhiyun *
669*4882a593Smuzhiyun * NSEC_PER_SEC
670*4882a593Smuzhiyun * f = ----------------------
671*4882a593Smuzhiyun * (PTPPINDUR * 8 ns) * 2
672*4882a593Smuzhiyun */
sja1105_per_out_enable(struct sja1105_private * priv,struct ptp_perout_request * perout,bool on)673*4882a593Smuzhiyun static int sja1105_per_out_enable(struct sja1105_private *priv,
674*4882a593Smuzhiyun struct ptp_perout_request *perout,
675*4882a593Smuzhiyun bool on)
676*4882a593Smuzhiyun {
677*4882a593Smuzhiyun struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
678*4882a593Smuzhiyun const struct sja1105_regs *regs = priv->info->regs;
679*4882a593Smuzhiyun struct sja1105_ptp_cmd cmd = ptp_data->cmd;
680*4882a593Smuzhiyun int rc;
681*4882a593Smuzhiyun
682*4882a593Smuzhiyun /* We only support one channel */
683*4882a593Smuzhiyun if (perout->index != 0)
684*4882a593Smuzhiyun return -EOPNOTSUPP;
685*4882a593Smuzhiyun
686*4882a593Smuzhiyun /* Reject requests with unsupported flags */
687*4882a593Smuzhiyun if (perout->flags)
688*4882a593Smuzhiyun return -EOPNOTSUPP;
689*4882a593Smuzhiyun
690*4882a593Smuzhiyun mutex_lock(&ptp_data->lock);
691*4882a593Smuzhiyun
692*4882a593Smuzhiyun rc = sja1105_change_ptp_clk_pin_func(priv, PTP_PF_PEROUT);
693*4882a593Smuzhiyun if (rc)
694*4882a593Smuzhiyun goto out;
695*4882a593Smuzhiyun
696*4882a593Smuzhiyun if (on) {
697*4882a593Smuzhiyun struct timespec64 pin_duration_ts = {
698*4882a593Smuzhiyun .tv_sec = perout->period.sec,
699*4882a593Smuzhiyun .tv_nsec = perout->period.nsec,
700*4882a593Smuzhiyun };
701*4882a593Smuzhiyun struct timespec64 pin_start_ts = {
702*4882a593Smuzhiyun .tv_sec = perout->start.sec,
703*4882a593Smuzhiyun .tv_nsec = perout->start.nsec,
704*4882a593Smuzhiyun };
705*4882a593Smuzhiyun u64 pin_duration = timespec64_to_ns(&pin_duration_ts);
706*4882a593Smuzhiyun u64 pin_start = timespec64_to_ns(&pin_start_ts);
707*4882a593Smuzhiyun u32 pin_duration32;
708*4882a593Smuzhiyun u64 now;
709*4882a593Smuzhiyun
710*4882a593Smuzhiyun /* ptppindur: 32 bit register which holds the interval between
711*4882a593Smuzhiyun * 2 edges on PTP_CLK. So check for truncation which happens
712*4882a593Smuzhiyun * at periods larger than around 68.7 seconds.
713*4882a593Smuzhiyun */
714*4882a593Smuzhiyun pin_duration = ns_to_sja1105_ticks(pin_duration / 2);
715*4882a593Smuzhiyun if (pin_duration > U32_MAX) {
716*4882a593Smuzhiyun rc = -ERANGE;
717*4882a593Smuzhiyun goto out;
718*4882a593Smuzhiyun }
719*4882a593Smuzhiyun pin_duration32 = pin_duration;
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun /* ptppins: 64 bit register which needs to hold a PTP time
722*4882a593Smuzhiyun * larger than the current time, otherwise the startptpcp
723*4882a593Smuzhiyun * command won't do anything. So advance the current time
724*4882a593Smuzhiyun * by a number of periods in a way that won't alter the
725*4882a593Smuzhiyun * phase offset.
726*4882a593Smuzhiyun */
727*4882a593Smuzhiyun rc = __sja1105_ptp_gettimex(priv->ds, &now, NULL);
728*4882a593Smuzhiyun if (rc < 0)
729*4882a593Smuzhiyun goto out;
730*4882a593Smuzhiyun
731*4882a593Smuzhiyun pin_start = future_base_time(pin_start, pin_duration,
732*4882a593Smuzhiyun now + 1ull * NSEC_PER_SEC);
733*4882a593Smuzhiyun pin_start = ns_to_sja1105_ticks(pin_start);
734*4882a593Smuzhiyun
735*4882a593Smuzhiyun rc = sja1105_xfer_u64(priv, SPI_WRITE, regs->ptppinst,
736*4882a593Smuzhiyun &pin_start, NULL);
737*4882a593Smuzhiyun if (rc < 0)
738*4882a593Smuzhiyun goto out;
739*4882a593Smuzhiyun
740*4882a593Smuzhiyun rc = sja1105_xfer_u32(priv, SPI_WRITE, regs->ptppindur,
741*4882a593Smuzhiyun &pin_duration32, NULL);
742*4882a593Smuzhiyun if (rc < 0)
743*4882a593Smuzhiyun goto out;
744*4882a593Smuzhiyun }
745*4882a593Smuzhiyun
746*4882a593Smuzhiyun if (on)
747*4882a593Smuzhiyun cmd.startptpcp = true;
748*4882a593Smuzhiyun else
749*4882a593Smuzhiyun cmd.stopptpcp = true;
750*4882a593Smuzhiyun
751*4882a593Smuzhiyun rc = sja1105_ptp_commit(priv->ds, &cmd, SPI_WRITE);
752*4882a593Smuzhiyun
753*4882a593Smuzhiyun out:
754*4882a593Smuzhiyun mutex_unlock(&ptp_data->lock);
755*4882a593Smuzhiyun
756*4882a593Smuzhiyun return rc;
757*4882a593Smuzhiyun }
758*4882a593Smuzhiyun
sja1105_extts_enable(struct sja1105_private * priv,struct ptp_extts_request * extts,bool on)759*4882a593Smuzhiyun static int sja1105_extts_enable(struct sja1105_private *priv,
760*4882a593Smuzhiyun struct ptp_extts_request *extts,
761*4882a593Smuzhiyun bool on)
762*4882a593Smuzhiyun {
763*4882a593Smuzhiyun int rc;
764*4882a593Smuzhiyun
765*4882a593Smuzhiyun /* We only support one channel */
766*4882a593Smuzhiyun if (extts->index != 0)
767*4882a593Smuzhiyun return -EOPNOTSUPP;
768*4882a593Smuzhiyun
769*4882a593Smuzhiyun /* Reject requests with unsupported flags */
770*4882a593Smuzhiyun if (extts->flags & ~(PTP_ENABLE_FEATURE |
771*4882a593Smuzhiyun PTP_RISING_EDGE |
772*4882a593Smuzhiyun PTP_FALLING_EDGE |
773*4882a593Smuzhiyun PTP_STRICT_FLAGS))
774*4882a593Smuzhiyun return -EOPNOTSUPP;
775*4882a593Smuzhiyun
776*4882a593Smuzhiyun /* We can only enable time stamping on both edges, sadly. */
777*4882a593Smuzhiyun if ((extts->flags & PTP_STRICT_FLAGS) &&
778*4882a593Smuzhiyun (extts->flags & PTP_ENABLE_FEATURE) &&
779*4882a593Smuzhiyun (extts->flags & PTP_EXTTS_EDGES) != PTP_EXTTS_EDGES)
780*4882a593Smuzhiyun return -EOPNOTSUPP;
781*4882a593Smuzhiyun
782*4882a593Smuzhiyun rc = sja1105_change_ptp_clk_pin_func(priv, PTP_PF_EXTTS);
783*4882a593Smuzhiyun if (rc)
784*4882a593Smuzhiyun return rc;
785*4882a593Smuzhiyun
786*4882a593Smuzhiyun priv->ptp_data.extts_enabled = on;
787*4882a593Smuzhiyun
788*4882a593Smuzhiyun if (on)
789*4882a593Smuzhiyun sja1105_ptp_extts_setup_timer(&priv->ptp_data);
790*4882a593Smuzhiyun else
791*4882a593Smuzhiyun del_timer_sync(&priv->ptp_data.extts_timer);
792*4882a593Smuzhiyun
793*4882a593Smuzhiyun return 0;
794*4882a593Smuzhiyun }
795*4882a593Smuzhiyun
sja1105_ptp_enable(struct ptp_clock_info * ptp,struct ptp_clock_request * req,int on)796*4882a593Smuzhiyun static int sja1105_ptp_enable(struct ptp_clock_info *ptp,
797*4882a593Smuzhiyun struct ptp_clock_request *req, int on)
798*4882a593Smuzhiyun {
799*4882a593Smuzhiyun struct sja1105_ptp_data *ptp_data = ptp_caps_to_data(ptp);
800*4882a593Smuzhiyun struct sja1105_private *priv = ptp_data_to_sja1105(ptp_data);
801*4882a593Smuzhiyun int rc = -EOPNOTSUPP;
802*4882a593Smuzhiyun
803*4882a593Smuzhiyun if (req->type == PTP_CLK_REQ_PEROUT)
804*4882a593Smuzhiyun rc = sja1105_per_out_enable(priv, &req->perout, on);
805*4882a593Smuzhiyun else if (req->type == PTP_CLK_REQ_EXTTS)
806*4882a593Smuzhiyun rc = sja1105_extts_enable(priv, &req->extts, on);
807*4882a593Smuzhiyun
808*4882a593Smuzhiyun return rc;
809*4882a593Smuzhiyun }
810*4882a593Smuzhiyun
sja1105_ptp_verify_pin(struct ptp_clock_info * ptp,unsigned int pin,enum ptp_pin_function func,unsigned int chan)811*4882a593Smuzhiyun static int sja1105_ptp_verify_pin(struct ptp_clock_info *ptp, unsigned int pin,
812*4882a593Smuzhiyun enum ptp_pin_function func, unsigned int chan)
813*4882a593Smuzhiyun {
814*4882a593Smuzhiyun struct sja1105_ptp_data *ptp_data = ptp_caps_to_data(ptp);
815*4882a593Smuzhiyun struct sja1105_private *priv = ptp_data_to_sja1105(ptp_data);
816*4882a593Smuzhiyun
817*4882a593Smuzhiyun if (chan != 0 || pin != 0)
818*4882a593Smuzhiyun return -1;
819*4882a593Smuzhiyun
820*4882a593Smuzhiyun switch (func) {
821*4882a593Smuzhiyun case PTP_PF_NONE:
822*4882a593Smuzhiyun case PTP_PF_PEROUT:
823*4882a593Smuzhiyun break;
824*4882a593Smuzhiyun case PTP_PF_EXTTS:
825*4882a593Smuzhiyun if (priv->info->device_id == SJA1105E_DEVICE_ID ||
826*4882a593Smuzhiyun priv->info->device_id == SJA1105T_DEVICE_ID)
827*4882a593Smuzhiyun return -1;
828*4882a593Smuzhiyun break;
829*4882a593Smuzhiyun default:
830*4882a593Smuzhiyun return -1;
831*4882a593Smuzhiyun }
832*4882a593Smuzhiyun return 0;
833*4882a593Smuzhiyun }
834*4882a593Smuzhiyun
835*4882a593Smuzhiyun static struct ptp_pin_desc sja1105_ptp_pin = {
836*4882a593Smuzhiyun .name = "ptp_clk",
837*4882a593Smuzhiyun .index = 0,
838*4882a593Smuzhiyun .func = PTP_PF_NONE,
839*4882a593Smuzhiyun };
840*4882a593Smuzhiyun
sja1105_ptp_clock_register(struct dsa_switch * ds)841*4882a593Smuzhiyun int sja1105_ptp_clock_register(struct dsa_switch *ds)
842*4882a593Smuzhiyun {
843*4882a593Smuzhiyun struct sja1105_private *priv = ds->priv;
844*4882a593Smuzhiyun struct sja1105_tagger_data *tagger_data = &priv->tagger_data;
845*4882a593Smuzhiyun struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
846*4882a593Smuzhiyun
847*4882a593Smuzhiyun ptp_data->caps = (struct ptp_clock_info) {
848*4882a593Smuzhiyun .owner = THIS_MODULE,
849*4882a593Smuzhiyun .name = "SJA1105 PHC",
850*4882a593Smuzhiyun .adjfine = sja1105_ptp_adjfine,
851*4882a593Smuzhiyun .adjtime = sja1105_ptp_adjtime,
852*4882a593Smuzhiyun .gettimex64 = sja1105_ptp_gettimex,
853*4882a593Smuzhiyun .settime64 = sja1105_ptp_settime,
854*4882a593Smuzhiyun .enable = sja1105_ptp_enable,
855*4882a593Smuzhiyun .verify = sja1105_ptp_verify_pin,
856*4882a593Smuzhiyun .do_aux_work = sja1105_rxtstamp_work,
857*4882a593Smuzhiyun .max_adj = SJA1105_MAX_ADJ_PPB,
858*4882a593Smuzhiyun .pin_config = &sja1105_ptp_pin,
859*4882a593Smuzhiyun .n_pins = 1,
860*4882a593Smuzhiyun .n_ext_ts = 1,
861*4882a593Smuzhiyun .n_per_out = 1,
862*4882a593Smuzhiyun };
863*4882a593Smuzhiyun
864*4882a593Smuzhiyun skb_queue_head_init(&ptp_data->skb_rxtstamp_queue);
865*4882a593Smuzhiyun spin_lock_init(&tagger_data->meta_lock);
866*4882a593Smuzhiyun
867*4882a593Smuzhiyun ptp_data->clock = ptp_clock_register(&ptp_data->caps, ds->dev);
868*4882a593Smuzhiyun if (IS_ERR_OR_NULL(ptp_data->clock))
869*4882a593Smuzhiyun return PTR_ERR(ptp_data->clock);
870*4882a593Smuzhiyun
871*4882a593Smuzhiyun ptp_data->cmd.corrclk4ts = true;
872*4882a593Smuzhiyun ptp_data->cmd.ptpclkadd = PTP_SET_MODE;
873*4882a593Smuzhiyun
874*4882a593Smuzhiyun timer_setup(&ptp_data->extts_timer, sja1105_ptp_extts_timer, 0);
875*4882a593Smuzhiyun
876*4882a593Smuzhiyun return sja1105_ptp_reset(ds);
877*4882a593Smuzhiyun }
878*4882a593Smuzhiyun
sja1105_ptp_clock_unregister(struct dsa_switch * ds)879*4882a593Smuzhiyun void sja1105_ptp_clock_unregister(struct dsa_switch *ds)
880*4882a593Smuzhiyun {
881*4882a593Smuzhiyun struct sja1105_private *priv = ds->priv;
882*4882a593Smuzhiyun struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
883*4882a593Smuzhiyun
884*4882a593Smuzhiyun if (IS_ERR_OR_NULL(ptp_data->clock))
885*4882a593Smuzhiyun return;
886*4882a593Smuzhiyun
887*4882a593Smuzhiyun del_timer_sync(&ptp_data->extts_timer);
888*4882a593Smuzhiyun ptp_cancel_worker_sync(ptp_data->clock);
889*4882a593Smuzhiyun skb_queue_purge(&ptp_data->skb_rxtstamp_queue);
890*4882a593Smuzhiyun ptp_clock_unregister(ptp_data->clock);
891*4882a593Smuzhiyun ptp_data->clock = NULL;
892*4882a593Smuzhiyun }
893*4882a593Smuzhiyun
sja1105_ptp_txtstamp_skb(struct dsa_switch * ds,int port,struct sk_buff * skb)894*4882a593Smuzhiyun void sja1105_ptp_txtstamp_skb(struct dsa_switch *ds, int port,
895*4882a593Smuzhiyun struct sk_buff *skb)
896*4882a593Smuzhiyun {
897*4882a593Smuzhiyun struct sja1105_private *priv = ds->priv;
898*4882a593Smuzhiyun struct sja1105_ptp_data *ptp_data = &priv->ptp_data;
899*4882a593Smuzhiyun struct skb_shared_hwtstamps shwt = {0};
900*4882a593Smuzhiyun u64 ticks, ts;
901*4882a593Smuzhiyun int rc;
902*4882a593Smuzhiyun
903*4882a593Smuzhiyun skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
904*4882a593Smuzhiyun
905*4882a593Smuzhiyun mutex_lock(&ptp_data->lock);
906*4882a593Smuzhiyun
907*4882a593Smuzhiyun rc = sja1105_ptpegr_ts_poll(ds, port, &ts);
908*4882a593Smuzhiyun if (rc < 0) {
909*4882a593Smuzhiyun dev_err(ds->dev, "timed out polling for tstamp\n");
910*4882a593Smuzhiyun kfree_skb(skb);
911*4882a593Smuzhiyun goto out;
912*4882a593Smuzhiyun }
913*4882a593Smuzhiyun
914*4882a593Smuzhiyun rc = sja1105_ptpclkval_read(priv, &ticks, NULL);
915*4882a593Smuzhiyun if (rc < 0) {
916*4882a593Smuzhiyun dev_err(ds->dev, "Failed to read PTP clock: %d\n", rc);
917*4882a593Smuzhiyun kfree_skb(skb);
918*4882a593Smuzhiyun goto out;
919*4882a593Smuzhiyun }
920*4882a593Smuzhiyun
921*4882a593Smuzhiyun ts = sja1105_tstamp_reconstruct(ds, ticks, ts);
922*4882a593Smuzhiyun
923*4882a593Smuzhiyun shwt.hwtstamp = ns_to_ktime(sja1105_ticks_to_ns(ts));
924*4882a593Smuzhiyun skb_complete_tx_timestamp(skb, &shwt);
925*4882a593Smuzhiyun
926*4882a593Smuzhiyun out:
927*4882a593Smuzhiyun mutex_unlock(&ptp_data->lock);
928*4882a593Smuzhiyun }
929