File Index
Files and directories
Sign in
FILE

dwmac1000_core.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*******************************************************************************
  3  This is the driver for the GMAC on-chip Ethernet controller for ST SoCs.
  4  DWC Ether MAC 10/100/1000 Universal version 3.41a  has been used for
  5  developing this code.
  6
  7  This only implements the mac core functions for this chip.
  8
  9  Copyright (C) 2007-2009  STMicroelectronics Ltd
 10
 11
 12  Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
 13*******************************************************************************/
 14
 15#include <linux/crc32.h>
 16#include <linux/slab.h>
 17#include <linux/ethtool.h>
 18#include <linux/io.h>
 19#include <linux/string_choices.h>
 20#include "stmmac.h"
 21#include "stmmac_pcs.h"
 22#include "stmmac_ptp.h"
 23#include "dwmac1000.h"
 24
 25static int dwmac1000_pcs_init(struct stmmac_priv *priv)
 26{
 27	if (!priv->dma_cap.pcs)
 28		return 0;
 29
 30	return stmmac_integrated_pcs_init(priv, GMAC_PCS_BASE,
 31					  GMAC_INT_DISABLE_PCSLINK |
 32					  GMAC_INT_DISABLE_PCSAN);
 33}
 34
 35static void dwmac1000_core_init(struct mac_device_info *hw,
 36				struct net_device *dev)
 37{
 38	void __iomem *ioaddr = hw->pcsr;
 39	int mtu = dev->mtu;
 40	u32 value;
 41
 42	/* Configure GMAC core */
 43	value = readl(ioaddr + GMAC_CONTROL);
 44
 45	if (mtu > 1500)
 46		value |= GMAC_CONTROL_2K;
 47	if (mtu > 2000)
 48		value |= GMAC_CONTROL_JE;
 49
 50	writel(value | GMAC_CORE_INIT, ioaddr + GMAC_CONTROL);
 51
 52	/* Mask GMAC interrupts */
 53	writel(GMAC_INT_DEFAULT_MASK, ioaddr + GMAC_INT_MASK);
 54
 55#ifdef STMMAC_VLAN_TAG_USED
 56	/* Tag detection without filtering */
 57	writel(0x0, ioaddr + GMAC_VLAN_TAG);
 58#endif
 59}
 60
 61static void dwmac1000_irq_modify(struct mac_device_info *hw, u32 disable,
 62				 u32 enable)
 63{
 64	void __iomem *int_mask = hw->pcsr + GMAC_INT_MASK;
 65	unsigned long flags;
 66	u32 value;
 67
 68	spin_lock_irqsave(&hw->irq_ctrl_lock, flags);
 69	value = readl(int_mask) | disable;
 70	value &= ~enable;
 71	writel(value, int_mask);
 72	spin_unlock_irqrestore(&hw->irq_ctrl_lock, flags);
 73}
 74
 75static int dwmac1000_rx_ipc_enable(struct mac_device_info *hw)
 76{
 77	void __iomem *ioaddr = hw->pcsr;
 78	u32 value = readl(ioaddr + GMAC_CONTROL);
 79
 80	if (hw->rx_csum)
 81		value |= GMAC_CONTROL_IPC;
 82	else
 83		value &= ~GMAC_CONTROL_IPC;
 84
 85	writel(value, ioaddr + GMAC_CONTROL);
 86
 87	value = readl(ioaddr + GMAC_CONTROL);
 88
 89	return !!(value & GMAC_CONTROL_IPC);
 90}
 91
 92static void dwmac1000_dump_regs(struct mac_device_info *hw, u32 *reg_space)
 93{
 94	void __iomem *ioaddr = hw->pcsr;
 95	int i;
 96
 97	for (i = 0; i < 55; i++)
 98		reg_space[i] = readl(ioaddr + i * 4);
 99}
100
101static void dwmac1000_set_umac_addr(struct mac_device_info *hw,
102				    const unsigned char *addr,
103				    unsigned int reg_n)
104{
105	void __iomem *ioaddr = hw->pcsr;
106	stmmac_set_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
107			    GMAC_ADDR_LOW(reg_n));
108}
109
110static void dwmac1000_get_umac_addr(struct mac_device_info *hw,
111				    unsigned char *addr,
112				    unsigned int reg_n)
113{
114	void __iomem *ioaddr = hw->pcsr;
115	stmmac_get_mac_addr(ioaddr, addr, GMAC_ADDR_HIGH(reg_n),
116			    GMAC_ADDR_LOW(reg_n));
117}
118
119static void dwmac1000_set_mchash(void __iomem *ioaddr, u32 *mcfilterbits,
120				 int mcbitslog2)
121{
122	int numhashregs, regs;
123
124	switch (mcbitslog2) {
125	case 6:
126		writel(mcfilterbits[0], ioaddr + GMAC_HASH_LOW);
127		writel(mcfilterbits[1], ioaddr + GMAC_HASH_HIGH);
128		return;
129	case 7:
130		numhashregs = 4;
131		break;
132	case 8:
133		numhashregs = 8;
134		break;
135	default:
136		pr_debug("STMMAC: err in setting multicast filter\n");
137		return;
138	}
139	for (regs = 0; regs < numhashregs; regs++)
140		writel(mcfilterbits[regs],
141		       ioaddr + GMAC_EXTHASH_BASE + regs * 4);
142}
143
144static void dwmac1000_set_filter(struct mac_device_info *hw,
145				 struct net_device *dev)
146{
147	void __iomem *ioaddr = (void __iomem *)dev->base_addr;
148	unsigned int value = 0;
149	unsigned int perfect_addr_number = hw->unicast_filter_entries;
150	u32 mc_filter[8];
151	int mcbitslog2 = hw->mcast_bits_log2;
152
153	pr_debug("%s: # mcasts %d, # unicast %d\n", __func__,
154		 netdev_mc_count(dev), netdev_uc_count(dev));
155
156	memset(mc_filter, 0, sizeof(mc_filter));
157
158	if (dev->flags & IFF_PROMISC) {
159		value = GMAC_FRAME_FILTER_PR | GMAC_FRAME_FILTER_PCF;
160	} else if (dev->flags & IFF_ALLMULTI) {
161		value = GMAC_FRAME_FILTER_PM;	/* pass all multi */
162	} else if (!netdev_mc_empty(dev) && (mcbitslog2 == 0)) {
163		/* Fall back to all multicast if we've no filter */
164		value = GMAC_FRAME_FILTER_PM;
165	} else if (!netdev_mc_empty(dev)) {
166		struct netdev_hw_addr *ha;
167
168		/* Hash filter for multicast */
169		value = GMAC_FRAME_FILTER_HMC;
170
171		netdev_for_each_mc_addr(ha, dev) {
172			/* The upper n bits of the calculated CRC are used to
173			 * index the contents of the hash table. The number of
174			 * bits used depends on the hardware configuration
175			 * selected at core configuration time.
176			 */
177			int bit_nr = bitrev32(~crc32_le(~0, ha->addr,
178					      ETH_ALEN)) >>
179					      (32 - mcbitslog2);
180			/* The most significant bit determines the register to
181			 * use (H/L) while the other 5 bits determine the bit
182			 * within the register.
183			 */
184			mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31);
185		}
186	}
187
188	value |= GMAC_FRAME_FILTER_HPF;
189	dwmac1000_set_mchash(ioaddr, mc_filter, mcbitslog2);
190
191	/* Handle multiple unicast addresses (perfect filtering) */
192	if (netdev_uc_count(dev) > perfect_addr_number)
193		/* Switch to promiscuous mode if more than unicast
194		 * addresses are requested than supported by hardware.
195		 */
196		value |= GMAC_FRAME_FILTER_PR;
197	else {
198		int reg = 1;
199		struct netdev_hw_addr *ha;
200
201		netdev_for_each_uc_addr(ha, dev) {
202			stmmac_set_mac_addr(ioaddr, ha->addr,
203					    GMAC_ADDR_HIGH(reg),
204					    GMAC_ADDR_LOW(reg));
205			reg++;
206		}
207
208		while (reg < perfect_addr_number) {
209			writel(0, ioaddr + GMAC_ADDR_HIGH(reg));
210			writel(0, ioaddr + GMAC_ADDR_LOW(reg));
211			reg++;
212		}
213	}
214
215#ifdef FRAME_FILTER_DEBUG
216	/* Enable Receive all mode (to debug filtering_fail errors) */
217	value |= GMAC_FRAME_FILTER_RA;
218#endif
219	writel(value, ioaddr + GMAC_FRAME_FILTER);
220}
221
222
223static void dwmac1000_flow_ctrl(struct mac_device_info *hw, unsigned int duplex,
224				unsigned int fc, unsigned int pause_time,
225				u32 tx_cnt)
226{
227	void __iomem *ioaddr = hw->pcsr;
228	/* Set flow such that DZPQ in Mac Register 6 is 0,
229	 * and unicast pause detect is enabled.
230	 */
231	unsigned int flow = GMAC_FLOW_CTRL_UP;
232
233	pr_debug("GMAC Flow-Control:\n");
234	if (fc & FLOW_RX) {
235		pr_debug("\tReceive Flow-Control ON\n");
236		flow |= GMAC_FLOW_CTRL_RFE;
237	}
238	if (fc & FLOW_TX) {
239		pr_debug("\tTransmit Flow-Control ON\n");
240		flow |= GMAC_FLOW_CTRL_TFE;
241	}
242
243	if (duplex) {
244		pr_debug("\tduplex mode: PAUSE %d\n", pause_time);
245		flow |= (pause_time << GMAC_FLOW_CTRL_PT_SHIFT);
246	}
247
248	writel(flow, ioaddr + GMAC_FLOW_CTRL);
249}
250
251static void dwmac1000_pmt(struct mac_device_info *hw, unsigned long mode)
252{
253	void __iomem *ioaddr = hw->pcsr;
254	unsigned int pmt = 0;
255
256	if (mode & WAKE_MAGIC) {
257		pr_debug("GMAC: WOL Magic frame\n");
258		pmt |= power_down | magic_pkt_en;
259	}
260	if (mode & WAKE_UCAST) {
261		pr_debug("GMAC: WOL on global unicast\n");
262		pmt |= power_down | global_unicast | wake_up_frame_en;
263	}
264
265	writel(pmt, ioaddr + GMAC_PMT);
266}
267
268static int dwmac1000_irq_status(struct mac_device_info *hw,
269				struct stmmac_extra_stats *x)
270{
271	void __iomem *ioaddr = hw->pcsr;
272	u32 intr_status = readl(ioaddr + GMAC_INT_STATUS);
273	u32 intr_mask = readl(ioaddr + GMAC_INT_MASK);
274	int ret = 0;
275
276	/* Discard masked bits */
277	intr_status &= ~intr_mask;
278
279	/* Not used events (e.g. MMC interrupts) are not handled. */
280	if ((intr_status & GMAC_INT_STATUS_MMCTIS))
281		x->mmc_tx_irq_n++;
282	if (unlikely(intr_status & GMAC_INT_STATUS_MMCRIS))
283		x->mmc_rx_irq_n++;
284	if (unlikely(intr_status & GMAC_INT_STATUS_MMCCSUM))
285		x->mmc_rx_csum_offload_irq_n++;
286	if (unlikely(intr_status & GMAC_INT_DISABLE_PMT)) {
287		/* clear the PMT bits 5 and 6 by reading the PMT status reg */
288		readl(ioaddr + GMAC_PMT);
289		x->irq_receive_pmt_irq_n++;
290	}
291
292	/* MAC tx/rx EEE LPI entry/exit interrupts */
293	if (intr_status & GMAC_INT_STATUS_LPIIS) {
294		/* Clean LPI interrupt by reading the Reg 12 */
295		ret = readl(ioaddr + LPI_CTRL_STATUS);
296
297		if (ret & LPI_CTRL_STATUS_TLPIEN)
298			x->irq_tx_path_in_lpi_mode_n++;
299		if (ret & LPI_CTRL_STATUS_TLPIEX)
300			x->irq_tx_path_exit_lpi_mode_n++;
301		if (ret & LPI_CTRL_STATUS_RLPIEN)
302			x->irq_rx_path_in_lpi_mode_n++;
303		if (ret & LPI_CTRL_STATUS_RLPIEX)
304			x->irq_rx_path_exit_lpi_mode_n++;
305	}
306
307	dwmac_pcs_isr(ioaddr, GMAC_PCS_BASE, intr_status, x);
308
309	return ret;
310}
311
312static int dwmac1000_set_lpi_mode(struct mac_device_info *hw,
313				  enum stmmac_lpi_mode mode,
314				  bool en_tx_lpi_clockgating, u32 et)
315{
316	void __iomem *ioaddr = hw->pcsr;
317	u32 value;
318
319	if (mode == STMMAC_LPI_TIMER)
320		return -EOPNOTSUPP;
321
322	value = readl(ioaddr + LPI_CTRL_STATUS);
323	if (mode == STMMAC_LPI_FORCED)
324		value |= LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA;
325	else
326		value &= ~(LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA);
327	writel(value, ioaddr + LPI_CTRL_STATUS);
328
329	return 0;
330}
331
332static void dwmac1000_set_eee_pls(struct mac_device_info *hw, int link)
333{
334	void __iomem *ioaddr = hw->pcsr;
335	u32 value;
336
337	value = readl(ioaddr + LPI_CTRL_STATUS);
338
339	if (link)
340		value |= LPI_CTRL_STATUS_PLS;
341	else
342		value &= ~LPI_CTRL_STATUS_PLS;
343
344	writel(value, ioaddr + LPI_CTRL_STATUS);
345}
346
347static void dwmac1000_set_eee_timer(struct mac_device_info *hw, int ls, int tw)
348{
349	void __iomem *ioaddr = hw->pcsr;
350	int value = ((tw & 0xffff)) | ((ls & 0x7ff) << 16);
351
352	/* Program the timers in the LPI timer control register:
353	 * LS: minimum time (ms) for which the link
354	 *  status from PHY should be ok before transmitting
355	 *  the LPI pattern.
356	 * TW: minimum time (us) for which the core waits
357	 *  after it has stopped transmitting the LPI pattern.
358	 */
359	writel(value, ioaddr + LPI_TIMER_CTRL);
360}
361
362static void dwmac1000_ctrl_ane(struct stmmac_priv *priv, bool ane,
363			       bool srgmi_ral)
364{
365	dwmac_ctrl_ane(priv->ioaddr, GMAC_PCS_BASE, ane, srgmi_ral);
366}
367
368static void dwmac1000_debug(struct stmmac_priv *priv, void __iomem *ioaddr,
369			    struct stmmac_extra_stats *x,
370			    u32 rx_queues, u32 tx_queues)
371{
372	u32 value = readl(ioaddr + GMAC_DEBUG);
373
374	if (value & GMAC_DEBUG_TXSTSFSTS)
375		x->mtl_tx_status_fifo_full++;
376	if (value & GMAC_DEBUG_TXFSTS)
377		x->mtl_tx_fifo_not_empty++;
378	if (value & GMAC_DEBUG_TWCSTS)
379		x->mmtl_fifo_ctrl++;
380	if (value & GMAC_DEBUG_TRCSTS_MASK) {
381		u32 trcsts = (value & GMAC_DEBUG_TRCSTS_MASK)
382			     >> GMAC_DEBUG_TRCSTS_SHIFT;
383		if (trcsts == GMAC_DEBUG_TRCSTS_WRITE)
384			x->mtl_tx_fifo_read_ctrl_write++;
385		else if (trcsts == GMAC_DEBUG_TRCSTS_TXW)
386			x->mtl_tx_fifo_read_ctrl_wait++;
387		else if (trcsts == GMAC_DEBUG_TRCSTS_READ)
388			x->mtl_tx_fifo_read_ctrl_read++;
389		else
390			x->mtl_tx_fifo_read_ctrl_idle++;
391	}
392	if (value & GMAC_DEBUG_TXPAUSED)
393		x->mac_tx_in_pause++;
394	if (value & GMAC_DEBUG_TFCSTS_MASK) {
395		u32 tfcsts = (value & GMAC_DEBUG_TFCSTS_MASK)
396			      >> GMAC_DEBUG_TFCSTS_SHIFT;
397
398		if (tfcsts == GMAC_DEBUG_TFCSTS_XFER)
399			x->mac_tx_frame_ctrl_xfer++;
400		else if (tfcsts == GMAC_DEBUG_TFCSTS_GEN_PAUSE)
401			x->mac_tx_frame_ctrl_pause++;
402		else if (tfcsts == GMAC_DEBUG_TFCSTS_WAIT)
403			x->mac_tx_frame_ctrl_wait++;
404		else
405			x->mac_tx_frame_ctrl_idle++;
406	}
407	if (value & GMAC_DEBUG_TPESTS)
408		x->mac_gmii_tx_proto_engine++;
409	if (value & GMAC_DEBUG_RXFSTS_MASK) {
410		u32 rxfsts = (value & GMAC_DEBUG_RXFSTS_MASK)
411			     >> GMAC_DEBUG_RRCSTS_SHIFT;
412
413		if (rxfsts == GMAC_DEBUG_RXFSTS_FULL)
414			x->mtl_rx_fifo_fill_level_full++;
415		else if (rxfsts == GMAC_DEBUG_RXFSTS_AT)
416			x->mtl_rx_fifo_fill_above_thresh++;
417		else if (rxfsts == GMAC_DEBUG_RXFSTS_BT)
418			x->mtl_rx_fifo_fill_below_thresh++;
419		else
420			x->mtl_rx_fifo_fill_level_empty++;
421	}
422	if (value & GMAC_DEBUG_RRCSTS_MASK) {
423		u32 rrcsts = (value & GMAC_DEBUG_RRCSTS_MASK) >>
424			     GMAC_DEBUG_RRCSTS_SHIFT;
425
426		if (rrcsts == GMAC_DEBUG_RRCSTS_FLUSH)
427			x->mtl_rx_fifo_read_ctrl_flush++;
428		else if (rrcsts == GMAC_DEBUG_RRCSTS_RSTAT)
429			x->mtl_rx_fifo_read_ctrl_read_data++;
430		else if (rrcsts == GMAC_DEBUG_RRCSTS_RDATA)
431			x->mtl_rx_fifo_read_ctrl_status++;
432		else
433			x->mtl_rx_fifo_read_ctrl_idle++;
434	}
435	if (value & GMAC_DEBUG_RWCSTS)
436		x->mtl_rx_fifo_ctrl_active++;
437	if (value & GMAC_DEBUG_RFCFCSTS_MASK)
438		x->mac_rx_frame_ctrl_fifo = (value & GMAC_DEBUG_RFCFCSTS_MASK)
439					    >> GMAC_DEBUG_RFCFCSTS_SHIFT;
440	if (value & GMAC_DEBUG_RPESTS)
441		x->mac_gmii_rx_proto_engine++;
442}
443
444static void dwmac1000_set_mac_loopback(void __iomem *ioaddr, bool enable)
445{
446	u32 value = readl(ioaddr + GMAC_CONTROL);
447
448	if (enable)
449		value |= GMAC_CONTROL_LM;
450	else
451		value &= ~GMAC_CONTROL_LM;
452
453	writel(value, ioaddr + GMAC_CONTROL);
454}
455
456const struct stmmac_ops dwmac1000_ops = {
457	.pcs_init = dwmac1000_pcs_init,
458	.core_init = dwmac1000_core_init,
459	.irq_modify = dwmac1000_irq_modify,
460	.set_mac = stmmac_set_mac,
461	.rx_ipc = dwmac1000_rx_ipc_enable,
462	.dump_regs = dwmac1000_dump_regs,
463	.host_irq_status = dwmac1000_irq_status,
464	.set_filter = dwmac1000_set_filter,
465	.flow_ctrl = dwmac1000_flow_ctrl,
466	.pmt = dwmac1000_pmt,
467	.set_umac_addr = dwmac1000_set_umac_addr,
468	.get_umac_addr = dwmac1000_get_umac_addr,
469	.set_lpi_mode = dwmac1000_set_lpi_mode,
470	.set_eee_timer = dwmac1000_set_eee_timer,
471	.set_eee_pls = dwmac1000_set_eee_pls,
472	.debug = dwmac1000_debug,
473	.pcs_ctrl_ane = dwmac1000_ctrl_ane,
474	.set_mac_loopback = dwmac1000_set_mac_loopback,
475};
476
477int dwmac1000_setup(struct stmmac_priv *priv)
478{
479	struct mac_device_info *mac = priv->hw;
480
481	dev_info(priv->device, "\tDWMAC1000\n");
482
483	priv->dev->priv_flags |= IFF_UNICAST_FLT;
484	mac->pcsr = priv->ioaddr;
485	mac->multicast_filter_bins = priv->plat->multicast_filter_bins;
486	mac->unicast_filter_entries = priv->plat->unicast_filter_entries;
487	mac->mcast_bits_log2 = 0;
488
489	if (mac->multicast_filter_bins)
490		mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
491
492	mac->link.caps = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
493			 MAC_10 | MAC_100 | MAC_1000;
494	mac->link.duplex = GMAC_CONTROL_DM;
495	mac->link.speed10 = GMAC_CONTROL_PS;
496	mac->link.speed100 = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
497	mac->link.speed1000 = 0;
498	mac->link.speed_mask = GMAC_CONTROL_PS | GMAC_CONTROL_FES;
499	mac->mii.addr = GMAC_MII_ADDR;
500	mac->mii.data = GMAC_MII_DATA;
501	mac->mii.addr_shift = 11;
502	mac->mii.addr_mask = 0x0000F800;
503	mac->mii.reg_shift = 6;
504	mac->mii.reg_mask = 0x000007C0;
505	mac->mii.clk_csr_shift = 2;
506	mac->mii.clk_csr_mask = GENMASK(5, 2);
507
508	return 0;
509}
510
511/* DWMAC 1000 HW Timestaming ops */
512
513void dwmac1000_get_ptptime(void __iomem *ptpaddr, u64 *ptp_time)
514{
515	u64 ns;
516
517	ns = readl(ptpaddr + GMAC_PTP_ATNR);
518	ns += (u64)readl(ptpaddr + GMAC_PTP_ATSR) * NSEC_PER_SEC;
519
520	*ptp_time = ns;
521}
522
523void dwmac1000_timestamp_interrupt(struct stmmac_priv *priv)
524{
525	struct ptp_clock_event event;
526	u32 ts_status, num_snapshot;
527	unsigned long flags;
528	u64 ptp_time;
529	int i;
530
531	/* Clears the timestamp interrupt */
532	ts_status = readl(priv->ptpaddr + GMAC3_X_TIMESTAMP_STATUS);
533
534	if (!(priv->plat->flags & STMMAC_FLAG_EXT_SNAPSHOT_EN))
535		return;
536
537	num_snapshot = (ts_status & GMAC3_X_ATSNS) >> GMAC3_X_ATSNS_SHIFT;
538
539	for (i = 0; i < num_snapshot; i++) {
540		read_lock_irqsave(&priv->ptp_lock, flags);
541		stmmac_get_ptptime(priv, priv->ptpaddr, &ptp_time);
542		read_unlock_irqrestore(&priv->ptp_lock, flags);
543
544		event.type = PTP_CLOCK_EXTTS;
545		event.index = 0;
546		event.timestamp = ptp_time;
547		ptp_clock_event(priv->ptp_clock, &event);
548	}
549}
550
551/* DWMAC 1000 ptp_clock_info ops */
552
553static void dwmac1000_timestamp_interrupt_cfg(struct stmmac_priv *priv, bool en)
554{
555	void __iomem *ioaddr = priv->ioaddr;
556
557	u32 intr_mask = readl(ioaddr + GMAC_INT_MASK);
558
559	if (en)
560		intr_mask &= ~GMAC_INT_DISABLE_TIMESTAMP;
561	else
562		intr_mask |= GMAC_INT_DISABLE_TIMESTAMP;
563
564	writel(intr_mask, ioaddr + GMAC_INT_MASK);
565}
566
567int dwmac1000_ptp_enable(struct ptp_clock_info *ptp,
568			 struct ptp_clock_request *rq, int on)
569{
570	struct stmmac_priv *priv =
571	    container_of(ptp, struct stmmac_priv, ptp_clock_ops);
572	void __iomem *ptpaddr = priv->ptpaddr;
573	int ret = -EOPNOTSUPP;
574	u32 tcr_val;
575
576	switch (rq->type) {
577	case PTP_CLK_REQ_EXTTS:
578		mutex_lock(&priv->aux_ts_lock);
579		tcr_val = readl(ptpaddr + PTP_TCR);
580
581		if (on) {
582			tcr_val |= GMAC_PTP_TCR_ATSEN0;
583			tcr_val |= GMAC_PTP_TCR_ATSFC;
584			priv->plat->flags |= STMMAC_FLAG_EXT_SNAPSHOT_EN;
585		} else {
586			tcr_val &= ~GMAC_PTP_TCR_ATSEN0;
587			priv->plat->flags &= ~STMMAC_FLAG_EXT_SNAPSHOT_EN;
588		}
589
590		netdev_dbg(priv->dev, "Auxiliary Snapshot %s.\n",
591			   str_enabled_disabled(on));
592		writel(tcr_val, ptpaddr + PTP_TCR);
593
594		/* wait for auxts fifo clear to finish */
595		ret = readl_poll_timeout(ptpaddr + PTP_TCR, tcr_val,
596					 !(tcr_val & GMAC_PTP_TCR_ATSFC),
597					 10, 10000);
598
599		mutex_unlock(&priv->aux_ts_lock);
600
601		dwmac1000_timestamp_interrupt_cfg(priv, on);
602		break;
603
604	default:
605		break;
606	}
607
608	return ret;
609}
~/ Read-only file preview.