162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/* Renesas Ethernet AVB device driver
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (C) 2014-2019 Renesas Electronics Corporation
562306a36Sopenharmony_ci * Copyright (C) 2015 Renesas Solutions Corp.
662306a36Sopenharmony_ci * Copyright (C) 2015-2016 Cogent Embedded, Inc. <source@cogentembedded.com>
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Based on the SuperH Ethernet driver
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/cache.h>
1262306a36Sopenharmony_ci#include <linux/clk.h>
1362306a36Sopenharmony_ci#include <linux/delay.h>
1462306a36Sopenharmony_ci#include <linux/dma-mapping.h>
1562306a36Sopenharmony_ci#include <linux/err.h>
1662306a36Sopenharmony_ci#include <linux/etherdevice.h>
1762306a36Sopenharmony_ci#include <linux/ethtool.h>
1862306a36Sopenharmony_ci#include <linux/if_vlan.h>
1962306a36Sopenharmony_ci#include <linux/kernel.h>
2062306a36Sopenharmony_ci#include <linux/list.h>
2162306a36Sopenharmony_ci#include <linux/module.h>
2262306a36Sopenharmony_ci#include <linux/net_tstamp.h>
2362306a36Sopenharmony_ci#include <linux/of.h>
2462306a36Sopenharmony_ci#include <linux/of_mdio.h>
2562306a36Sopenharmony_ci#include <linux/of_net.h>
2662306a36Sopenharmony_ci#include <linux/platform_device.h>
2762306a36Sopenharmony_ci#include <linux/pm_runtime.h>
2862306a36Sopenharmony_ci#include <linux/slab.h>
2962306a36Sopenharmony_ci#include <linux/spinlock.h>
3062306a36Sopenharmony_ci#include <linux/reset.h>
3162306a36Sopenharmony_ci#include <linux/math64.h>
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#include "ravb.h"
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci#define RAVB_DEF_MSG_ENABLE \
3662306a36Sopenharmony_ci		(NETIF_MSG_LINK	  | \
3762306a36Sopenharmony_ci		 NETIF_MSG_TIMER  | \
3862306a36Sopenharmony_ci		 NETIF_MSG_RX_ERR | \
3962306a36Sopenharmony_ci		 NETIF_MSG_TX_ERR)
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cistatic const char *ravb_rx_irqs[NUM_RX_QUEUE] = {
4262306a36Sopenharmony_ci	"ch0", /* RAVB_BE */
4362306a36Sopenharmony_ci	"ch1", /* RAVB_NC */
4462306a36Sopenharmony_ci};
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_cistatic const char *ravb_tx_irqs[NUM_TX_QUEUE] = {
4762306a36Sopenharmony_ci	"ch18", /* RAVB_BE */
4862306a36Sopenharmony_ci	"ch19", /* RAVB_NC */
4962306a36Sopenharmony_ci};
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_civoid ravb_modify(struct net_device *ndev, enum ravb_reg reg, u32 clear,
5262306a36Sopenharmony_ci		 u32 set)
5362306a36Sopenharmony_ci{
5462306a36Sopenharmony_ci	ravb_write(ndev, (ravb_read(ndev, reg) & ~clear) | set, reg);
5562306a36Sopenharmony_ci}
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ciint ravb_wait(struct net_device *ndev, enum ravb_reg reg, u32 mask, u32 value)
5862306a36Sopenharmony_ci{
5962306a36Sopenharmony_ci	int i;
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	for (i = 0; i < 10000; i++) {
6262306a36Sopenharmony_ci		if ((ravb_read(ndev, reg) & mask) == value)
6362306a36Sopenharmony_ci			return 0;
6462306a36Sopenharmony_ci		udelay(10);
6562306a36Sopenharmony_ci	}
6662306a36Sopenharmony_ci	return -ETIMEDOUT;
6762306a36Sopenharmony_ci}
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_cistatic int ravb_set_opmode(struct net_device *ndev, u32 opmode)
7062306a36Sopenharmony_ci{
7162306a36Sopenharmony_ci	u32 csr_ops = 1U << (opmode & CCC_OPC);
7262306a36Sopenharmony_ci	u32 ccc_mask = CCC_OPC;
7362306a36Sopenharmony_ci	int error;
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	/* If gPTP active in config mode is supported it needs to be configured
7662306a36Sopenharmony_ci	 * along with CSEL and operating mode in the same access. This is a
7762306a36Sopenharmony_ci	 * hardware limitation.
7862306a36Sopenharmony_ci	 */
7962306a36Sopenharmony_ci	if (opmode & CCC_GAC)
8062306a36Sopenharmony_ci		ccc_mask |= CCC_GAC | CCC_CSEL;
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_ci	/* Set operating mode */
8362306a36Sopenharmony_ci	ravb_modify(ndev, CCC, ccc_mask, opmode);
8462306a36Sopenharmony_ci	/* Check if the operating mode is changed to the requested one */
8562306a36Sopenharmony_ci	error = ravb_wait(ndev, CSR, CSR_OPS, csr_ops);
8662306a36Sopenharmony_ci	if (error) {
8762306a36Sopenharmony_ci		netdev_err(ndev, "failed to switch device to requested mode (%u)\n",
8862306a36Sopenharmony_ci			   opmode & CCC_OPC);
8962306a36Sopenharmony_ci	}
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	return error;
9262306a36Sopenharmony_ci}
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_cistatic void ravb_set_rate_gbeth(struct net_device *ndev)
9562306a36Sopenharmony_ci{
9662306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	switch (priv->speed) {
9962306a36Sopenharmony_ci	case 10:                /* 10BASE */
10062306a36Sopenharmony_ci		ravb_write(ndev, GBETH_GECMR_SPEED_10, GECMR);
10162306a36Sopenharmony_ci		break;
10262306a36Sopenharmony_ci	case 100:               /* 100BASE */
10362306a36Sopenharmony_ci		ravb_write(ndev, GBETH_GECMR_SPEED_100, GECMR);
10462306a36Sopenharmony_ci		break;
10562306a36Sopenharmony_ci	case 1000:              /* 1000BASE */
10662306a36Sopenharmony_ci		ravb_write(ndev, GBETH_GECMR_SPEED_1000, GECMR);
10762306a36Sopenharmony_ci		break;
10862306a36Sopenharmony_ci	}
10962306a36Sopenharmony_ci}
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cistatic void ravb_set_rate_rcar(struct net_device *ndev)
11262306a36Sopenharmony_ci{
11362306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
11462306a36Sopenharmony_ci
11562306a36Sopenharmony_ci	switch (priv->speed) {
11662306a36Sopenharmony_ci	case 100:		/* 100BASE */
11762306a36Sopenharmony_ci		ravb_write(ndev, GECMR_SPEED_100, GECMR);
11862306a36Sopenharmony_ci		break;
11962306a36Sopenharmony_ci	case 1000:		/* 1000BASE */
12062306a36Sopenharmony_ci		ravb_write(ndev, GECMR_SPEED_1000, GECMR);
12162306a36Sopenharmony_ci		break;
12262306a36Sopenharmony_ci	}
12362306a36Sopenharmony_ci}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_cistatic void ravb_set_buffer_align(struct sk_buff *skb)
12662306a36Sopenharmony_ci{
12762306a36Sopenharmony_ci	u32 reserve = (unsigned long)skb->data & (RAVB_ALIGN - 1);
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci	if (reserve)
13062306a36Sopenharmony_ci		skb_reserve(skb, RAVB_ALIGN - reserve);
13162306a36Sopenharmony_ci}
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_ci/* Get MAC address from the MAC address registers
13462306a36Sopenharmony_ci *
13562306a36Sopenharmony_ci * Ethernet AVB device doesn't have ROM for MAC address.
13662306a36Sopenharmony_ci * This function gets the MAC address that was used by a bootloader.
13762306a36Sopenharmony_ci */
13862306a36Sopenharmony_cistatic void ravb_read_mac_address(struct device_node *np,
13962306a36Sopenharmony_ci				  struct net_device *ndev)
14062306a36Sopenharmony_ci{
14162306a36Sopenharmony_ci	int ret;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	ret = of_get_ethdev_address(np, ndev);
14462306a36Sopenharmony_ci	if (ret) {
14562306a36Sopenharmony_ci		u32 mahr = ravb_read(ndev, MAHR);
14662306a36Sopenharmony_ci		u32 malr = ravb_read(ndev, MALR);
14762306a36Sopenharmony_ci		u8 addr[ETH_ALEN];
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci		addr[0] = (mahr >> 24) & 0xFF;
15062306a36Sopenharmony_ci		addr[1] = (mahr >> 16) & 0xFF;
15162306a36Sopenharmony_ci		addr[2] = (mahr >>  8) & 0xFF;
15262306a36Sopenharmony_ci		addr[3] = (mahr >>  0) & 0xFF;
15362306a36Sopenharmony_ci		addr[4] = (malr >>  8) & 0xFF;
15462306a36Sopenharmony_ci		addr[5] = (malr >>  0) & 0xFF;
15562306a36Sopenharmony_ci		eth_hw_addr_set(ndev, addr);
15662306a36Sopenharmony_ci	}
15762306a36Sopenharmony_ci}
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_cistatic void ravb_mdio_ctrl(struct mdiobb_ctrl *ctrl, u32 mask, int set)
16062306a36Sopenharmony_ci{
16162306a36Sopenharmony_ci	struct ravb_private *priv = container_of(ctrl, struct ravb_private,
16262306a36Sopenharmony_ci						 mdiobb);
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	ravb_modify(priv->ndev, PIR, mask, set ? mask : 0);
16562306a36Sopenharmony_ci}
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci/* MDC pin control */
16862306a36Sopenharmony_cistatic void ravb_set_mdc(struct mdiobb_ctrl *ctrl, int level)
16962306a36Sopenharmony_ci{
17062306a36Sopenharmony_ci	ravb_mdio_ctrl(ctrl, PIR_MDC, level);
17162306a36Sopenharmony_ci}
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci/* Data I/O pin control */
17462306a36Sopenharmony_cistatic void ravb_set_mdio_dir(struct mdiobb_ctrl *ctrl, int output)
17562306a36Sopenharmony_ci{
17662306a36Sopenharmony_ci	ravb_mdio_ctrl(ctrl, PIR_MMD, output);
17762306a36Sopenharmony_ci}
17862306a36Sopenharmony_ci
17962306a36Sopenharmony_ci/* Set data bit */
18062306a36Sopenharmony_cistatic void ravb_set_mdio_data(struct mdiobb_ctrl *ctrl, int value)
18162306a36Sopenharmony_ci{
18262306a36Sopenharmony_ci	ravb_mdio_ctrl(ctrl, PIR_MDO, value);
18362306a36Sopenharmony_ci}
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci/* Get data bit */
18662306a36Sopenharmony_cistatic int ravb_get_mdio_data(struct mdiobb_ctrl *ctrl)
18762306a36Sopenharmony_ci{
18862306a36Sopenharmony_ci	struct ravb_private *priv = container_of(ctrl, struct ravb_private,
18962306a36Sopenharmony_ci						 mdiobb);
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	return (ravb_read(priv->ndev, PIR) & PIR_MDI) != 0;
19262306a36Sopenharmony_ci}
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_ci/* MDIO bus control struct */
19562306a36Sopenharmony_cistatic const struct mdiobb_ops bb_ops = {
19662306a36Sopenharmony_ci	.owner = THIS_MODULE,
19762306a36Sopenharmony_ci	.set_mdc = ravb_set_mdc,
19862306a36Sopenharmony_ci	.set_mdio_dir = ravb_set_mdio_dir,
19962306a36Sopenharmony_ci	.set_mdio_data = ravb_set_mdio_data,
20062306a36Sopenharmony_ci	.get_mdio_data = ravb_get_mdio_data,
20162306a36Sopenharmony_ci};
20262306a36Sopenharmony_ci
20362306a36Sopenharmony_ci/* Free TX skb function for AVB-IP */
20462306a36Sopenharmony_cistatic int ravb_tx_free(struct net_device *ndev, int q, bool free_txed_only)
20562306a36Sopenharmony_ci{
20662306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
20762306a36Sopenharmony_ci	struct net_device_stats *stats = &priv->stats[q];
20862306a36Sopenharmony_ci	unsigned int num_tx_desc = priv->num_tx_desc;
20962306a36Sopenharmony_ci	struct ravb_tx_desc *desc;
21062306a36Sopenharmony_ci	unsigned int entry;
21162306a36Sopenharmony_ci	int free_num = 0;
21262306a36Sopenharmony_ci	u32 size;
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	for (; priv->cur_tx[q] - priv->dirty_tx[q] > 0; priv->dirty_tx[q]++) {
21562306a36Sopenharmony_ci		bool txed;
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci		entry = priv->dirty_tx[q] % (priv->num_tx_ring[q] *
21862306a36Sopenharmony_ci					     num_tx_desc);
21962306a36Sopenharmony_ci		desc = &priv->tx_ring[q][entry];
22062306a36Sopenharmony_ci		txed = desc->die_dt == DT_FEMPTY;
22162306a36Sopenharmony_ci		if (free_txed_only && !txed)
22262306a36Sopenharmony_ci			break;
22362306a36Sopenharmony_ci		/* Descriptor type must be checked before all other reads */
22462306a36Sopenharmony_ci		dma_rmb();
22562306a36Sopenharmony_ci		size = le16_to_cpu(desc->ds_tagl) & TX_DS;
22662306a36Sopenharmony_ci		/* Free the original skb. */
22762306a36Sopenharmony_ci		if (priv->tx_skb[q][entry / num_tx_desc]) {
22862306a36Sopenharmony_ci			dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr),
22962306a36Sopenharmony_ci					 size, DMA_TO_DEVICE);
23062306a36Sopenharmony_ci			/* Last packet descriptor? */
23162306a36Sopenharmony_ci			if (entry % num_tx_desc == num_tx_desc - 1) {
23262306a36Sopenharmony_ci				entry /= num_tx_desc;
23362306a36Sopenharmony_ci				dev_kfree_skb_any(priv->tx_skb[q][entry]);
23462306a36Sopenharmony_ci				priv->tx_skb[q][entry] = NULL;
23562306a36Sopenharmony_ci				if (txed)
23662306a36Sopenharmony_ci					stats->tx_packets++;
23762306a36Sopenharmony_ci			}
23862306a36Sopenharmony_ci			free_num++;
23962306a36Sopenharmony_ci		}
24062306a36Sopenharmony_ci		if (txed)
24162306a36Sopenharmony_ci			stats->tx_bytes += size;
24262306a36Sopenharmony_ci		desc->die_dt = DT_EEMPTY;
24362306a36Sopenharmony_ci	}
24462306a36Sopenharmony_ci	return free_num;
24562306a36Sopenharmony_ci}
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_cistatic void ravb_rx_ring_free_gbeth(struct net_device *ndev, int q)
24862306a36Sopenharmony_ci{
24962306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
25062306a36Sopenharmony_ci	unsigned int ring_size;
25162306a36Sopenharmony_ci	unsigned int i;
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	if (!priv->gbeth_rx_ring)
25462306a36Sopenharmony_ci		return;
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_ci	for (i = 0; i < priv->num_rx_ring[q]; i++) {
25762306a36Sopenharmony_ci		struct ravb_rx_desc *desc = &priv->gbeth_rx_ring[i];
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci		if (!dma_mapping_error(ndev->dev.parent,
26062306a36Sopenharmony_ci				       le32_to_cpu(desc->dptr)))
26162306a36Sopenharmony_ci			dma_unmap_single(ndev->dev.parent,
26262306a36Sopenharmony_ci					 le32_to_cpu(desc->dptr),
26362306a36Sopenharmony_ci					 GBETH_RX_BUFF_MAX,
26462306a36Sopenharmony_ci					 DMA_FROM_DEVICE);
26562306a36Sopenharmony_ci	}
26662306a36Sopenharmony_ci	ring_size = sizeof(struct ravb_rx_desc) * (priv->num_rx_ring[q] + 1);
26762306a36Sopenharmony_ci	dma_free_coherent(ndev->dev.parent, ring_size, priv->gbeth_rx_ring,
26862306a36Sopenharmony_ci			  priv->rx_desc_dma[q]);
26962306a36Sopenharmony_ci	priv->gbeth_rx_ring = NULL;
27062306a36Sopenharmony_ci}
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_cistatic void ravb_rx_ring_free_rcar(struct net_device *ndev, int q)
27362306a36Sopenharmony_ci{
27462306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
27562306a36Sopenharmony_ci	unsigned int ring_size;
27662306a36Sopenharmony_ci	unsigned int i;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	if (!priv->rx_ring[q])
27962306a36Sopenharmony_ci		return;
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	for (i = 0; i < priv->num_rx_ring[q]; i++) {
28262306a36Sopenharmony_ci		struct ravb_ex_rx_desc *desc = &priv->rx_ring[q][i];
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci		if (!dma_mapping_error(ndev->dev.parent,
28562306a36Sopenharmony_ci				       le32_to_cpu(desc->dptr)))
28662306a36Sopenharmony_ci			dma_unmap_single(ndev->dev.parent,
28762306a36Sopenharmony_ci					 le32_to_cpu(desc->dptr),
28862306a36Sopenharmony_ci					 RX_BUF_SZ,
28962306a36Sopenharmony_ci					 DMA_FROM_DEVICE);
29062306a36Sopenharmony_ci	}
29162306a36Sopenharmony_ci	ring_size = sizeof(struct ravb_ex_rx_desc) *
29262306a36Sopenharmony_ci		    (priv->num_rx_ring[q] + 1);
29362306a36Sopenharmony_ci	dma_free_coherent(ndev->dev.parent, ring_size, priv->rx_ring[q],
29462306a36Sopenharmony_ci			  priv->rx_desc_dma[q]);
29562306a36Sopenharmony_ci	priv->rx_ring[q] = NULL;
29662306a36Sopenharmony_ci}
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci/* Free skb's and DMA buffers for Ethernet AVB */
29962306a36Sopenharmony_cistatic void ravb_ring_free(struct net_device *ndev, int q)
30062306a36Sopenharmony_ci{
30162306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
30262306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
30362306a36Sopenharmony_ci	unsigned int num_tx_desc = priv->num_tx_desc;
30462306a36Sopenharmony_ci	unsigned int ring_size;
30562306a36Sopenharmony_ci	unsigned int i;
30662306a36Sopenharmony_ci
30762306a36Sopenharmony_ci	info->rx_ring_free(ndev, q);
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	if (priv->tx_ring[q]) {
31062306a36Sopenharmony_ci		ravb_tx_free(ndev, q, false);
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci		ring_size = sizeof(struct ravb_tx_desc) *
31362306a36Sopenharmony_ci			    (priv->num_tx_ring[q] * num_tx_desc + 1);
31462306a36Sopenharmony_ci		dma_free_coherent(ndev->dev.parent, ring_size, priv->tx_ring[q],
31562306a36Sopenharmony_ci				  priv->tx_desc_dma[q]);
31662306a36Sopenharmony_ci		priv->tx_ring[q] = NULL;
31762306a36Sopenharmony_ci	}
31862306a36Sopenharmony_ci
31962306a36Sopenharmony_ci	/* Free RX skb ringbuffer */
32062306a36Sopenharmony_ci	if (priv->rx_skb[q]) {
32162306a36Sopenharmony_ci		for (i = 0; i < priv->num_rx_ring[q]; i++)
32262306a36Sopenharmony_ci			dev_kfree_skb(priv->rx_skb[q][i]);
32362306a36Sopenharmony_ci	}
32462306a36Sopenharmony_ci	kfree(priv->rx_skb[q]);
32562306a36Sopenharmony_ci	priv->rx_skb[q] = NULL;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	/* Free aligned TX buffers */
32862306a36Sopenharmony_ci	kfree(priv->tx_align[q]);
32962306a36Sopenharmony_ci	priv->tx_align[q] = NULL;
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_ci	/* Free TX skb ringbuffer.
33262306a36Sopenharmony_ci	 * SKBs are freed by ravb_tx_free() call above.
33362306a36Sopenharmony_ci	 */
33462306a36Sopenharmony_ci	kfree(priv->tx_skb[q]);
33562306a36Sopenharmony_ci	priv->tx_skb[q] = NULL;
33662306a36Sopenharmony_ci}
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_cistatic void ravb_rx_ring_format_gbeth(struct net_device *ndev, int q)
33962306a36Sopenharmony_ci{
34062306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
34162306a36Sopenharmony_ci	struct ravb_rx_desc *rx_desc;
34262306a36Sopenharmony_ci	unsigned int rx_ring_size;
34362306a36Sopenharmony_ci	dma_addr_t dma_addr;
34462306a36Sopenharmony_ci	unsigned int i;
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci	rx_ring_size = sizeof(*rx_desc) * priv->num_rx_ring[q];
34762306a36Sopenharmony_ci	memset(priv->gbeth_rx_ring, 0, rx_ring_size);
34862306a36Sopenharmony_ci	/* Build RX ring buffer */
34962306a36Sopenharmony_ci	for (i = 0; i < priv->num_rx_ring[q]; i++) {
35062306a36Sopenharmony_ci		/* RX descriptor */
35162306a36Sopenharmony_ci		rx_desc = &priv->gbeth_rx_ring[i];
35262306a36Sopenharmony_ci		rx_desc->ds_cc = cpu_to_le16(GBETH_RX_DESC_DATA_SIZE);
35362306a36Sopenharmony_ci		dma_addr = dma_map_single(ndev->dev.parent, priv->rx_skb[q][i]->data,
35462306a36Sopenharmony_ci					  GBETH_RX_BUFF_MAX,
35562306a36Sopenharmony_ci					  DMA_FROM_DEVICE);
35662306a36Sopenharmony_ci		/* We just set the data size to 0 for a failed mapping which
35762306a36Sopenharmony_ci		 * should prevent DMA from happening...
35862306a36Sopenharmony_ci		 */
35962306a36Sopenharmony_ci		if (dma_mapping_error(ndev->dev.parent, dma_addr))
36062306a36Sopenharmony_ci			rx_desc->ds_cc = cpu_to_le16(0);
36162306a36Sopenharmony_ci		rx_desc->dptr = cpu_to_le32(dma_addr);
36262306a36Sopenharmony_ci		rx_desc->die_dt = DT_FEMPTY;
36362306a36Sopenharmony_ci	}
36462306a36Sopenharmony_ci	rx_desc = &priv->gbeth_rx_ring[i];
36562306a36Sopenharmony_ci	rx_desc->dptr = cpu_to_le32((u32)priv->rx_desc_dma[q]);
36662306a36Sopenharmony_ci	rx_desc->die_dt = DT_LINKFIX; /* type */
36762306a36Sopenharmony_ci}
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_cistatic void ravb_rx_ring_format_rcar(struct net_device *ndev, int q)
37062306a36Sopenharmony_ci{
37162306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
37262306a36Sopenharmony_ci	struct ravb_ex_rx_desc *rx_desc;
37362306a36Sopenharmony_ci	unsigned int rx_ring_size = sizeof(*rx_desc) * priv->num_rx_ring[q];
37462306a36Sopenharmony_ci	dma_addr_t dma_addr;
37562306a36Sopenharmony_ci	unsigned int i;
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	memset(priv->rx_ring[q], 0, rx_ring_size);
37862306a36Sopenharmony_ci	/* Build RX ring buffer */
37962306a36Sopenharmony_ci	for (i = 0; i < priv->num_rx_ring[q]; i++) {
38062306a36Sopenharmony_ci		/* RX descriptor */
38162306a36Sopenharmony_ci		rx_desc = &priv->rx_ring[q][i];
38262306a36Sopenharmony_ci		rx_desc->ds_cc = cpu_to_le16(RX_BUF_SZ);
38362306a36Sopenharmony_ci		dma_addr = dma_map_single(ndev->dev.parent, priv->rx_skb[q][i]->data,
38462306a36Sopenharmony_ci					  RX_BUF_SZ,
38562306a36Sopenharmony_ci					  DMA_FROM_DEVICE);
38662306a36Sopenharmony_ci		/* We just set the data size to 0 for a failed mapping which
38762306a36Sopenharmony_ci		 * should prevent DMA from happening...
38862306a36Sopenharmony_ci		 */
38962306a36Sopenharmony_ci		if (dma_mapping_error(ndev->dev.parent, dma_addr))
39062306a36Sopenharmony_ci			rx_desc->ds_cc = cpu_to_le16(0);
39162306a36Sopenharmony_ci		rx_desc->dptr = cpu_to_le32(dma_addr);
39262306a36Sopenharmony_ci		rx_desc->die_dt = DT_FEMPTY;
39362306a36Sopenharmony_ci	}
39462306a36Sopenharmony_ci	rx_desc = &priv->rx_ring[q][i];
39562306a36Sopenharmony_ci	rx_desc->dptr = cpu_to_le32((u32)priv->rx_desc_dma[q]);
39662306a36Sopenharmony_ci	rx_desc->die_dt = DT_LINKFIX; /* type */
39762306a36Sopenharmony_ci}
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci/* Format skb and descriptor buffer for Ethernet AVB */
40062306a36Sopenharmony_cistatic void ravb_ring_format(struct net_device *ndev, int q)
40162306a36Sopenharmony_ci{
40262306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
40362306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
40462306a36Sopenharmony_ci	unsigned int num_tx_desc = priv->num_tx_desc;
40562306a36Sopenharmony_ci	struct ravb_tx_desc *tx_desc;
40662306a36Sopenharmony_ci	struct ravb_desc *desc;
40762306a36Sopenharmony_ci	unsigned int tx_ring_size = sizeof(*tx_desc) * priv->num_tx_ring[q] *
40862306a36Sopenharmony_ci				    num_tx_desc;
40962306a36Sopenharmony_ci	unsigned int i;
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci	priv->cur_rx[q] = 0;
41262306a36Sopenharmony_ci	priv->cur_tx[q] = 0;
41362306a36Sopenharmony_ci	priv->dirty_rx[q] = 0;
41462306a36Sopenharmony_ci	priv->dirty_tx[q] = 0;
41562306a36Sopenharmony_ci
41662306a36Sopenharmony_ci	info->rx_ring_format(ndev, q);
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	memset(priv->tx_ring[q], 0, tx_ring_size);
41962306a36Sopenharmony_ci	/* Build TX ring buffer */
42062306a36Sopenharmony_ci	for (i = 0, tx_desc = priv->tx_ring[q]; i < priv->num_tx_ring[q];
42162306a36Sopenharmony_ci	     i++, tx_desc++) {
42262306a36Sopenharmony_ci		tx_desc->die_dt = DT_EEMPTY;
42362306a36Sopenharmony_ci		if (num_tx_desc > 1) {
42462306a36Sopenharmony_ci			tx_desc++;
42562306a36Sopenharmony_ci			tx_desc->die_dt = DT_EEMPTY;
42662306a36Sopenharmony_ci		}
42762306a36Sopenharmony_ci	}
42862306a36Sopenharmony_ci	tx_desc->dptr = cpu_to_le32((u32)priv->tx_desc_dma[q]);
42962306a36Sopenharmony_ci	tx_desc->die_dt = DT_LINKFIX; /* type */
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	/* RX descriptor base address for best effort */
43262306a36Sopenharmony_ci	desc = &priv->desc_bat[RX_QUEUE_OFFSET + q];
43362306a36Sopenharmony_ci	desc->die_dt = DT_LINKFIX; /* type */
43462306a36Sopenharmony_ci	desc->dptr = cpu_to_le32((u32)priv->rx_desc_dma[q]);
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ci	/* TX descriptor base address for best effort */
43762306a36Sopenharmony_ci	desc = &priv->desc_bat[q];
43862306a36Sopenharmony_ci	desc->die_dt = DT_LINKFIX; /* type */
43962306a36Sopenharmony_ci	desc->dptr = cpu_to_le32((u32)priv->tx_desc_dma[q]);
44062306a36Sopenharmony_ci}
44162306a36Sopenharmony_ci
44262306a36Sopenharmony_cistatic void *ravb_alloc_rx_desc_gbeth(struct net_device *ndev, int q)
44362306a36Sopenharmony_ci{
44462306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
44562306a36Sopenharmony_ci	unsigned int ring_size;
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	ring_size = sizeof(struct ravb_rx_desc) * (priv->num_rx_ring[q] + 1);
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_ci	priv->gbeth_rx_ring = dma_alloc_coherent(ndev->dev.parent, ring_size,
45062306a36Sopenharmony_ci						 &priv->rx_desc_dma[q],
45162306a36Sopenharmony_ci						 GFP_KERNEL);
45262306a36Sopenharmony_ci	return priv->gbeth_rx_ring;
45362306a36Sopenharmony_ci}
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_cistatic void *ravb_alloc_rx_desc_rcar(struct net_device *ndev, int q)
45662306a36Sopenharmony_ci{
45762306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
45862306a36Sopenharmony_ci	unsigned int ring_size;
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	ring_size = sizeof(struct ravb_ex_rx_desc) * (priv->num_rx_ring[q] + 1);
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci	priv->rx_ring[q] = dma_alloc_coherent(ndev->dev.parent, ring_size,
46362306a36Sopenharmony_ci					      &priv->rx_desc_dma[q],
46462306a36Sopenharmony_ci					      GFP_KERNEL);
46562306a36Sopenharmony_ci	return priv->rx_ring[q];
46662306a36Sopenharmony_ci}
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci/* Init skb and descriptor buffer for Ethernet AVB */
46962306a36Sopenharmony_cistatic int ravb_ring_init(struct net_device *ndev, int q)
47062306a36Sopenharmony_ci{
47162306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
47262306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
47362306a36Sopenharmony_ci	unsigned int num_tx_desc = priv->num_tx_desc;
47462306a36Sopenharmony_ci	unsigned int ring_size;
47562306a36Sopenharmony_ci	struct sk_buff *skb;
47662306a36Sopenharmony_ci	unsigned int i;
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci	/* Allocate RX and TX skb rings */
47962306a36Sopenharmony_ci	priv->rx_skb[q] = kcalloc(priv->num_rx_ring[q],
48062306a36Sopenharmony_ci				  sizeof(*priv->rx_skb[q]), GFP_KERNEL);
48162306a36Sopenharmony_ci	priv->tx_skb[q] = kcalloc(priv->num_tx_ring[q],
48262306a36Sopenharmony_ci				  sizeof(*priv->tx_skb[q]), GFP_KERNEL);
48362306a36Sopenharmony_ci	if (!priv->rx_skb[q] || !priv->tx_skb[q])
48462306a36Sopenharmony_ci		goto error;
48562306a36Sopenharmony_ci
48662306a36Sopenharmony_ci	for (i = 0; i < priv->num_rx_ring[q]; i++) {
48762306a36Sopenharmony_ci		skb = __netdev_alloc_skb(ndev, info->max_rx_len, GFP_KERNEL);
48862306a36Sopenharmony_ci		if (!skb)
48962306a36Sopenharmony_ci			goto error;
49062306a36Sopenharmony_ci		ravb_set_buffer_align(skb);
49162306a36Sopenharmony_ci		priv->rx_skb[q][i] = skb;
49262306a36Sopenharmony_ci	}
49362306a36Sopenharmony_ci
49462306a36Sopenharmony_ci	if (num_tx_desc > 1) {
49562306a36Sopenharmony_ci		/* Allocate rings for the aligned buffers */
49662306a36Sopenharmony_ci		priv->tx_align[q] = kmalloc(DPTR_ALIGN * priv->num_tx_ring[q] +
49762306a36Sopenharmony_ci					    DPTR_ALIGN - 1, GFP_KERNEL);
49862306a36Sopenharmony_ci		if (!priv->tx_align[q])
49962306a36Sopenharmony_ci			goto error;
50062306a36Sopenharmony_ci	}
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci	/* Allocate all RX descriptors. */
50362306a36Sopenharmony_ci	if (!info->alloc_rx_desc(ndev, q))
50462306a36Sopenharmony_ci		goto error;
50562306a36Sopenharmony_ci
50662306a36Sopenharmony_ci	priv->dirty_rx[q] = 0;
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci	/* Allocate all TX descriptors. */
50962306a36Sopenharmony_ci	ring_size = sizeof(struct ravb_tx_desc) *
51062306a36Sopenharmony_ci		    (priv->num_tx_ring[q] * num_tx_desc + 1);
51162306a36Sopenharmony_ci	priv->tx_ring[q] = dma_alloc_coherent(ndev->dev.parent, ring_size,
51262306a36Sopenharmony_ci					      &priv->tx_desc_dma[q],
51362306a36Sopenharmony_ci					      GFP_KERNEL);
51462306a36Sopenharmony_ci	if (!priv->tx_ring[q])
51562306a36Sopenharmony_ci		goto error;
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci	return 0;
51862306a36Sopenharmony_ci
51962306a36Sopenharmony_cierror:
52062306a36Sopenharmony_ci	ravb_ring_free(ndev, q);
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	return -ENOMEM;
52362306a36Sopenharmony_ci}
52462306a36Sopenharmony_ci
52562306a36Sopenharmony_cistatic void ravb_emac_init_gbeth(struct net_device *ndev)
52662306a36Sopenharmony_ci{
52762306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	if (priv->phy_interface == PHY_INTERFACE_MODE_MII) {
53062306a36Sopenharmony_ci		ravb_write(ndev, (1000 << 16) | CXR35_SEL_XMII_MII, CXR35);
53162306a36Sopenharmony_ci		ravb_modify(ndev, CXR31, CXR31_SEL_LINK0 | CXR31_SEL_LINK1, 0);
53262306a36Sopenharmony_ci	} else {
53362306a36Sopenharmony_ci		ravb_write(ndev, (1000 << 16) | CXR35_SEL_XMII_RGMII, CXR35);
53462306a36Sopenharmony_ci		ravb_modify(ndev, CXR31, CXR31_SEL_LINK0 | CXR31_SEL_LINK1,
53562306a36Sopenharmony_ci			    CXR31_SEL_LINK0);
53662306a36Sopenharmony_ci	}
53762306a36Sopenharmony_ci
53862306a36Sopenharmony_ci	/* Receive frame limit set register */
53962306a36Sopenharmony_ci	ravb_write(ndev, GBETH_RX_BUFF_MAX + ETH_FCS_LEN, RFLR);
54062306a36Sopenharmony_ci
54162306a36Sopenharmony_ci	/* EMAC Mode: PAUSE prohibition; Duplex; TX; RX; CRC Pass Through */
54262306a36Sopenharmony_ci	ravb_write(ndev, ECMR_ZPF | ((priv->duplex > 0) ? ECMR_DM : 0) |
54362306a36Sopenharmony_ci			 ECMR_TE | ECMR_RE | ECMR_RCPT |
54462306a36Sopenharmony_ci			 ECMR_TXF | ECMR_RXF, ECMR);
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	ravb_set_rate_gbeth(ndev);
54762306a36Sopenharmony_ci
54862306a36Sopenharmony_ci	/* Set MAC address */
54962306a36Sopenharmony_ci	ravb_write(ndev,
55062306a36Sopenharmony_ci		   (ndev->dev_addr[0] << 24) | (ndev->dev_addr[1] << 16) |
55162306a36Sopenharmony_ci		   (ndev->dev_addr[2] << 8)  | (ndev->dev_addr[3]), MAHR);
55262306a36Sopenharmony_ci	ravb_write(ndev, (ndev->dev_addr[4] << 8)  | (ndev->dev_addr[5]), MALR);
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_ci	/* E-MAC status register clear */
55562306a36Sopenharmony_ci	ravb_write(ndev, ECSR_ICD | ECSR_LCHNG | ECSR_PFRI, ECSR);
55662306a36Sopenharmony_ci	ravb_write(ndev, CSR0_TPE | CSR0_RPE, CSR0);
55762306a36Sopenharmony_ci
55862306a36Sopenharmony_ci	/* E-MAC interrupt enable register */
55962306a36Sopenharmony_ci	ravb_write(ndev, ECSIPR_ICDIP, ECSIPR);
56062306a36Sopenharmony_ci}
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_cistatic void ravb_emac_init_rcar(struct net_device *ndev)
56362306a36Sopenharmony_ci{
56462306a36Sopenharmony_ci	/* Receive frame limit set register */
56562306a36Sopenharmony_ci	ravb_write(ndev, ndev->mtu + ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN, RFLR);
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_ci	/* EMAC Mode: PAUSE prohibition; Duplex; RX Checksum; TX; RX */
56862306a36Sopenharmony_ci	ravb_write(ndev, ECMR_ZPF | ECMR_DM |
56962306a36Sopenharmony_ci		   (ndev->features & NETIF_F_RXCSUM ? ECMR_RCSC : 0) |
57062306a36Sopenharmony_ci		   ECMR_TE | ECMR_RE, ECMR);
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci	ravb_set_rate_rcar(ndev);
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ci	/* Set MAC address */
57562306a36Sopenharmony_ci	ravb_write(ndev,
57662306a36Sopenharmony_ci		   (ndev->dev_addr[0] << 24) | (ndev->dev_addr[1] << 16) |
57762306a36Sopenharmony_ci		   (ndev->dev_addr[2] << 8)  | (ndev->dev_addr[3]), MAHR);
57862306a36Sopenharmony_ci	ravb_write(ndev,
57962306a36Sopenharmony_ci		   (ndev->dev_addr[4] << 8)  | (ndev->dev_addr[5]), MALR);
58062306a36Sopenharmony_ci
58162306a36Sopenharmony_ci	/* E-MAC status register clear */
58262306a36Sopenharmony_ci	ravb_write(ndev, ECSR_ICD | ECSR_MPD, ECSR);
58362306a36Sopenharmony_ci
58462306a36Sopenharmony_ci	/* E-MAC interrupt enable register */
58562306a36Sopenharmony_ci	ravb_write(ndev, ECSIPR_ICDIP | ECSIPR_MPDIP | ECSIPR_LCHNGIP, ECSIPR);
58662306a36Sopenharmony_ci}
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_ci/* E-MAC init function */
58962306a36Sopenharmony_cistatic void ravb_emac_init(struct net_device *ndev)
59062306a36Sopenharmony_ci{
59162306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
59262306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_ci	info->emac_init(ndev);
59562306a36Sopenharmony_ci}
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_cistatic int ravb_dmac_init_gbeth(struct net_device *ndev)
59862306a36Sopenharmony_ci{
59962306a36Sopenharmony_ci	int error;
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci	error = ravb_ring_init(ndev, RAVB_BE);
60262306a36Sopenharmony_ci	if (error)
60362306a36Sopenharmony_ci		return error;
60462306a36Sopenharmony_ci
60562306a36Sopenharmony_ci	/* Descriptor format */
60662306a36Sopenharmony_ci	ravb_ring_format(ndev, RAVB_BE);
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci	/* Set DMAC RX */
60962306a36Sopenharmony_ci	ravb_write(ndev, 0x60000000, RCR);
61062306a36Sopenharmony_ci
61162306a36Sopenharmony_ci	/* Set Max Frame Length (RTC) */
61262306a36Sopenharmony_ci	ravb_write(ndev, 0x7ffc0000 | GBETH_RX_BUFF_MAX, RTC);
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci	/* Set FIFO size */
61562306a36Sopenharmony_ci	ravb_write(ndev, 0x00222200, TGC);
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	ravb_write(ndev, 0, TCCR);
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci	/* Frame receive */
62062306a36Sopenharmony_ci	ravb_write(ndev, RIC0_FRE0, RIC0);
62162306a36Sopenharmony_ci	/* Disable FIFO full warning */
62262306a36Sopenharmony_ci	ravb_write(ndev, 0x0, RIC1);
62362306a36Sopenharmony_ci	/* Receive FIFO full error, descriptor empty */
62462306a36Sopenharmony_ci	ravb_write(ndev, RIC2_QFE0 | RIC2_RFFE, RIC2);
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci	ravb_write(ndev, TIC_FTE0, TIC);
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci	return 0;
62962306a36Sopenharmony_ci}
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_cistatic int ravb_dmac_init_rcar(struct net_device *ndev)
63262306a36Sopenharmony_ci{
63362306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
63462306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
63562306a36Sopenharmony_ci	int error;
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_ci	error = ravb_ring_init(ndev, RAVB_BE);
63862306a36Sopenharmony_ci	if (error)
63962306a36Sopenharmony_ci		return error;
64062306a36Sopenharmony_ci	error = ravb_ring_init(ndev, RAVB_NC);
64162306a36Sopenharmony_ci	if (error) {
64262306a36Sopenharmony_ci		ravb_ring_free(ndev, RAVB_BE);
64362306a36Sopenharmony_ci		return error;
64462306a36Sopenharmony_ci	}
64562306a36Sopenharmony_ci
64662306a36Sopenharmony_ci	/* Descriptor format */
64762306a36Sopenharmony_ci	ravb_ring_format(ndev, RAVB_BE);
64862306a36Sopenharmony_ci	ravb_ring_format(ndev, RAVB_NC);
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci	/* Set AVB RX */
65162306a36Sopenharmony_ci	ravb_write(ndev,
65262306a36Sopenharmony_ci		   RCR_EFFS | RCR_ENCF | RCR_ETS0 | RCR_ESF | 0x18000000, RCR);
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_ci	/* Set FIFO size */
65562306a36Sopenharmony_ci	ravb_write(ndev, TGC_TQP_AVBMODE1 | 0x00112200, TGC);
65662306a36Sopenharmony_ci
65762306a36Sopenharmony_ci	/* Timestamp enable */
65862306a36Sopenharmony_ci	ravb_write(ndev, TCCR_TFEN, TCCR);
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_ci	/* Interrupt init: */
66162306a36Sopenharmony_ci	if (info->multi_irqs) {
66262306a36Sopenharmony_ci		/* Clear DIL.DPLx */
66362306a36Sopenharmony_ci		ravb_write(ndev, 0, DIL);
66462306a36Sopenharmony_ci		/* Set queue specific interrupt */
66562306a36Sopenharmony_ci		ravb_write(ndev, CIE_CRIE | CIE_CTIE | CIE_CL0M, CIE);
66662306a36Sopenharmony_ci	}
66762306a36Sopenharmony_ci	/* Frame receive */
66862306a36Sopenharmony_ci	ravb_write(ndev, RIC0_FRE0 | RIC0_FRE1, RIC0);
66962306a36Sopenharmony_ci	/* Disable FIFO full warning */
67062306a36Sopenharmony_ci	ravb_write(ndev, 0, RIC1);
67162306a36Sopenharmony_ci	/* Receive FIFO full error, descriptor empty */
67262306a36Sopenharmony_ci	ravb_write(ndev, RIC2_QFE0 | RIC2_QFE1 | RIC2_RFFE, RIC2);
67362306a36Sopenharmony_ci	/* Frame transmitted, timestamp FIFO updated */
67462306a36Sopenharmony_ci	ravb_write(ndev, TIC_FTE0 | TIC_FTE1 | TIC_TFUE, TIC);
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci	return 0;
67762306a36Sopenharmony_ci}
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_ci/* Device init function for Ethernet AVB */
68062306a36Sopenharmony_cistatic int ravb_dmac_init(struct net_device *ndev)
68162306a36Sopenharmony_ci{
68262306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
68362306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
68462306a36Sopenharmony_ci	int error;
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci	/* Set CONFIG mode */
68762306a36Sopenharmony_ci	error = ravb_set_opmode(ndev, CCC_OPC_CONFIG);
68862306a36Sopenharmony_ci	if (error)
68962306a36Sopenharmony_ci		return error;
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci	error = info->dmac_init(ndev);
69262306a36Sopenharmony_ci	if (error)
69362306a36Sopenharmony_ci		return error;
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci	/* Setting the control will start the AVB-DMAC process. */
69662306a36Sopenharmony_ci	return ravb_set_opmode(ndev, CCC_OPC_OPERATION);
69762306a36Sopenharmony_ci}
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_cistatic void ravb_get_tx_tstamp(struct net_device *ndev)
70062306a36Sopenharmony_ci{
70162306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
70262306a36Sopenharmony_ci	struct ravb_tstamp_skb *ts_skb, *ts_skb2;
70362306a36Sopenharmony_ci	struct skb_shared_hwtstamps shhwtstamps;
70462306a36Sopenharmony_ci	struct sk_buff *skb;
70562306a36Sopenharmony_ci	struct timespec64 ts;
70662306a36Sopenharmony_ci	u16 tag, tfa_tag;
70762306a36Sopenharmony_ci	int count;
70862306a36Sopenharmony_ci	u32 tfa2;
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_ci	count = (ravb_read(ndev, TSR) & TSR_TFFL) >> 8;
71162306a36Sopenharmony_ci	while (count--) {
71262306a36Sopenharmony_ci		tfa2 = ravb_read(ndev, TFA2);
71362306a36Sopenharmony_ci		tfa_tag = (tfa2 & TFA2_TST) >> 16;
71462306a36Sopenharmony_ci		ts.tv_nsec = (u64)ravb_read(ndev, TFA0);
71562306a36Sopenharmony_ci		ts.tv_sec = ((u64)(tfa2 & TFA2_TSV) << 32) |
71662306a36Sopenharmony_ci			    ravb_read(ndev, TFA1);
71762306a36Sopenharmony_ci		memset(&shhwtstamps, 0, sizeof(shhwtstamps));
71862306a36Sopenharmony_ci		shhwtstamps.hwtstamp = timespec64_to_ktime(ts);
71962306a36Sopenharmony_ci		list_for_each_entry_safe(ts_skb, ts_skb2, &priv->ts_skb_list,
72062306a36Sopenharmony_ci					 list) {
72162306a36Sopenharmony_ci			skb = ts_skb->skb;
72262306a36Sopenharmony_ci			tag = ts_skb->tag;
72362306a36Sopenharmony_ci			list_del(&ts_skb->list);
72462306a36Sopenharmony_ci			kfree(ts_skb);
72562306a36Sopenharmony_ci			if (tag == tfa_tag) {
72662306a36Sopenharmony_ci				skb_tstamp_tx(skb, &shhwtstamps);
72762306a36Sopenharmony_ci				dev_consume_skb_any(skb);
72862306a36Sopenharmony_ci				break;
72962306a36Sopenharmony_ci			} else {
73062306a36Sopenharmony_ci				dev_kfree_skb_any(skb);
73162306a36Sopenharmony_ci			}
73262306a36Sopenharmony_ci		}
73362306a36Sopenharmony_ci		ravb_modify(ndev, TCCR, TCCR_TFR, TCCR_TFR);
73462306a36Sopenharmony_ci	}
73562306a36Sopenharmony_ci}
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_cistatic void ravb_rx_csum(struct sk_buff *skb)
73862306a36Sopenharmony_ci{
73962306a36Sopenharmony_ci	u8 *hw_csum;
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_ci	/* The hardware checksum is contained in sizeof(__sum16) (2) bytes
74262306a36Sopenharmony_ci	 * appended to packet data
74362306a36Sopenharmony_ci	 */
74462306a36Sopenharmony_ci	if (unlikely(skb->len < sizeof(__sum16)))
74562306a36Sopenharmony_ci		return;
74662306a36Sopenharmony_ci	hw_csum = skb_tail_pointer(skb) - sizeof(__sum16);
74762306a36Sopenharmony_ci	skb->csum = csum_unfold((__force __sum16)get_unaligned_le16(hw_csum));
74862306a36Sopenharmony_ci	skb->ip_summed = CHECKSUM_COMPLETE;
74962306a36Sopenharmony_ci	skb_trim(skb, skb->len - sizeof(__sum16));
75062306a36Sopenharmony_ci}
75162306a36Sopenharmony_ci
75262306a36Sopenharmony_cistatic struct sk_buff *ravb_get_skb_gbeth(struct net_device *ndev, int entry,
75362306a36Sopenharmony_ci					  struct ravb_rx_desc *desc)
75462306a36Sopenharmony_ci{
75562306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
75662306a36Sopenharmony_ci	struct sk_buff *skb;
75762306a36Sopenharmony_ci
75862306a36Sopenharmony_ci	skb = priv->rx_skb[RAVB_BE][entry];
75962306a36Sopenharmony_ci	priv->rx_skb[RAVB_BE][entry] = NULL;
76062306a36Sopenharmony_ci	dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr),
76162306a36Sopenharmony_ci			 ALIGN(GBETH_RX_BUFF_MAX, 16), DMA_FROM_DEVICE);
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_ci	return skb;
76462306a36Sopenharmony_ci}
76562306a36Sopenharmony_ci
76662306a36Sopenharmony_ci/* Packet receive function for Gigabit Ethernet */
76762306a36Sopenharmony_cistatic bool ravb_rx_gbeth(struct net_device *ndev, int *quota, int q)
76862306a36Sopenharmony_ci{
76962306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
77062306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
77162306a36Sopenharmony_ci	struct net_device_stats *stats;
77262306a36Sopenharmony_ci	struct ravb_rx_desc *desc;
77362306a36Sopenharmony_ci	struct sk_buff *skb;
77462306a36Sopenharmony_ci	dma_addr_t dma_addr;
77562306a36Sopenharmony_ci	u8  desc_status;
77662306a36Sopenharmony_ci	int boguscnt;
77762306a36Sopenharmony_ci	u16 pkt_len;
77862306a36Sopenharmony_ci	u8  die_dt;
77962306a36Sopenharmony_ci	int entry;
78062306a36Sopenharmony_ci	int limit;
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci	entry = priv->cur_rx[q] % priv->num_rx_ring[q];
78362306a36Sopenharmony_ci	boguscnt = priv->dirty_rx[q] + priv->num_rx_ring[q] - priv->cur_rx[q];
78462306a36Sopenharmony_ci	stats = &priv->stats[q];
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci	boguscnt = min(boguscnt, *quota);
78762306a36Sopenharmony_ci	limit = boguscnt;
78862306a36Sopenharmony_ci	desc = &priv->gbeth_rx_ring[entry];
78962306a36Sopenharmony_ci	while (desc->die_dt != DT_FEMPTY) {
79062306a36Sopenharmony_ci		/* Descriptor type must be checked before all other reads */
79162306a36Sopenharmony_ci		dma_rmb();
79262306a36Sopenharmony_ci		desc_status = desc->msc;
79362306a36Sopenharmony_ci		pkt_len = le16_to_cpu(desc->ds_cc) & RX_DS;
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ci		if (--boguscnt < 0)
79662306a36Sopenharmony_ci			break;
79762306a36Sopenharmony_ci
79862306a36Sopenharmony_ci		/* We use 0-byte descriptors to mark the DMA mapping errors */
79962306a36Sopenharmony_ci		if (!pkt_len)
80062306a36Sopenharmony_ci			continue;
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci		if (desc_status & MSC_MC)
80362306a36Sopenharmony_ci			stats->multicast++;
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_ci		if (desc_status & (MSC_CRC | MSC_RFE | MSC_RTSF | MSC_RTLF | MSC_CEEF)) {
80662306a36Sopenharmony_ci			stats->rx_errors++;
80762306a36Sopenharmony_ci			if (desc_status & MSC_CRC)
80862306a36Sopenharmony_ci				stats->rx_crc_errors++;
80962306a36Sopenharmony_ci			if (desc_status & MSC_RFE)
81062306a36Sopenharmony_ci				stats->rx_frame_errors++;
81162306a36Sopenharmony_ci			if (desc_status & (MSC_RTLF | MSC_RTSF))
81262306a36Sopenharmony_ci				stats->rx_length_errors++;
81362306a36Sopenharmony_ci			if (desc_status & MSC_CEEF)
81462306a36Sopenharmony_ci				stats->rx_missed_errors++;
81562306a36Sopenharmony_ci		} else {
81662306a36Sopenharmony_ci			die_dt = desc->die_dt & 0xF0;
81762306a36Sopenharmony_ci			switch (die_dt) {
81862306a36Sopenharmony_ci			case DT_FSINGLE:
81962306a36Sopenharmony_ci				skb = ravb_get_skb_gbeth(ndev, entry, desc);
82062306a36Sopenharmony_ci				skb_put(skb, pkt_len);
82162306a36Sopenharmony_ci				skb->protocol = eth_type_trans(skb, ndev);
82262306a36Sopenharmony_ci				napi_gro_receive(&priv->napi[q], skb);
82362306a36Sopenharmony_ci				stats->rx_packets++;
82462306a36Sopenharmony_ci				stats->rx_bytes += pkt_len;
82562306a36Sopenharmony_ci				break;
82662306a36Sopenharmony_ci			case DT_FSTART:
82762306a36Sopenharmony_ci				priv->rx_1st_skb = ravb_get_skb_gbeth(ndev, entry, desc);
82862306a36Sopenharmony_ci				skb_put(priv->rx_1st_skb, pkt_len);
82962306a36Sopenharmony_ci				break;
83062306a36Sopenharmony_ci			case DT_FMID:
83162306a36Sopenharmony_ci				skb = ravb_get_skb_gbeth(ndev, entry, desc);
83262306a36Sopenharmony_ci				skb_copy_to_linear_data_offset(priv->rx_1st_skb,
83362306a36Sopenharmony_ci							       priv->rx_1st_skb->len,
83462306a36Sopenharmony_ci							       skb->data,
83562306a36Sopenharmony_ci							       pkt_len);
83662306a36Sopenharmony_ci				skb_put(priv->rx_1st_skb, pkt_len);
83762306a36Sopenharmony_ci				dev_kfree_skb(skb);
83862306a36Sopenharmony_ci				break;
83962306a36Sopenharmony_ci			case DT_FEND:
84062306a36Sopenharmony_ci				skb = ravb_get_skb_gbeth(ndev, entry, desc);
84162306a36Sopenharmony_ci				skb_copy_to_linear_data_offset(priv->rx_1st_skb,
84262306a36Sopenharmony_ci							       priv->rx_1st_skb->len,
84362306a36Sopenharmony_ci							       skb->data,
84462306a36Sopenharmony_ci							       pkt_len);
84562306a36Sopenharmony_ci				skb_put(priv->rx_1st_skb, pkt_len);
84662306a36Sopenharmony_ci				dev_kfree_skb(skb);
84762306a36Sopenharmony_ci				priv->rx_1st_skb->protocol =
84862306a36Sopenharmony_ci					eth_type_trans(priv->rx_1st_skb, ndev);
84962306a36Sopenharmony_ci				napi_gro_receive(&priv->napi[q],
85062306a36Sopenharmony_ci						 priv->rx_1st_skb);
85162306a36Sopenharmony_ci				stats->rx_packets++;
85262306a36Sopenharmony_ci				stats->rx_bytes += pkt_len;
85362306a36Sopenharmony_ci				break;
85462306a36Sopenharmony_ci			}
85562306a36Sopenharmony_ci		}
85662306a36Sopenharmony_ci
85762306a36Sopenharmony_ci		entry = (++priv->cur_rx[q]) % priv->num_rx_ring[q];
85862306a36Sopenharmony_ci		desc = &priv->gbeth_rx_ring[entry];
85962306a36Sopenharmony_ci	}
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_ci	/* Refill the RX ring buffers. */
86262306a36Sopenharmony_ci	for (; priv->cur_rx[q] - priv->dirty_rx[q] > 0; priv->dirty_rx[q]++) {
86362306a36Sopenharmony_ci		entry = priv->dirty_rx[q] % priv->num_rx_ring[q];
86462306a36Sopenharmony_ci		desc = &priv->gbeth_rx_ring[entry];
86562306a36Sopenharmony_ci		desc->ds_cc = cpu_to_le16(GBETH_RX_DESC_DATA_SIZE);
86662306a36Sopenharmony_ci
86762306a36Sopenharmony_ci		if (!priv->rx_skb[q][entry]) {
86862306a36Sopenharmony_ci			skb = netdev_alloc_skb(ndev, info->max_rx_len);
86962306a36Sopenharmony_ci			if (!skb)
87062306a36Sopenharmony_ci				break;
87162306a36Sopenharmony_ci			ravb_set_buffer_align(skb);
87262306a36Sopenharmony_ci			dma_addr = dma_map_single(ndev->dev.parent,
87362306a36Sopenharmony_ci						  skb->data,
87462306a36Sopenharmony_ci						  GBETH_RX_BUFF_MAX,
87562306a36Sopenharmony_ci						  DMA_FROM_DEVICE);
87662306a36Sopenharmony_ci			skb_checksum_none_assert(skb);
87762306a36Sopenharmony_ci			/* We just set the data size to 0 for a failed mapping
87862306a36Sopenharmony_ci			 * which should prevent DMA  from happening...
87962306a36Sopenharmony_ci			 */
88062306a36Sopenharmony_ci			if (dma_mapping_error(ndev->dev.parent, dma_addr))
88162306a36Sopenharmony_ci				desc->ds_cc = cpu_to_le16(0);
88262306a36Sopenharmony_ci			desc->dptr = cpu_to_le32(dma_addr);
88362306a36Sopenharmony_ci			priv->rx_skb[q][entry] = skb;
88462306a36Sopenharmony_ci		}
88562306a36Sopenharmony_ci		/* Descriptor type must be set after all the above writes */
88662306a36Sopenharmony_ci		dma_wmb();
88762306a36Sopenharmony_ci		desc->die_dt = DT_FEMPTY;
88862306a36Sopenharmony_ci	}
88962306a36Sopenharmony_ci
89062306a36Sopenharmony_ci	*quota -= limit - (++boguscnt);
89162306a36Sopenharmony_ci
89262306a36Sopenharmony_ci	return boguscnt <= 0;
89362306a36Sopenharmony_ci}
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_ci/* Packet receive function for Ethernet AVB */
89662306a36Sopenharmony_cistatic bool ravb_rx_rcar(struct net_device *ndev, int *quota, int q)
89762306a36Sopenharmony_ci{
89862306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
89962306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
90062306a36Sopenharmony_ci	int entry = priv->cur_rx[q] % priv->num_rx_ring[q];
90162306a36Sopenharmony_ci	int boguscnt = (priv->dirty_rx[q] + priv->num_rx_ring[q]) -
90262306a36Sopenharmony_ci			priv->cur_rx[q];
90362306a36Sopenharmony_ci	struct net_device_stats *stats = &priv->stats[q];
90462306a36Sopenharmony_ci	struct ravb_ex_rx_desc *desc;
90562306a36Sopenharmony_ci	struct sk_buff *skb;
90662306a36Sopenharmony_ci	dma_addr_t dma_addr;
90762306a36Sopenharmony_ci	struct timespec64 ts;
90862306a36Sopenharmony_ci	u8  desc_status;
90962306a36Sopenharmony_ci	u16 pkt_len;
91062306a36Sopenharmony_ci	int limit;
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci	boguscnt = min(boguscnt, *quota);
91362306a36Sopenharmony_ci	limit = boguscnt;
91462306a36Sopenharmony_ci	desc = &priv->rx_ring[q][entry];
91562306a36Sopenharmony_ci	while (desc->die_dt != DT_FEMPTY) {
91662306a36Sopenharmony_ci		/* Descriptor type must be checked before all other reads */
91762306a36Sopenharmony_ci		dma_rmb();
91862306a36Sopenharmony_ci		desc_status = desc->msc;
91962306a36Sopenharmony_ci		pkt_len = le16_to_cpu(desc->ds_cc) & RX_DS;
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_ci		if (--boguscnt < 0)
92262306a36Sopenharmony_ci			break;
92362306a36Sopenharmony_ci
92462306a36Sopenharmony_ci		/* We use 0-byte descriptors to mark the DMA mapping errors */
92562306a36Sopenharmony_ci		if (!pkt_len)
92662306a36Sopenharmony_ci			continue;
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_ci		if (desc_status & MSC_MC)
92962306a36Sopenharmony_ci			stats->multicast++;
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci		if (desc_status & (MSC_CRC | MSC_RFE | MSC_RTSF | MSC_RTLF |
93262306a36Sopenharmony_ci				   MSC_CEEF)) {
93362306a36Sopenharmony_ci			stats->rx_errors++;
93462306a36Sopenharmony_ci			if (desc_status & MSC_CRC)
93562306a36Sopenharmony_ci				stats->rx_crc_errors++;
93662306a36Sopenharmony_ci			if (desc_status & MSC_RFE)
93762306a36Sopenharmony_ci				stats->rx_frame_errors++;
93862306a36Sopenharmony_ci			if (desc_status & (MSC_RTLF | MSC_RTSF))
93962306a36Sopenharmony_ci				stats->rx_length_errors++;
94062306a36Sopenharmony_ci			if (desc_status & MSC_CEEF)
94162306a36Sopenharmony_ci				stats->rx_missed_errors++;
94262306a36Sopenharmony_ci		} else {
94362306a36Sopenharmony_ci			u32 get_ts = priv->tstamp_rx_ctrl & RAVB_RXTSTAMP_TYPE;
94462306a36Sopenharmony_ci
94562306a36Sopenharmony_ci			skb = priv->rx_skb[q][entry];
94662306a36Sopenharmony_ci			priv->rx_skb[q][entry] = NULL;
94762306a36Sopenharmony_ci			dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr),
94862306a36Sopenharmony_ci					 RX_BUF_SZ,
94962306a36Sopenharmony_ci					 DMA_FROM_DEVICE);
95062306a36Sopenharmony_ci			get_ts &= (q == RAVB_NC) ?
95162306a36Sopenharmony_ci					RAVB_RXTSTAMP_TYPE_V2_L2_EVENT :
95262306a36Sopenharmony_ci					~RAVB_RXTSTAMP_TYPE_V2_L2_EVENT;
95362306a36Sopenharmony_ci			if (get_ts) {
95462306a36Sopenharmony_ci				struct skb_shared_hwtstamps *shhwtstamps;
95562306a36Sopenharmony_ci
95662306a36Sopenharmony_ci				shhwtstamps = skb_hwtstamps(skb);
95762306a36Sopenharmony_ci				memset(shhwtstamps, 0, sizeof(*shhwtstamps));
95862306a36Sopenharmony_ci				ts.tv_sec = ((u64) le16_to_cpu(desc->ts_sh) <<
95962306a36Sopenharmony_ci					     32) | le32_to_cpu(desc->ts_sl);
96062306a36Sopenharmony_ci				ts.tv_nsec = le32_to_cpu(desc->ts_n);
96162306a36Sopenharmony_ci				shhwtstamps->hwtstamp = timespec64_to_ktime(ts);
96262306a36Sopenharmony_ci			}
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_ci			skb_put(skb, pkt_len);
96562306a36Sopenharmony_ci			skb->protocol = eth_type_trans(skb, ndev);
96662306a36Sopenharmony_ci			if (ndev->features & NETIF_F_RXCSUM)
96762306a36Sopenharmony_ci				ravb_rx_csum(skb);
96862306a36Sopenharmony_ci			napi_gro_receive(&priv->napi[q], skb);
96962306a36Sopenharmony_ci			stats->rx_packets++;
97062306a36Sopenharmony_ci			stats->rx_bytes += pkt_len;
97162306a36Sopenharmony_ci		}
97262306a36Sopenharmony_ci
97362306a36Sopenharmony_ci		entry = (++priv->cur_rx[q]) % priv->num_rx_ring[q];
97462306a36Sopenharmony_ci		desc = &priv->rx_ring[q][entry];
97562306a36Sopenharmony_ci	}
97662306a36Sopenharmony_ci
97762306a36Sopenharmony_ci	/* Refill the RX ring buffers. */
97862306a36Sopenharmony_ci	for (; priv->cur_rx[q] - priv->dirty_rx[q] > 0; priv->dirty_rx[q]++) {
97962306a36Sopenharmony_ci		entry = priv->dirty_rx[q] % priv->num_rx_ring[q];
98062306a36Sopenharmony_ci		desc = &priv->rx_ring[q][entry];
98162306a36Sopenharmony_ci		desc->ds_cc = cpu_to_le16(RX_BUF_SZ);
98262306a36Sopenharmony_ci
98362306a36Sopenharmony_ci		if (!priv->rx_skb[q][entry]) {
98462306a36Sopenharmony_ci			skb = netdev_alloc_skb(ndev, info->max_rx_len);
98562306a36Sopenharmony_ci			if (!skb)
98662306a36Sopenharmony_ci				break;	/* Better luck next round. */
98762306a36Sopenharmony_ci			ravb_set_buffer_align(skb);
98862306a36Sopenharmony_ci			dma_addr = dma_map_single(ndev->dev.parent, skb->data,
98962306a36Sopenharmony_ci						  le16_to_cpu(desc->ds_cc),
99062306a36Sopenharmony_ci						  DMA_FROM_DEVICE);
99162306a36Sopenharmony_ci			skb_checksum_none_assert(skb);
99262306a36Sopenharmony_ci			/* We just set the data size to 0 for a failed mapping
99362306a36Sopenharmony_ci			 * which should prevent DMA  from happening...
99462306a36Sopenharmony_ci			 */
99562306a36Sopenharmony_ci			if (dma_mapping_error(ndev->dev.parent, dma_addr))
99662306a36Sopenharmony_ci				desc->ds_cc = cpu_to_le16(0);
99762306a36Sopenharmony_ci			desc->dptr = cpu_to_le32(dma_addr);
99862306a36Sopenharmony_ci			priv->rx_skb[q][entry] = skb;
99962306a36Sopenharmony_ci		}
100062306a36Sopenharmony_ci		/* Descriptor type must be set after all the above writes */
100162306a36Sopenharmony_ci		dma_wmb();
100262306a36Sopenharmony_ci		desc->die_dt = DT_FEMPTY;
100362306a36Sopenharmony_ci	}
100462306a36Sopenharmony_ci
100562306a36Sopenharmony_ci	*quota -= limit - (++boguscnt);
100662306a36Sopenharmony_ci
100762306a36Sopenharmony_ci	return boguscnt <= 0;
100862306a36Sopenharmony_ci}
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci/* Packet receive function for Ethernet AVB */
101162306a36Sopenharmony_cistatic bool ravb_rx(struct net_device *ndev, int *quota, int q)
101262306a36Sopenharmony_ci{
101362306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
101462306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
101562306a36Sopenharmony_ci
101662306a36Sopenharmony_ci	return info->receive(ndev, quota, q);
101762306a36Sopenharmony_ci}
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_cistatic void ravb_rcv_snd_disable(struct net_device *ndev)
102062306a36Sopenharmony_ci{
102162306a36Sopenharmony_ci	/* Disable TX and RX */
102262306a36Sopenharmony_ci	ravb_modify(ndev, ECMR, ECMR_RE | ECMR_TE, 0);
102362306a36Sopenharmony_ci}
102462306a36Sopenharmony_ci
102562306a36Sopenharmony_cistatic void ravb_rcv_snd_enable(struct net_device *ndev)
102662306a36Sopenharmony_ci{
102762306a36Sopenharmony_ci	/* Enable TX and RX */
102862306a36Sopenharmony_ci	ravb_modify(ndev, ECMR, ECMR_RE | ECMR_TE, ECMR_RE | ECMR_TE);
102962306a36Sopenharmony_ci}
103062306a36Sopenharmony_ci
103162306a36Sopenharmony_ci/* function for waiting dma process finished */
103262306a36Sopenharmony_cistatic int ravb_stop_dma(struct net_device *ndev)
103362306a36Sopenharmony_ci{
103462306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
103562306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
103662306a36Sopenharmony_ci	int error;
103762306a36Sopenharmony_ci
103862306a36Sopenharmony_ci	/* Wait for stopping the hardware TX process */
103962306a36Sopenharmony_ci	error = ravb_wait(ndev, TCCR, info->tccr_mask, 0);
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_ci	if (error)
104262306a36Sopenharmony_ci		return error;
104362306a36Sopenharmony_ci
104462306a36Sopenharmony_ci	error = ravb_wait(ndev, CSR, CSR_TPO0 | CSR_TPO1 | CSR_TPO2 | CSR_TPO3,
104562306a36Sopenharmony_ci			  0);
104662306a36Sopenharmony_ci	if (error)
104762306a36Sopenharmony_ci		return error;
104862306a36Sopenharmony_ci
104962306a36Sopenharmony_ci	/* Stop the E-MAC's RX/TX processes. */
105062306a36Sopenharmony_ci	ravb_rcv_snd_disable(ndev);
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_ci	/* Wait for stopping the RX DMA process */
105362306a36Sopenharmony_ci	error = ravb_wait(ndev, CSR, CSR_RPO, 0);
105462306a36Sopenharmony_ci	if (error)
105562306a36Sopenharmony_ci		return error;
105662306a36Sopenharmony_ci
105762306a36Sopenharmony_ci	/* Stop AVB-DMAC process */
105862306a36Sopenharmony_ci	return ravb_set_opmode(ndev, CCC_OPC_CONFIG);
105962306a36Sopenharmony_ci}
106062306a36Sopenharmony_ci
106162306a36Sopenharmony_ci/* E-MAC interrupt handler */
106262306a36Sopenharmony_cistatic void ravb_emac_interrupt_unlocked(struct net_device *ndev)
106362306a36Sopenharmony_ci{
106462306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
106562306a36Sopenharmony_ci	u32 ecsr, psr;
106662306a36Sopenharmony_ci
106762306a36Sopenharmony_ci	ecsr = ravb_read(ndev, ECSR);
106862306a36Sopenharmony_ci	ravb_write(ndev, ecsr, ECSR);	/* clear interrupt */
106962306a36Sopenharmony_ci
107062306a36Sopenharmony_ci	if (ecsr & ECSR_MPD)
107162306a36Sopenharmony_ci		pm_wakeup_event(&priv->pdev->dev, 0);
107262306a36Sopenharmony_ci	if (ecsr & ECSR_ICD)
107362306a36Sopenharmony_ci		ndev->stats.tx_carrier_errors++;
107462306a36Sopenharmony_ci	if (ecsr & ECSR_LCHNG) {
107562306a36Sopenharmony_ci		/* Link changed */
107662306a36Sopenharmony_ci		if (priv->no_avb_link)
107762306a36Sopenharmony_ci			return;
107862306a36Sopenharmony_ci		psr = ravb_read(ndev, PSR);
107962306a36Sopenharmony_ci		if (priv->avb_link_active_low)
108062306a36Sopenharmony_ci			psr ^= PSR_LMON;
108162306a36Sopenharmony_ci		if (!(psr & PSR_LMON)) {
108262306a36Sopenharmony_ci			/* DIsable RX and TX */
108362306a36Sopenharmony_ci			ravb_rcv_snd_disable(ndev);
108462306a36Sopenharmony_ci		} else {
108562306a36Sopenharmony_ci			/* Enable RX and TX */
108662306a36Sopenharmony_ci			ravb_rcv_snd_enable(ndev);
108762306a36Sopenharmony_ci		}
108862306a36Sopenharmony_ci	}
108962306a36Sopenharmony_ci}
109062306a36Sopenharmony_ci
109162306a36Sopenharmony_cistatic irqreturn_t ravb_emac_interrupt(int irq, void *dev_id)
109262306a36Sopenharmony_ci{
109362306a36Sopenharmony_ci	struct net_device *ndev = dev_id;
109462306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_ci	spin_lock(&priv->lock);
109762306a36Sopenharmony_ci	ravb_emac_interrupt_unlocked(ndev);
109862306a36Sopenharmony_ci	spin_unlock(&priv->lock);
109962306a36Sopenharmony_ci	return IRQ_HANDLED;
110062306a36Sopenharmony_ci}
110162306a36Sopenharmony_ci
110262306a36Sopenharmony_ci/* Error interrupt handler */
110362306a36Sopenharmony_cistatic void ravb_error_interrupt(struct net_device *ndev)
110462306a36Sopenharmony_ci{
110562306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
110662306a36Sopenharmony_ci	u32 eis, ris2;
110762306a36Sopenharmony_ci
110862306a36Sopenharmony_ci	eis = ravb_read(ndev, EIS);
110962306a36Sopenharmony_ci	ravb_write(ndev, ~(EIS_QFS | EIS_RESERVED), EIS);
111062306a36Sopenharmony_ci	if (eis & EIS_QFS) {
111162306a36Sopenharmony_ci		ris2 = ravb_read(ndev, RIS2);
111262306a36Sopenharmony_ci		ravb_write(ndev, ~(RIS2_QFF0 | RIS2_QFF1 | RIS2_RFFF | RIS2_RESERVED),
111362306a36Sopenharmony_ci			   RIS2);
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_ci		/* Receive Descriptor Empty int */
111662306a36Sopenharmony_ci		if (ris2 & RIS2_QFF0)
111762306a36Sopenharmony_ci			priv->stats[RAVB_BE].rx_over_errors++;
111862306a36Sopenharmony_ci
111962306a36Sopenharmony_ci		/* Receive Descriptor Empty int */
112062306a36Sopenharmony_ci		if (ris2 & RIS2_QFF1)
112162306a36Sopenharmony_ci			priv->stats[RAVB_NC].rx_over_errors++;
112262306a36Sopenharmony_ci
112362306a36Sopenharmony_ci		/* Receive FIFO Overflow int */
112462306a36Sopenharmony_ci		if (ris2 & RIS2_RFFF)
112562306a36Sopenharmony_ci			priv->rx_fifo_errors++;
112662306a36Sopenharmony_ci	}
112762306a36Sopenharmony_ci}
112862306a36Sopenharmony_ci
112962306a36Sopenharmony_cistatic bool ravb_queue_interrupt(struct net_device *ndev, int q)
113062306a36Sopenharmony_ci{
113162306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
113262306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
113362306a36Sopenharmony_ci	u32 ris0 = ravb_read(ndev, RIS0);
113462306a36Sopenharmony_ci	u32 ric0 = ravb_read(ndev, RIC0);
113562306a36Sopenharmony_ci	u32 tis  = ravb_read(ndev, TIS);
113662306a36Sopenharmony_ci	u32 tic  = ravb_read(ndev, TIC);
113762306a36Sopenharmony_ci
113862306a36Sopenharmony_ci	if (((ris0 & ric0) & BIT(q)) || ((tis  & tic)  & BIT(q))) {
113962306a36Sopenharmony_ci		if (napi_schedule_prep(&priv->napi[q])) {
114062306a36Sopenharmony_ci			/* Mask RX and TX interrupts */
114162306a36Sopenharmony_ci			if (!info->irq_en_dis) {
114262306a36Sopenharmony_ci				ravb_write(ndev, ric0 & ~BIT(q), RIC0);
114362306a36Sopenharmony_ci				ravb_write(ndev, tic & ~BIT(q), TIC);
114462306a36Sopenharmony_ci			} else {
114562306a36Sopenharmony_ci				ravb_write(ndev, BIT(q), RID0);
114662306a36Sopenharmony_ci				ravb_write(ndev, BIT(q), TID);
114762306a36Sopenharmony_ci			}
114862306a36Sopenharmony_ci			__napi_schedule(&priv->napi[q]);
114962306a36Sopenharmony_ci		} else {
115062306a36Sopenharmony_ci			netdev_warn(ndev,
115162306a36Sopenharmony_ci				    "ignoring interrupt, rx status 0x%08x, rx mask 0x%08x,\n",
115262306a36Sopenharmony_ci				    ris0, ric0);
115362306a36Sopenharmony_ci			netdev_warn(ndev,
115462306a36Sopenharmony_ci				    "                    tx status 0x%08x, tx mask 0x%08x.\n",
115562306a36Sopenharmony_ci				    tis, tic);
115662306a36Sopenharmony_ci		}
115762306a36Sopenharmony_ci		return true;
115862306a36Sopenharmony_ci	}
115962306a36Sopenharmony_ci	return false;
116062306a36Sopenharmony_ci}
116162306a36Sopenharmony_ci
116262306a36Sopenharmony_cistatic bool ravb_timestamp_interrupt(struct net_device *ndev)
116362306a36Sopenharmony_ci{
116462306a36Sopenharmony_ci	u32 tis = ravb_read(ndev, TIS);
116562306a36Sopenharmony_ci
116662306a36Sopenharmony_ci	if (tis & TIS_TFUF) {
116762306a36Sopenharmony_ci		ravb_write(ndev, ~(TIS_TFUF | TIS_RESERVED), TIS);
116862306a36Sopenharmony_ci		ravb_get_tx_tstamp(ndev);
116962306a36Sopenharmony_ci		return true;
117062306a36Sopenharmony_ci	}
117162306a36Sopenharmony_ci	return false;
117262306a36Sopenharmony_ci}
117362306a36Sopenharmony_ci
117462306a36Sopenharmony_cistatic irqreturn_t ravb_interrupt(int irq, void *dev_id)
117562306a36Sopenharmony_ci{
117662306a36Sopenharmony_ci	struct net_device *ndev = dev_id;
117762306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
117862306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
117962306a36Sopenharmony_ci	irqreturn_t result = IRQ_NONE;
118062306a36Sopenharmony_ci	u32 iss;
118162306a36Sopenharmony_ci
118262306a36Sopenharmony_ci	spin_lock(&priv->lock);
118362306a36Sopenharmony_ci	/* Get interrupt status */
118462306a36Sopenharmony_ci	iss = ravb_read(ndev, ISS);
118562306a36Sopenharmony_ci
118662306a36Sopenharmony_ci	/* Received and transmitted interrupts */
118762306a36Sopenharmony_ci	if (iss & (ISS_FRS | ISS_FTS | ISS_TFUS)) {
118862306a36Sopenharmony_ci		int q;
118962306a36Sopenharmony_ci
119062306a36Sopenharmony_ci		/* Timestamp updated */
119162306a36Sopenharmony_ci		if (ravb_timestamp_interrupt(ndev))
119262306a36Sopenharmony_ci			result = IRQ_HANDLED;
119362306a36Sopenharmony_ci
119462306a36Sopenharmony_ci		/* Network control and best effort queue RX/TX */
119562306a36Sopenharmony_ci		if (info->nc_queues) {
119662306a36Sopenharmony_ci			for (q = RAVB_NC; q >= RAVB_BE; q--) {
119762306a36Sopenharmony_ci				if (ravb_queue_interrupt(ndev, q))
119862306a36Sopenharmony_ci					result = IRQ_HANDLED;
119962306a36Sopenharmony_ci			}
120062306a36Sopenharmony_ci		} else {
120162306a36Sopenharmony_ci			if (ravb_queue_interrupt(ndev, RAVB_BE))
120262306a36Sopenharmony_ci				result = IRQ_HANDLED;
120362306a36Sopenharmony_ci		}
120462306a36Sopenharmony_ci	}
120562306a36Sopenharmony_ci
120662306a36Sopenharmony_ci	/* E-MAC status summary */
120762306a36Sopenharmony_ci	if (iss & ISS_MS) {
120862306a36Sopenharmony_ci		ravb_emac_interrupt_unlocked(ndev);
120962306a36Sopenharmony_ci		result = IRQ_HANDLED;
121062306a36Sopenharmony_ci	}
121162306a36Sopenharmony_ci
121262306a36Sopenharmony_ci	/* Error status summary */
121362306a36Sopenharmony_ci	if (iss & ISS_ES) {
121462306a36Sopenharmony_ci		ravb_error_interrupt(ndev);
121562306a36Sopenharmony_ci		result = IRQ_HANDLED;
121662306a36Sopenharmony_ci	}
121762306a36Sopenharmony_ci
121862306a36Sopenharmony_ci	/* gPTP interrupt status summary */
121962306a36Sopenharmony_ci	if (iss & ISS_CGIS) {
122062306a36Sopenharmony_ci		ravb_ptp_interrupt(ndev);
122162306a36Sopenharmony_ci		result = IRQ_HANDLED;
122262306a36Sopenharmony_ci	}
122362306a36Sopenharmony_ci
122462306a36Sopenharmony_ci	spin_unlock(&priv->lock);
122562306a36Sopenharmony_ci	return result;
122662306a36Sopenharmony_ci}
122762306a36Sopenharmony_ci
122862306a36Sopenharmony_ci/* Timestamp/Error/gPTP interrupt handler */
122962306a36Sopenharmony_cistatic irqreturn_t ravb_multi_interrupt(int irq, void *dev_id)
123062306a36Sopenharmony_ci{
123162306a36Sopenharmony_ci	struct net_device *ndev = dev_id;
123262306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
123362306a36Sopenharmony_ci	irqreturn_t result = IRQ_NONE;
123462306a36Sopenharmony_ci	u32 iss;
123562306a36Sopenharmony_ci
123662306a36Sopenharmony_ci	spin_lock(&priv->lock);
123762306a36Sopenharmony_ci	/* Get interrupt status */
123862306a36Sopenharmony_ci	iss = ravb_read(ndev, ISS);
123962306a36Sopenharmony_ci
124062306a36Sopenharmony_ci	/* Timestamp updated */
124162306a36Sopenharmony_ci	if ((iss & ISS_TFUS) && ravb_timestamp_interrupt(ndev))
124262306a36Sopenharmony_ci		result = IRQ_HANDLED;
124362306a36Sopenharmony_ci
124462306a36Sopenharmony_ci	/* Error status summary */
124562306a36Sopenharmony_ci	if (iss & ISS_ES) {
124662306a36Sopenharmony_ci		ravb_error_interrupt(ndev);
124762306a36Sopenharmony_ci		result = IRQ_HANDLED;
124862306a36Sopenharmony_ci	}
124962306a36Sopenharmony_ci
125062306a36Sopenharmony_ci	/* gPTP interrupt status summary */
125162306a36Sopenharmony_ci	if (iss & ISS_CGIS) {
125262306a36Sopenharmony_ci		ravb_ptp_interrupt(ndev);
125362306a36Sopenharmony_ci		result = IRQ_HANDLED;
125462306a36Sopenharmony_ci	}
125562306a36Sopenharmony_ci
125662306a36Sopenharmony_ci	spin_unlock(&priv->lock);
125762306a36Sopenharmony_ci	return result;
125862306a36Sopenharmony_ci}
125962306a36Sopenharmony_ci
126062306a36Sopenharmony_cistatic irqreturn_t ravb_dma_interrupt(int irq, void *dev_id, int q)
126162306a36Sopenharmony_ci{
126262306a36Sopenharmony_ci	struct net_device *ndev = dev_id;
126362306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
126462306a36Sopenharmony_ci	irqreturn_t result = IRQ_NONE;
126562306a36Sopenharmony_ci
126662306a36Sopenharmony_ci	spin_lock(&priv->lock);
126762306a36Sopenharmony_ci
126862306a36Sopenharmony_ci	/* Network control/Best effort queue RX/TX */
126962306a36Sopenharmony_ci	if (ravb_queue_interrupt(ndev, q))
127062306a36Sopenharmony_ci		result = IRQ_HANDLED;
127162306a36Sopenharmony_ci
127262306a36Sopenharmony_ci	spin_unlock(&priv->lock);
127362306a36Sopenharmony_ci	return result;
127462306a36Sopenharmony_ci}
127562306a36Sopenharmony_ci
127662306a36Sopenharmony_cistatic irqreturn_t ravb_be_interrupt(int irq, void *dev_id)
127762306a36Sopenharmony_ci{
127862306a36Sopenharmony_ci	return ravb_dma_interrupt(irq, dev_id, RAVB_BE);
127962306a36Sopenharmony_ci}
128062306a36Sopenharmony_ci
128162306a36Sopenharmony_cistatic irqreturn_t ravb_nc_interrupt(int irq, void *dev_id)
128262306a36Sopenharmony_ci{
128362306a36Sopenharmony_ci	return ravb_dma_interrupt(irq, dev_id, RAVB_NC);
128462306a36Sopenharmony_ci}
128562306a36Sopenharmony_ci
128662306a36Sopenharmony_cistatic int ravb_poll(struct napi_struct *napi, int budget)
128762306a36Sopenharmony_ci{
128862306a36Sopenharmony_ci	struct net_device *ndev = napi->dev;
128962306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
129062306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
129162306a36Sopenharmony_ci	bool gptp = info->gptp || info->ccc_gac;
129262306a36Sopenharmony_ci	struct ravb_rx_desc *desc;
129362306a36Sopenharmony_ci	unsigned long flags;
129462306a36Sopenharmony_ci	int q = napi - priv->napi;
129562306a36Sopenharmony_ci	int mask = BIT(q);
129662306a36Sopenharmony_ci	int quota = budget;
129762306a36Sopenharmony_ci	unsigned int entry;
129862306a36Sopenharmony_ci
129962306a36Sopenharmony_ci	if (!gptp) {
130062306a36Sopenharmony_ci		entry = priv->cur_rx[q] % priv->num_rx_ring[q];
130162306a36Sopenharmony_ci		desc = &priv->gbeth_rx_ring[entry];
130262306a36Sopenharmony_ci	}
130362306a36Sopenharmony_ci	/* Processing RX Descriptor Ring */
130462306a36Sopenharmony_ci	/* Clear RX interrupt */
130562306a36Sopenharmony_ci	ravb_write(ndev, ~(mask | RIS0_RESERVED), RIS0);
130662306a36Sopenharmony_ci	if (gptp || desc->die_dt != DT_FEMPTY) {
130762306a36Sopenharmony_ci		if (ravb_rx(ndev, &quota, q))
130862306a36Sopenharmony_ci			goto out;
130962306a36Sopenharmony_ci	}
131062306a36Sopenharmony_ci
131162306a36Sopenharmony_ci	/* Processing TX Descriptor Ring */
131262306a36Sopenharmony_ci	spin_lock_irqsave(&priv->lock, flags);
131362306a36Sopenharmony_ci	/* Clear TX interrupt */
131462306a36Sopenharmony_ci	ravb_write(ndev, ~(mask | TIS_RESERVED), TIS);
131562306a36Sopenharmony_ci	ravb_tx_free(ndev, q, true);
131662306a36Sopenharmony_ci	netif_wake_subqueue(ndev, q);
131762306a36Sopenharmony_ci	spin_unlock_irqrestore(&priv->lock, flags);
131862306a36Sopenharmony_ci
131962306a36Sopenharmony_ci	napi_complete(napi);
132062306a36Sopenharmony_ci
132162306a36Sopenharmony_ci	/* Re-enable RX/TX interrupts */
132262306a36Sopenharmony_ci	spin_lock_irqsave(&priv->lock, flags);
132362306a36Sopenharmony_ci	if (!info->irq_en_dis) {
132462306a36Sopenharmony_ci		ravb_modify(ndev, RIC0, mask, mask);
132562306a36Sopenharmony_ci		ravb_modify(ndev, TIC,  mask, mask);
132662306a36Sopenharmony_ci	} else {
132762306a36Sopenharmony_ci		ravb_write(ndev, mask, RIE0);
132862306a36Sopenharmony_ci		ravb_write(ndev, mask, TIE);
132962306a36Sopenharmony_ci	}
133062306a36Sopenharmony_ci	spin_unlock_irqrestore(&priv->lock, flags);
133162306a36Sopenharmony_ci
133262306a36Sopenharmony_ci	/* Receive error message handling */
133362306a36Sopenharmony_ci	priv->rx_over_errors =  priv->stats[RAVB_BE].rx_over_errors;
133462306a36Sopenharmony_ci	if (info->nc_queues)
133562306a36Sopenharmony_ci		priv->rx_over_errors += priv->stats[RAVB_NC].rx_over_errors;
133662306a36Sopenharmony_ci	if (priv->rx_over_errors != ndev->stats.rx_over_errors)
133762306a36Sopenharmony_ci		ndev->stats.rx_over_errors = priv->rx_over_errors;
133862306a36Sopenharmony_ci	if (priv->rx_fifo_errors != ndev->stats.rx_fifo_errors)
133962306a36Sopenharmony_ci		ndev->stats.rx_fifo_errors = priv->rx_fifo_errors;
134062306a36Sopenharmony_ciout:
134162306a36Sopenharmony_ci	return budget - quota;
134262306a36Sopenharmony_ci}
134362306a36Sopenharmony_ci
134462306a36Sopenharmony_cistatic void ravb_set_duplex_gbeth(struct net_device *ndev)
134562306a36Sopenharmony_ci{
134662306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
134762306a36Sopenharmony_ci
134862306a36Sopenharmony_ci	ravb_modify(ndev, ECMR, ECMR_DM, priv->duplex > 0 ? ECMR_DM : 0);
134962306a36Sopenharmony_ci}
135062306a36Sopenharmony_ci
135162306a36Sopenharmony_ci/* PHY state control function */
135262306a36Sopenharmony_cistatic void ravb_adjust_link(struct net_device *ndev)
135362306a36Sopenharmony_ci{
135462306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
135562306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
135662306a36Sopenharmony_ci	struct phy_device *phydev = ndev->phydev;
135762306a36Sopenharmony_ci	bool new_state = false;
135862306a36Sopenharmony_ci	unsigned long flags;
135962306a36Sopenharmony_ci
136062306a36Sopenharmony_ci	spin_lock_irqsave(&priv->lock, flags);
136162306a36Sopenharmony_ci
136262306a36Sopenharmony_ci	/* Disable TX and RX right over here, if E-MAC change is ignored */
136362306a36Sopenharmony_ci	if (priv->no_avb_link)
136462306a36Sopenharmony_ci		ravb_rcv_snd_disable(ndev);
136562306a36Sopenharmony_ci
136662306a36Sopenharmony_ci	if (phydev->link) {
136762306a36Sopenharmony_ci		if (info->half_duplex && phydev->duplex != priv->duplex) {
136862306a36Sopenharmony_ci			new_state = true;
136962306a36Sopenharmony_ci			priv->duplex = phydev->duplex;
137062306a36Sopenharmony_ci			ravb_set_duplex_gbeth(ndev);
137162306a36Sopenharmony_ci		}
137262306a36Sopenharmony_ci
137362306a36Sopenharmony_ci		if (phydev->speed != priv->speed) {
137462306a36Sopenharmony_ci			new_state = true;
137562306a36Sopenharmony_ci			priv->speed = phydev->speed;
137662306a36Sopenharmony_ci			info->set_rate(ndev);
137762306a36Sopenharmony_ci		}
137862306a36Sopenharmony_ci		if (!priv->link) {
137962306a36Sopenharmony_ci			ravb_modify(ndev, ECMR, ECMR_TXF, 0);
138062306a36Sopenharmony_ci			new_state = true;
138162306a36Sopenharmony_ci			priv->link = phydev->link;
138262306a36Sopenharmony_ci		}
138362306a36Sopenharmony_ci	} else if (priv->link) {
138462306a36Sopenharmony_ci		new_state = true;
138562306a36Sopenharmony_ci		priv->link = 0;
138662306a36Sopenharmony_ci		priv->speed = 0;
138762306a36Sopenharmony_ci		if (info->half_duplex)
138862306a36Sopenharmony_ci			priv->duplex = -1;
138962306a36Sopenharmony_ci	}
139062306a36Sopenharmony_ci
139162306a36Sopenharmony_ci	/* Enable TX and RX right over here, if E-MAC change is ignored */
139262306a36Sopenharmony_ci	if (priv->no_avb_link && phydev->link)
139362306a36Sopenharmony_ci		ravb_rcv_snd_enable(ndev);
139462306a36Sopenharmony_ci
139562306a36Sopenharmony_ci	spin_unlock_irqrestore(&priv->lock, flags);
139662306a36Sopenharmony_ci
139762306a36Sopenharmony_ci	if (new_state && netif_msg_link(priv))
139862306a36Sopenharmony_ci		phy_print_status(phydev);
139962306a36Sopenharmony_ci}
140062306a36Sopenharmony_ci
140162306a36Sopenharmony_ci/* PHY init function */
140262306a36Sopenharmony_cistatic int ravb_phy_init(struct net_device *ndev)
140362306a36Sopenharmony_ci{
140462306a36Sopenharmony_ci	struct device_node *np = ndev->dev.parent->of_node;
140562306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
140662306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
140762306a36Sopenharmony_ci	struct phy_device *phydev;
140862306a36Sopenharmony_ci	struct device_node *pn;
140962306a36Sopenharmony_ci	phy_interface_t iface;
141062306a36Sopenharmony_ci	int err;
141162306a36Sopenharmony_ci
141262306a36Sopenharmony_ci	priv->link = 0;
141362306a36Sopenharmony_ci	priv->speed = 0;
141462306a36Sopenharmony_ci	priv->duplex = -1;
141562306a36Sopenharmony_ci
141662306a36Sopenharmony_ci	/* Try connecting to PHY */
141762306a36Sopenharmony_ci	pn = of_parse_phandle(np, "phy-handle", 0);
141862306a36Sopenharmony_ci	if (!pn) {
141962306a36Sopenharmony_ci		/* In the case of a fixed PHY, the DT node associated
142062306a36Sopenharmony_ci		 * to the PHY is the Ethernet MAC DT node.
142162306a36Sopenharmony_ci		 */
142262306a36Sopenharmony_ci		if (of_phy_is_fixed_link(np)) {
142362306a36Sopenharmony_ci			err = of_phy_register_fixed_link(np);
142462306a36Sopenharmony_ci			if (err)
142562306a36Sopenharmony_ci				return err;
142662306a36Sopenharmony_ci		}
142762306a36Sopenharmony_ci		pn = of_node_get(np);
142862306a36Sopenharmony_ci	}
142962306a36Sopenharmony_ci
143062306a36Sopenharmony_ci	iface = priv->rgmii_override ? PHY_INTERFACE_MODE_RGMII
143162306a36Sopenharmony_ci				     : priv->phy_interface;
143262306a36Sopenharmony_ci	phydev = of_phy_connect(ndev, pn, ravb_adjust_link, 0, iface);
143362306a36Sopenharmony_ci	of_node_put(pn);
143462306a36Sopenharmony_ci	if (!phydev) {
143562306a36Sopenharmony_ci		netdev_err(ndev, "failed to connect PHY\n");
143662306a36Sopenharmony_ci		err = -ENOENT;
143762306a36Sopenharmony_ci		goto err_deregister_fixed_link;
143862306a36Sopenharmony_ci	}
143962306a36Sopenharmony_ci
144062306a36Sopenharmony_ci	if (!info->half_duplex) {
144162306a36Sopenharmony_ci		/* 10BASE, Pause and Asym Pause is not supported */
144262306a36Sopenharmony_ci		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT);
144362306a36Sopenharmony_ci		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_10baseT_Full_BIT);
144462306a36Sopenharmony_ci		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_Pause_BIT);
144562306a36Sopenharmony_ci		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_Asym_Pause_BIT);
144662306a36Sopenharmony_ci
144762306a36Sopenharmony_ci		/* Half Duplex is not supported */
144862306a36Sopenharmony_ci		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
144962306a36Sopenharmony_ci		phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT);
145062306a36Sopenharmony_ci	}
145162306a36Sopenharmony_ci
145262306a36Sopenharmony_ci	phy_attached_info(phydev);
145362306a36Sopenharmony_ci
145462306a36Sopenharmony_ci	return 0;
145562306a36Sopenharmony_ci
145662306a36Sopenharmony_cierr_deregister_fixed_link:
145762306a36Sopenharmony_ci	if (of_phy_is_fixed_link(np))
145862306a36Sopenharmony_ci		of_phy_deregister_fixed_link(np);
145962306a36Sopenharmony_ci
146062306a36Sopenharmony_ci	return err;
146162306a36Sopenharmony_ci}
146262306a36Sopenharmony_ci
146362306a36Sopenharmony_ci/* PHY control start function */
146462306a36Sopenharmony_cistatic int ravb_phy_start(struct net_device *ndev)
146562306a36Sopenharmony_ci{
146662306a36Sopenharmony_ci	int error;
146762306a36Sopenharmony_ci
146862306a36Sopenharmony_ci	error = ravb_phy_init(ndev);
146962306a36Sopenharmony_ci	if (error)
147062306a36Sopenharmony_ci		return error;
147162306a36Sopenharmony_ci
147262306a36Sopenharmony_ci	phy_start(ndev->phydev);
147362306a36Sopenharmony_ci
147462306a36Sopenharmony_ci	return 0;
147562306a36Sopenharmony_ci}
147662306a36Sopenharmony_ci
147762306a36Sopenharmony_cistatic u32 ravb_get_msglevel(struct net_device *ndev)
147862306a36Sopenharmony_ci{
147962306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
148062306a36Sopenharmony_ci
148162306a36Sopenharmony_ci	return priv->msg_enable;
148262306a36Sopenharmony_ci}
148362306a36Sopenharmony_ci
148462306a36Sopenharmony_cistatic void ravb_set_msglevel(struct net_device *ndev, u32 value)
148562306a36Sopenharmony_ci{
148662306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
148762306a36Sopenharmony_ci
148862306a36Sopenharmony_ci	priv->msg_enable = value;
148962306a36Sopenharmony_ci}
149062306a36Sopenharmony_ci
149162306a36Sopenharmony_cistatic const char ravb_gstrings_stats_gbeth[][ETH_GSTRING_LEN] = {
149262306a36Sopenharmony_ci	"rx_queue_0_current",
149362306a36Sopenharmony_ci	"tx_queue_0_current",
149462306a36Sopenharmony_ci	"rx_queue_0_dirty",
149562306a36Sopenharmony_ci	"tx_queue_0_dirty",
149662306a36Sopenharmony_ci	"rx_queue_0_packets",
149762306a36Sopenharmony_ci	"tx_queue_0_packets",
149862306a36Sopenharmony_ci	"rx_queue_0_bytes",
149962306a36Sopenharmony_ci	"tx_queue_0_bytes",
150062306a36Sopenharmony_ci	"rx_queue_0_mcast_packets",
150162306a36Sopenharmony_ci	"rx_queue_0_errors",
150262306a36Sopenharmony_ci	"rx_queue_0_crc_errors",
150362306a36Sopenharmony_ci	"rx_queue_0_frame_errors",
150462306a36Sopenharmony_ci	"rx_queue_0_length_errors",
150562306a36Sopenharmony_ci	"rx_queue_0_csum_offload_errors",
150662306a36Sopenharmony_ci	"rx_queue_0_over_errors",
150762306a36Sopenharmony_ci};
150862306a36Sopenharmony_ci
150962306a36Sopenharmony_cistatic const char ravb_gstrings_stats[][ETH_GSTRING_LEN] = {
151062306a36Sopenharmony_ci	"rx_queue_0_current",
151162306a36Sopenharmony_ci	"tx_queue_0_current",
151262306a36Sopenharmony_ci	"rx_queue_0_dirty",
151362306a36Sopenharmony_ci	"tx_queue_0_dirty",
151462306a36Sopenharmony_ci	"rx_queue_0_packets",
151562306a36Sopenharmony_ci	"tx_queue_0_packets",
151662306a36Sopenharmony_ci	"rx_queue_0_bytes",
151762306a36Sopenharmony_ci	"tx_queue_0_bytes",
151862306a36Sopenharmony_ci	"rx_queue_0_mcast_packets",
151962306a36Sopenharmony_ci	"rx_queue_0_errors",
152062306a36Sopenharmony_ci	"rx_queue_0_crc_errors",
152162306a36Sopenharmony_ci	"rx_queue_0_frame_errors",
152262306a36Sopenharmony_ci	"rx_queue_0_length_errors",
152362306a36Sopenharmony_ci	"rx_queue_0_missed_errors",
152462306a36Sopenharmony_ci	"rx_queue_0_over_errors",
152562306a36Sopenharmony_ci
152662306a36Sopenharmony_ci	"rx_queue_1_current",
152762306a36Sopenharmony_ci	"tx_queue_1_current",
152862306a36Sopenharmony_ci	"rx_queue_1_dirty",
152962306a36Sopenharmony_ci	"tx_queue_1_dirty",
153062306a36Sopenharmony_ci	"rx_queue_1_packets",
153162306a36Sopenharmony_ci	"tx_queue_1_packets",
153262306a36Sopenharmony_ci	"rx_queue_1_bytes",
153362306a36Sopenharmony_ci	"tx_queue_1_bytes",
153462306a36Sopenharmony_ci	"rx_queue_1_mcast_packets",
153562306a36Sopenharmony_ci	"rx_queue_1_errors",
153662306a36Sopenharmony_ci	"rx_queue_1_crc_errors",
153762306a36Sopenharmony_ci	"rx_queue_1_frame_errors",
153862306a36Sopenharmony_ci	"rx_queue_1_length_errors",
153962306a36Sopenharmony_ci	"rx_queue_1_missed_errors",
154062306a36Sopenharmony_ci	"rx_queue_1_over_errors",
154162306a36Sopenharmony_ci};
154262306a36Sopenharmony_ci
154362306a36Sopenharmony_cistatic int ravb_get_sset_count(struct net_device *netdev, int sset)
154462306a36Sopenharmony_ci{
154562306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(netdev);
154662306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
154762306a36Sopenharmony_ci
154862306a36Sopenharmony_ci	switch (sset) {
154962306a36Sopenharmony_ci	case ETH_SS_STATS:
155062306a36Sopenharmony_ci		return info->stats_len;
155162306a36Sopenharmony_ci	default:
155262306a36Sopenharmony_ci		return -EOPNOTSUPP;
155362306a36Sopenharmony_ci	}
155462306a36Sopenharmony_ci}
155562306a36Sopenharmony_ci
155662306a36Sopenharmony_cistatic void ravb_get_ethtool_stats(struct net_device *ndev,
155762306a36Sopenharmony_ci				   struct ethtool_stats *estats, u64 *data)
155862306a36Sopenharmony_ci{
155962306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
156062306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
156162306a36Sopenharmony_ci	int num_rx_q;
156262306a36Sopenharmony_ci	int i = 0;
156362306a36Sopenharmony_ci	int q;
156462306a36Sopenharmony_ci
156562306a36Sopenharmony_ci	num_rx_q = info->nc_queues ? NUM_RX_QUEUE : 1;
156662306a36Sopenharmony_ci	/* Device-specific stats */
156762306a36Sopenharmony_ci	for (q = RAVB_BE; q < num_rx_q; q++) {
156862306a36Sopenharmony_ci		struct net_device_stats *stats = &priv->stats[q];
156962306a36Sopenharmony_ci
157062306a36Sopenharmony_ci		data[i++] = priv->cur_rx[q];
157162306a36Sopenharmony_ci		data[i++] = priv->cur_tx[q];
157262306a36Sopenharmony_ci		data[i++] = priv->dirty_rx[q];
157362306a36Sopenharmony_ci		data[i++] = priv->dirty_tx[q];
157462306a36Sopenharmony_ci		data[i++] = stats->rx_packets;
157562306a36Sopenharmony_ci		data[i++] = stats->tx_packets;
157662306a36Sopenharmony_ci		data[i++] = stats->rx_bytes;
157762306a36Sopenharmony_ci		data[i++] = stats->tx_bytes;
157862306a36Sopenharmony_ci		data[i++] = stats->multicast;
157962306a36Sopenharmony_ci		data[i++] = stats->rx_errors;
158062306a36Sopenharmony_ci		data[i++] = stats->rx_crc_errors;
158162306a36Sopenharmony_ci		data[i++] = stats->rx_frame_errors;
158262306a36Sopenharmony_ci		data[i++] = stats->rx_length_errors;
158362306a36Sopenharmony_ci		data[i++] = stats->rx_missed_errors;
158462306a36Sopenharmony_ci		data[i++] = stats->rx_over_errors;
158562306a36Sopenharmony_ci	}
158662306a36Sopenharmony_ci}
158762306a36Sopenharmony_ci
158862306a36Sopenharmony_cistatic void ravb_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
158962306a36Sopenharmony_ci{
159062306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
159162306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
159262306a36Sopenharmony_ci
159362306a36Sopenharmony_ci	switch (stringset) {
159462306a36Sopenharmony_ci	case ETH_SS_STATS:
159562306a36Sopenharmony_ci		memcpy(data, info->gstrings_stats, info->gstrings_size);
159662306a36Sopenharmony_ci		break;
159762306a36Sopenharmony_ci	}
159862306a36Sopenharmony_ci}
159962306a36Sopenharmony_ci
160062306a36Sopenharmony_cistatic void ravb_get_ringparam(struct net_device *ndev,
160162306a36Sopenharmony_ci			       struct ethtool_ringparam *ring,
160262306a36Sopenharmony_ci			       struct kernel_ethtool_ringparam *kernel_ring,
160362306a36Sopenharmony_ci			       struct netlink_ext_ack *extack)
160462306a36Sopenharmony_ci{
160562306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
160662306a36Sopenharmony_ci
160762306a36Sopenharmony_ci	ring->rx_max_pending = BE_RX_RING_MAX;
160862306a36Sopenharmony_ci	ring->tx_max_pending = BE_TX_RING_MAX;
160962306a36Sopenharmony_ci	ring->rx_pending = priv->num_rx_ring[RAVB_BE];
161062306a36Sopenharmony_ci	ring->tx_pending = priv->num_tx_ring[RAVB_BE];
161162306a36Sopenharmony_ci}
161262306a36Sopenharmony_ci
161362306a36Sopenharmony_cistatic int ravb_set_ringparam(struct net_device *ndev,
161462306a36Sopenharmony_ci			      struct ethtool_ringparam *ring,
161562306a36Sopenharmony_ci			      struct kernel_ethtool_ringparam *kernel_ring,
161662306a36Sopenharmony_ci			      struct netlink_ext_ack *extack)
161762306a36Sopenharmony_ci{
161862306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
161962306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
162062306a36Sopenharmony_ci	int error;
162162306a36Sopenharmony_ci
162262306a36Sopenharmony_ci	if (ring->tx_pending > BE_TX_RING_MAX ||
162362306a36Sopenharmony_ci	    ring->rx_pending > BE_RX_RING_MAX ||
162462306a36Sopenharmony_ci	    ring->tx_pending < BE_TX_RING_MIN ||
162562306a36Sopenharmony_ci	    ring->rx_pending < BE_RX_RING_MIN)
162662306a36Sopenharmony_ci		return -EINVAL;
162762306a36Sopenharmony_ci	if (ring->rx_mini_pending || ring->rx_jumbo_pending)
162862306a36Sopenharmony_ci		return -EINVAL;
162962306a36Sopenharmony_ci
163062306a36Sopenharmony_ci	if (netif_running(ndev)) {
163162306a36Sopenharmony_ci		netif_device_detach(ndev);
163262306a36Sopenharmony_ci		/* Stop PTP Clock driver */
163362306a36Sopenharmony_ci		if (info->gptp)
163462306a36Sopenharmony_ci			ravb_ptp_stop(ndev);
163562306a36Sopenharmony_ci		/* Wait for DMA stopping */
163662306a36Sopenharmony_ci		error = ravb_stop_dma(ndev);
163762306a36Sopenharmony_ci		if (error) {
163862306a36Sopenharmony_ci			netdev_err(ndev,
163962306a36Sopenharmony_ci				   "cannot set ringparam! Any AVB processes are still running?\n");
164062306a36Sopenharmony_ci			return error;
164162306a36Sopenharmony_ci		}
164262306a36Sopenharmony_ci		synchronize_irq(ndev->irq);
164362306a36Sopenharmony_ci
164462306a36Sopenharmony_ci		/* Free all the skb's in the RX queue and the DMA buffers. */
164562306a36Sopenharmony_ci		ravb_ring_free(ndev, RAVB_BE);
164662306a36Sopenharmony_ci		if (info->nc_queues)
164762306a36Sopenharmony_ci			ravb_ring_free(ndev, RAVB_NC);
164862306a36Sopenharmony_ci	}
164962306a36Sopenharmony_ci
165062306a36Sopenharmony_ci	/* Set new parameters */
165162306a36Sopenharmony_ci	priv->num_rx_ring[RAVB_BE] = ring->rx_pending;
165262306a36Sopenharmony_ci	priv->num_tx_ring[RAVB_BE] = ring->tx_pending;
165362306a36Sopenharmony_ci
165462306a36Sopenharmony_ci	if (netif_running(ndev)) {
165562306a36Sopenharmony_ci		error = ravb_dmac_init(ndev);
165662306a36Sopenharmony_ci		if (error) {
165762306a36Sopenharmony_ci			netdev_err(ndev,
165862306a36Sopenharmony_ci				   "%s: ravb_dmac_init() failed, error %d\n",
165962306a36Sopenharmony_ci				   __func__, error);
166062306a36Sopenharmony_ci			return error;
166162306a36Sopenharmony_ci		}
166262306a36Sopenharmony_ci
166362306a36Sopenharmony_ci		ravb_emac_init(ndev);
166462306a36Sopenharmony_ci
166562306a36Sopenharmony_ci		/* Initialise PTP Clock driver */
166662306a36Sopenharmony_ci		if (info->gptp)
166762306a36Sopenharmony_ci			ravb_ptp_init(ndev, priv->pdev);
166862306a36Sopenharmony_ci
166962306a36Sopenharmony_ci		netif_device_attach(ndev);
167062306a36Sopenharmony_ci	}
167162306a36Sopenharmony_ci
167262306a36Sopenharmony_ci	return 0;
167362306a36Sopenharmony_ci}
167462306a36Sopenharmony_ci
167562306a36Sopenharmony_cistatic int ravb_get_ts_info(struct net_device *ndev,
167662306a36Sopenharmony_ci			    struct ethtool_ts_info *info)
167762306a36Sopenharmony_ci{
167862306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
167962306a36Sopenharmony_ci	const struct ravb_hw_info *hw_info = priv->info;
168062306a36Sopenharmony_ci
168162306a36Sopenharmony_ci	info->so_timestamping =
168262306a36Sopenharmony_ci		SOF_TIMESTAMPING_TX_SOFTWARE |
168362306a36Sopenharmony_ci		SOF_TIMESTAMPING_RX_SOFTWARE |
168462306a36Sopenharmony_ci		SOF_TIMESTAMPING_SOFTWARE |
168562306a36Sopenharmony_ci		SOF_TIMESTAMPING_TX_HARDWARE |
168662306a36Sopenharmony_ci		SOF_TIMESTAMPING_RX_HARDWARE |
168762306a36Sopenharmony_ci		SOF_TIMESTAMPING_RAW_HARDWARE;
168862306a36Sopenharmony_ci	info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
168962306a36Sopenharmony_ci	info->rx_filters =
169062306a36Sopenharmony_ci		(1 << HWTSTAMP_FILTER_NONE) |
169162306a36Sopenharmony_ci		(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
169262306a36Sopenharmony_ci		(1 << HWTSTAMP_FILTER_ALL);
169362306a36Sopenharmony_ci	if (hw_info->gptp || hw_info->ccc_gac)
169462306a36Sopenharmony_ci		info->phc_index = ptp_clock_index(priv->ptp.clock);
169562306a36Sopenharmony_ci
169662306a36Sopenharmony_ci	return 0;
169762306a36Sopenharmony_ci}
169862306a36Sopenharmony_ci
169962306a36Sopenharmony_cistatic void ravb_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
170062306a36Sopenharmony_ci{
170162306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
170262306a36Sopenharmony_ci
170362306a36Sopenharmony_ci	wol->supported = WAKE_MAGIC;
170462306a36Sopenharmony_ci	wol->wolopts = priv->wol_enabled ? WAKE_MAGIC : 0;
170562306a36Sopenharmony_ci}
170662306a36Sopenharmony_ci
170762306a36Sopenharmony_cistatic int ravb_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
170862306a36Sopenharmony_ci{
170962306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
171062306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
171162306a36Sopenharmony_ci
171262306a36Sopenharmony_ci	if (!info->magic_pkt || (wol->wolopts & ~WAKE_MAGIC))
171362306a36Sopenharmony_ci		return -EOPNOTSUPP;
171462306a36Sopenharmony_ci
171562306a36Sopenharmony_ci	priv->wol_enabled = !!(wol->wolopts & WAKE_MAGIC);
171662306a36Sopenharmony_ci
171762306a36Sopenharmony_ci	device_set_wakeup_enable(&priv->pdev->dev, priv->wol_enabled);
171862306a36Sopenharmony_ci
171962306a36Sopenharmony_ci	return 0;
172062306a36Sopenharmony_ci}
172162306a36Sopenharmony_ci
172262306a36Sopenharmony_cistatic const struct ethtool_ops ravb_ethtool_ops = {
172362306a36Sopenharmony_ci	.nway_reset		= phy_ethtool_nway_reset,
172462306a36Sopenharmony_ci	.get_msglevel		= ravb_get_msglevel,
172562306a36Sopenharmony_ci	.set_msglevel		= ravb_set_msglevel,
172662306a36Sopenharmony_ci	.get_link		= ethtool_op_get_link,
172762306a36Sopenharmony_ci	.get_strings		= ravb_get_strings,
172862306a36Sopenharmony_ci	.get_ethtool_stats	= ravb_get_ethtool_stats,
172962306a36Sopenharmony_ci	.get_sset_count		= ravb_get_sset_count,
173062306a36Sopenharmony_ci	.get_ringparam		= ravb_get_ringparam,
173162306a36Sopenharmony_ci	.set_ringparam		= ravb_set_ringparam,
173262306a36Sopenharmony_ci	.get_ts_info		= ravb_get_ts_info,
173362306a36Sopenharmony_ci	.get_link_ksettings	= phy_ethtool_get_link_ksettings,
173462306a36Sopenharmony_ci	.set_link_ksettings	= phy_ethtool_set_link_ksettings,
173562306a36Sopenharmony_ci	.get_wol		= ravb_get_wol,
173662306a36Sopenharmony_ci	.set_wol		= ravb_set_wol,
173762306a36Sopenharmony_ci};
173862306a36Sopenharmony_ci
173962306a36Sopenharmony_cistatic inline int ravb_hook_irq(unsigned int irq, irq_handler_t handler,
174062306a36Sopenharmony_ci				struct net_device *ndev, struct device *dev,
174162306a36Sopenharmony_ci				const char *ch)
174262306a36Sopenharmony_ci{
174362306a36Sopenharmony_ci	char *name;
174462306a36Sopenharmony_ci	int error;
174562306a36Sopenharmony_ci
174662306a36Sopenharmony_ci	name = devm_kasprintf(dev, GFP_KERNEL, "%s:%s", ndev->name, ch);
174762306a36Sopenharmony_ci	if (!name)
174862306a36Sopenharmony_ci		return -ENOMEM;
174962306a36Sopenharmony_ci	error = request_irq(irq, handler, 0, name, ndev);
175062306a36Sopenharmony_ci	if (error)
175162306a36Sopenharmony_ci		netdev_err(ndev, "cannot request IRQ %s\n", name);
175262306a36Sopenharmony_ci
175362306a36Sopenharmony_ci	return error;
175462306a36Sopenharmony_ci}
175562306a36Sopenharmony_ci
175662306a36Sopenharmony_ci/* Network device open function for Ethernet AVB */
175762306a36Sopenharmony_cistatic int ravb_open(struct net_device *ndev)
175862306a36Sopenharmony_ci{
175962306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
176062306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
176162306a36Sopenharmony_ci	struct platform_device *pdev = priv->pdev;
176262306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
176362306a36Sopenharmony_ci	int error;
176462306a36Sopenharmony_ci
176562306a36Sopenharmony_ci	napi_enable(&priv->napi[RAVB_BE]);
176662306a36Sopenharmony_ci	if (info->nc_queues)
176762306a36Sopenharmony_ci		napi_enable(&priv->napi[RAVB_NC]);
176862306a36Sopenharmony_ci
176962306a36Sopenharmony_ci	if (!info->multi_irqs) {
177062306a36Sopenharmony_ci		error = request_irq(ndev->irq, ravb_interrupt, IRQF_SHARED,
177162306a36Sopenharmony_ci				    ndev->name, ndev);
177262306a36Sopenharmony_ci		if (error) {
177362306a36Sopenharmony_ci			netdev_err(ndev, "cannot request IRQ\n");
177462306a36Sopenharmony_ci			goto out_napi_off;
177562306a36Sopenharmony_ci		}
177662306a36Sopenharmony_ci	} else {
177762306a36Sopenharmony_ci		error = ravb_hook_irq(ndev->irq, ravb_multi_interrupt, ndev,
177862306a36Sopenharmony_ci				      dev, "ch22:multi");
177962306a36Sopenharmony_ci		if (error)
178062306a36Sopenharmony_ci			goto out_napi_off;
178162306a36Sopenharmony_ci		error = ravb_hook_irq(priv->emac_irq, ravb_emac_interrupt, ndev,
178262306a36Sopenharmony_ci				      dev, "ch24:emac");
178362306a36Sopenharmony_ci		if (error)
178462306a36Sopenharmony_ci			goto out_free_irq;
178562306a36Sopenharmony_ci		error = ravb_hook_irq(priv->rx_irqs[RAVB_BE], ravb_be_interrupt,
178662306a36Sopenharmony_ci				      ndev, dev, "ch0:rx_be");
178762306a36Sopenharmony_ci		if (error)
178862306a36Sopenharmony_ci			goto out_free_irq_emac;
178962306a36Sopenharmony_ci		error = ravb_hook_irq(priv->tx_irqs[RAVB_BE], ravb_be_interrupt,
179062306a36Sopenharmony_ci				      ndev, dev, "ch18:tx_be");
179162306a36Sopenharmony_ci		if (error)
179262306a36Sopenharmony_ci			goto out_free_irq_be_rx;
179362306a36Sopenharmony_ci		error = ravb_hook_irq(priv->rx_irqs[RAVB_NC], ravb_nc_interrupt,
179462306a36Sopenharmony_ci				      ndev, dev, "ch1:rx_nc");
179562306a36Sopenharmony_ci		if (error)
179662306a36Sopenharmony_ci			goto out_free_irq_be_tx;
179762306a36Sopenharmony_ci		error = ravb_hook_irq(priv->tx_irqs[RAVB_NC], ravb_nc_interrupt,
179862306a36Sopenharmony_ci				      ndev, dev, "ch19:tx_nc");
179962306a36Sopenharmony_ci		if (error)
180062306a36Sopenharmony_ci			goto out_free_irq_nc_rx;
180162306a36Sopenharmony_ci
180262306a36Sopenharmony_ci		if (info->err_mgmt_irqs) {
180362306a36Sopenharmony_ci			error = ravb_hook_irq(priv->erra_irq, ravb_multi_interrupt,
180462306a36Sopenharmony_ci					      ndev, dev, "err_a");
180562306a36Sopenharmony_ci			if (error)
180662306a36Sopenharmony_ci				goto out_free_irq_nc_tx;
180762306a36Sopenharmony_ci			error = ravb_hook_irq(priv->mgmta_irq, ravb_multi_interrupt,
180862306a36Sopenharmony_ci					      ndev, dev, "mgmt_a");
180962306a36Sopenharmony_ci			if (error)
181062306a36Sopenharmony_ci				goto out_free_irq_erra;
181162306a36Sopenharmony_ci		}
181262306a36Sopenharmony_ci	}
181362306a36Sopenharmony_ci
181462306a36Sopenharmony_ci	/* Device init */
181562306a36Sopenharmony_ci	error = ravb_dmac_init(ndev);
181662306a36Sopenharmony_ci	if (error)
181762306a36Sopenharmony_ci		goto out_free_irq_mgmta;
181862306a36Sopenharmony_ci	ravb_emac_init(ndev);
181962306a36Sopenharmony_ci
182062306a36Sopenharmony_ci	/* Initialise PTP Clock driver */
182162306a36Sopenharmony_ci	if (info->gptp)
182262306a36Sopenharmony_ci		ravb_ptp_init(ndev, priv->pdev);
182362306a36Sopenharmony_ci
182462306a36Sopenharmony_ci	/* PHY control start */
182562306a36Sopenharmony_ci	error = ravb_phy_start(ndev);
182662306a36Sopenharmony_ci	if (error)
182762306a36Sopenharmony_ci		goto out_ptp_stop;
182862306a36Sopenharmony_ci
182962306a36Sopenharmony_ci	netif_tx_start_all_queues(ndev);
183062306a36Sopenharmony_ci
183162306a36Sopenharmony_ci	return 0;
183262306a36Sopenharmony_ci
183362306a36Sopenharmony_ciout_ptp_stop:
183462306a36Sopenharmony_ci	/* Stop PTP Clock driver */
183562306a36Sopenharmony_ci	if (info->gptp)
183662306a36Sopenharmony_ci		ravb_ptp_stop(ndev);
183762306a36Sopenharmony_ci	ravb_stop_dma(ndev);
183862306a36Sopenharmony_ciout_free_irq_mgmta:
183962306a36Sopenharmony_ci	if (!info->multi_irqs)
184062306a36Sopenharmony_ci		goto out_free_irq;
184162306a36Sopenharmony_ci	if (info->err_mgmt_irqs)
184262306a36Sopenharmony_ci		free_irq(priv->mgmta_irq, ndev);
184362306a36Sopenharmony_ciout_free_irq_erra:
184462306a36Sopenharmony_ci	if (info->err_mgmt_irqs)
184562306a36Sopenharmony_ci		free_irq(priv->erra_irq, ndev);
184662306a36Sopenharmony_ciout_free_irq_nc_tx:
184762306a36Sopenharmony_ci	free_irq(priv->tx_irqs[RAVB_NC], ndev);
184862306a36Sopenharmony_ciout_free_irq_nc_rx:
184962306a36Sopenharmony_ci	free_irq(priv->rx_irqs[RAVB_NC], ndev);
185062306a36Sopenharmony_ciout_free_irq_be_tx:
185162306a36Sopenharmony_ci	free_irq(priv->tx_irqs[RAVB_BE], ndev);
185262306a36Sopenharmony_ciout_free_irq_be_rx:
185362306a36Sopenharmony_ci	free_irq(priv->rx_irqs[RAVB_BE], ndev);
185462306a36Sopenharmony_ciout_free_irq_emac:
185562306a36Sopenharmony_ci	free_irq(priv->emac_irq, ndev);
185662306a36Sopenharmony_ciout_free_irq:
185762306a36Sopenharmony_ci	free_irq(ndev->irq, ndev);
185862306a36Sopenharmony_ciout_napi_off:
185962306a36Sopenharmony_ci	if (info->nc_queues)
186062306a36Sopenharmony_ci		napi_disable(&priv->napi[RAVB_NC]);
186162306a36Sopenharmony_ci	napi_disable(&priv->napi[RAVB_BE]);
186262306a36Sopenharmony_ci	return error;
186362306a36Sopenharmony_ci}
186462306a36Sopenharmony_ci
186562306a36Sopenharmony_ci/* Timeout function for Ethernet AVB */
186662306a36Sopenharmony_cistatic void ravb_tx_timeout(struct net_device *ndev, unsigned int txqueue)
186762306a36Sopenharmony_ci{
186862306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
186962306a36Sopenharmony_ci
187062306a36Sopenharmony_ci	netif_err(priv, tx_err, ndev,
187162306a36Sopenharmony_ci		  "transmit timed out, status %08x, resetting...\n",
187262306a36Sopenharmony_ci		  ravb_read(ndev, ISS));
187362306a36Sopenharmony_ci
187462306a36Sopenharmony_ci	/* tx_errors count up */
187562306a36Sopenharmony_ci	ndev->stats.tx_errors++;
187662306a36Sopenharmony_ci
187762306a36Sopenharmony_ci	schedule_work(&priv->work);
187862306a36Sopenharmony_ci}
187962306a36Sopenharmony_ci
188062306a36Sopenharmony_cistatic void ravb_tx_timeout_work(struct work_struct *work)
188162306a36Sopenharmony_ci{
188262306a36Sopenharmony_ci	struct ravb_private *priv = container_of(work, struct ravb_private,
188362306a36Sopenharmony_ci						 work);
188462306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
188562306a36Sopenharmony_ci	struct net_device *ndev = priv->ndev;
188662306a36Sopenharmony_ci	int error;
188762306a36Sopenharmony_ci
188862306a36Sopenharmony_ci	if (!rtnl_trylock()) {
188962306a36Sopenharmony_ci		usleep_range(1000, 2000);
189062306a36Sopenharmony_ci		schedule_work(&priv->work);
189162306a36Sopenharmony_ci		return;
189262306a36Sopenharmony_ci	}
189362306a36Sopenharmony_ci
189462306a36Sopenharmony_ci	netif_tx_stop_all_queues(ndev);
189562306a36Sopenharmony_ci
189662306a36Sopenharmony_ci	/* Stop PTP Clock driver */
189762306a36Sopenharmony_ci	if (info->gptp)
189862306a36Sopenharmony_ci		ravb_ptp_stop(ndev);
189962306a36Sopenharmony_ci
190062306a36Sopenharmony_ci	/* Wait for DMA stopping */
190162306a36Sopenharmony_ci	if (ravb_stop_dma(ndev)) {
190262306a36Sopenharmony_ci		/* If ravb_stop_dma() fails, the hardware is still operating
190362306a36Sopenharmony_ci		 * for TX and/or RX. So, this should not call the following
190462306a36Sopenharmony_ci		 * functions because ravb_dmac_init() is possible to fail too.
190562306a36Sopenharmony_ci		 * Also, this should not retry ravb_stop_dma() again and again
190662306a36Sopenharmony_ci		 * here because it's possible to wait forever. So, this just
190762306a36Sopenharmony_ci		 * re-enables the TX and RX and skip the following
190862306a36Sopenharmony_ci		 * re-initialization procedure.
190962306a36Sopenharmony_ci		 */
191062306a36Sopenharmony_ci		ravb_rcv_snd_enable(ndev);
191162306a36Sopenharmony_ci		goto out;
191262306a36Sopenharmony_ci	}
191362306a36Sopenharmony_ci
191462306a36Sopenharmony_ci	ravb_ring_free(ndev, RAVB_BE);
191562306a36Sopenharmony_ci	if (info->nc_queues)
191662306a36Sopenharmony_ci		ravb_ring_free(ndev, RAVB_NC);
191762306a36Sopenharmony_ci
191862306a36Sopenharmony_ci	/* Device init */
191962306a36Sopenharmony_ci	error = ravb_dmac_init(ndev);
192062306a36Sopenharmony_ci	if (error) {
192162306a36Sopenharmony_ci		/* If ravb_dmac_init() fails, descriptors are freed. So, this
192262306a36Sopenharmony_ci		 * should return here to avoid re-enabling the TX and RX in
192362306a36Sopenharmony_ci		 * ravb_emac_init().
192462306a36Sopenharmony_ci		 */
192562306a36Sopenharmony_ci		netdev_err(ndev, "%s: ravb_dmac_init() failed, error %d\n",
192662306a36Sopenharmony_ci			   __func__, error);
192762306a36Sopenharmony_ci		goto out_unlock;
192862306a36Sopenharmony_ci	}
192962306a36Sopenharmony_ci	ravb_emac_init(ndev);
193062306a36Sopenharmony_ci
193162306a36Sopenharmony_ciout:
193262306a36Sopenharmony_ci	/* Initialise PTP Clock driver */
193362306a36Sopenharmony_ci	if (info->gptp)
193462306a36Sopenharmony_ci		ravb_ptp_init(ndev, priv->pdev);
193562306a36Sopenharmony_ci
193662306a36Sopenharmony_ci	netif_tx_start_all_queues(ndev);
193762306a36Sopenharmony_ci
193862306a36Sopenharmony_ciout_unlock:
193962306a36Sopenharmony_ci	rtnl_unlock();
194062306a36Sopenharmony_ci}
194162306a36Sopenharmony_ci
194262306a36Sopenharmony_ci/* Packet transmit function for Ethernet AVB */
194362306a36Sopenharmony_cistatic netdev_tx_t ravb_start_xmit(struct sk_buff *skb, struct net_device *ndev)
194462306a36Sopenharmony_ci{
194562306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
194662306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
194762306a36Sopenharmony_ci	unsigned int num_tx_desc = priv->num_tx_desc;
194862306a36Sopenharmony_ci	u16 q = skb_get_queue_mapping(skb);
194962306a36Sopenharmony_ci	struct ravb_tstamp_skb *ts_skb;
195062306a36Sopenharmony_ci	struct ravb_tx_desc *desc;
195162306a36Sopenharmony_ci	unsigned long flags;
195262306a36Sopenharmony_ci	dma_addr_t dma_addr;
195362306a36Sopenharmony_ci	void *buffer;
195462306a36Sopenharmony_ci	u32 entry;
195562306a36Sopenharmony_ci	u32 len;
195662306a36Sopenharmony_ci
195762306a36Sopenharmony_ci	spin_lock_irqsave(&priv->lock, flags);
195862306a36Sopenharmony_ci	if (priv->cur_tx[q] - priv->dirty_tx[q] > (priv->num_tx_ring[q] - 1) *
195962306a36Sopenharmony_ci	    num_tx_desc) {
196062306a36Sopenharmony_ci		netif_err(priv, tx_queued, ndev,
196162306a36Sopenharmony_ci			  "still transmitting with the full ring!\n");
196262306a36Sopenharmony_ci		netif_stop_subqueue(ndev, q);
196362306a36Sopenharmony_ci		spin_unlock_irqrestore(&priv->lock, flags);
196462306a36Sopenharmony_ci		return NETDEV_TX_BUSY;
196562306a36Sopenharmony_ci	}
196662306a36Sopenharmony_ci
196762306a36Sopenharmony_ci	if (skb_put_padto(skb, ETH_ZLEN))
196862306a36Sopenharmony_ci		goto exit;
196962306a36Sopenharmony_ci
197062306a36Sopenharmony_ci	entry = priv->cur_tx[q] % (priv->num_tx_ring[q] * num_tx_desc);
197162306a36Sopenharmony_ci	priv->tx_skb[q][entry / num_tx_desc] = skb;
197262306a36Sopenharmony_ci
197362306a36Sopenharmony_ci	if (num_tx_desc > 1) {
197462306a36Sopenharmony_ci		buffer = PTR_ALIGN(priv->tx_align[q], DPTR_ALIGN) +
197562306a36Sopenharmony_ci			 entry / num_tx_desc * DPTR_ALIGN;
197662306a36Sopenharmony_ci		len = PTR_ALIGN(skb->data, DPTR_ALIGN) - skb->data;
197762306a36Sopenharmony_ci
197862306a36Sopenharmony_ci		/* Zero length DMA descriptors are problematic as they seem
197962306a36Sopenharmony_ci		 * to terminate DMA transfers. Avoid them by simply using a
198062306a36Sopenharmony_ci		 * length of DPTR_ALIGN (4) when skb data is aligned to
198162306a36Sopenharmony_ci		 * DPTR_ALIGN.
198262306a36Sopenharmony_ci		 *
198362306a36Sopenharmony_ci		 * As skb is guaranteed to have at least ETH_ZLEN (60)
198462306a36Sopenharmony_ci		 * bytes of data by the call to skb_put_padto() above this
198562306a36Sopenharmony_ci		 * is safe with respect to both the length of the first DMA
198662306a36Sopenharmony_ci		 * descriptor (len) overflowing the available data and the
198762306a36Sopenharmony_ci		 * length of the second DMA descriptor (skb->len - len)
198862306a36Sopenharmony_ci		 * being negative.
198962306a36Sopenharmony_ci		 */
199062306a36Sopenharmony_ci		if (len == 0)
199162306a36Sopenharmony_ci			len = DPTR_ALIGN;
199262306a36Sopenharmony_ci
199362306a36Sopenharmony_ci		memcpy(buffer, skb->data, len);
199462306a36Sopenharmony_ci		dma_addr = dma_map_single(ndev->dev.parent, buffer, len,
199562306a36Sopenharmony_ci					  DMA_TO_DEVICE);
199662306a36Sopenharmony_ci		if (dma_mapping_error(ndev->dev.parent, dma_addr))
199762306a36Sopenharmony_ci			goto drop;
199862306a36Sopenharmony_ci
199962306a36Sopenharmony_ci		desc = &priv->tx_ring[q][entry];
200062306a36Sopenharmony_ci		desc->ds_tagl = cpu_to_le16(len);
200162306a36Sopenharmony_ci		desc->dptr = cpu_to_le32(dma_addr);
200262306a36Sopenharmony_ci
200362306a36Sopenharmony_ci		buffer = skb->data + len;
200462306a36Sopenharmony_ci		len = skb->len - len;
200562306a36Sopenharmony_ci		dma_addr = dma_map_single(ndev->dev.parent, buffer, len,
200662306a36Sopenharmony_ci					  DMA_TO_DEVICE);
200762306a36Sopenharmony_ci		if (dma_mapping_error(ndev->dev.parent, dma_addr))
200862306a36Sopenharmony_ci			goto unmap;
200962306a36Sopenharmony_ci
201062306a36Sopenharmony_ci		desc++;
201162306a36Sopenharmony_ci	} else {
201262306a36Sopenharmony_ci		desc = &priv->tx_ring[q][entry];
201362306a36Sopenharmony_ci		len = skb->len;
201462306a36Sopenharmony_ci		dma_addr = dma_map_single(ndev->dev.parent, skb->data, skb->len,
201562306a36Sopenharmony_ci					  DMA_TO_DEVICE);
201662306a36Sopenharmony_ci		if (dma_mapping_error(ndev->dev.parent, dma_addr))
201762306a36Sopenharmony_ci			goto drop;
201862306a36Sopenharmony_ci	}
201962306a36Sopenharmony_ci	desc->ds_tagl = cpu_to_le16(len);
202062306a36Sopenharmony_ci	desc->dptr = cpu_to_le32(dma_addr);
202162306a36Sopenharmony_ci
202262306a36Sopenharmony_ci	/* TX timestamp required */
202362306a36Sopenharmony_ci	if (info->gptp || info->ccc_gac) {
202462306a36Sopenharmony_ci		if (q == RAVB_NC) {
202562306a36Sopenharmony_ci			ts_skb = kmalloc(sizeof(*ts_skb), GFP_ATOMIC);
202662306a36Sopenharmony_ci			if (!ts_skb) {
202762306a36Sopenharmony_ci				if (num_tx_desc > 1) {
202862306a36Sopenharmony_ci					desc--;
202962306a36Sopenharmony_ci					dma_unmap_single(ndev->dev.parent, dma_addr,
203062306a36Sopenharmony_ci							 len, DMA_TO_DEVICE);
203162306a36Sopenharmony_ci				}
203262306a36Sopenharmony_ci				goto unmap;
203362306a36Sopenharmony_ci			}
203462306a36Sopenharmony_ci			ts_skb->skb = skb_get(skb);
203562306a36Sopenharmony_ci			ts_skb->tag = priv->ts_skb_tag++;
203662306a36Sopenharmony_ci			priv->ts_skb_tag &= 0x3ff;
203762306a36Sopenharmony_ci			list_add_tail(&ts_skb->list, &priv->ts_skb_list);
203862306a36Sopenharmony_ci
203962306a36Sopenharmony_ci			/* TAG and timestamp required flag */
204062306a36Sopenharmony_ci			skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
204162306a36Sopenharmony_ci			desc->tagh_tsr = (ts_skb->tag >> 4) | TX_TSR;
204262306a36Sopenharmony_ci			desc->ds_tagl |= cpu_to_le16(ts_skb->tag << 12);
204362306a36Sopenharmony_ci		}
204462306a36Sopenharmony_ci
204562306a36Sopenharmony_ci		skb_tx_timestamp(skb);
204662306a36Sopenharmony_ci	}
204762306a36Sopenharmony_ci	/* Descriptor type must be set after all the above writes */
204862306a36Sopenharmony_ci	dma_wmb();
204962306a36Sopenharmony_ci	if (num_tx_desc > 1) {
205062306a36Sopenharmony_ci		desc->die_dt = DT_FEND;
205162306a36Sopenharmony_ci		desc--;
205262306a36Sopenharmony_ci		desc->die_dt = DT_FSTART;
205362306a36Sopenharmony_ci	} else {
205462306a36Sopenharmony_ci		desc->die_dt = DT_FSINGLE;
205562306a36Sopenharmony_ci	}
205662306a36Sopenharmony_ci	ravb_modify(ndev, TCCR, TCCR_TSRQ0 << q, TCCR_TSRQ0 << q);
205762306a36Sopenharmony_ci
205862306a36Sopenharmony_ci	priv->cur_tx[q] += num_tx_desc;
205962306a36Sopenharmony_ci	if (priv->cur_tx[q] - priv->dirty_tx[q] >
206062306a36Sopenharmony_ci	    (priv->num_tx_ring[q] - 1) * num_tx_desc &&
206162306a36Sopenharmony_ci	    !ravb_tx_free(ndev, q, true))
206262306a36Sopenharmony_ci		netif_stop_subqueue(ndev, q);
206362306a36Sopenharmony_ci
206462306a36Sopenharmony_ciexit:
206562306a36Sopenharmony_ci	spin_unlock_irqrestore(&priv->lock, flags);
206662306a36Sopenharmony_ci	return NETDEV_TX_OK;
206762306a36Sopenharmony_ci
206862306a36Sopenharmony_ciunmap:
206962306a36Sopenharmony_ci	dma_unmap_single(ndev->dev.parent, le32_to_cpu(desc->dptr),
207062306a36Sopenharmony_ci			 le16_to_cpu(desc->ds_tagl), DMA_TO_DEVICE);
207162306a36Sopenharmony_cidrop:
207262306a36Sopenharmony_ci	dev_kfree_skb_any(skb);
207362306a36Sopenharmony_ci	priv->tx_skb[q][entry / num_tx_desc] = NULL;
207462306a36Sopenharmony_ci	goto exit;
207562306a36Sopenharmony_ci}
207662306a36Sopenharmony_ci
207762306a36Sopenharmony_cistatic u16 ravb_select_queue(struct net_device *ndev, struct sk_buff *skb,
207862306a36Sopenharmony_ci			     struct net_device *sb_dev)
207962306a36Sopenharmony_ci{
208062306a36Sopenharmony_ci	/* If skb needs TX timestamp, it is handled in network control queue */
208162306a36Sopenharmony_ci	return (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) ? RAVB_NC :
208262306a36Sopenharmony_ci							       RAVB_BE;
208362306a36Sopenharmony_ci
208462306a36Sopenharmony_ci}
208562306a36Sopenharmony_ci
208662306a36Sopenharmony_cistatic struct net_device_stats *ravb_get_stats(struct net_device *ndev)
208762306a36Sopenharmony_ci{
208862306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
208962306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
209062306a36Sopenharmony_ci	struct net_device_stats *nstats, *stats0, *stats1;
209162306a36Sopenharmony_ci
209262306a36Sopenharmony_ci	nstats = &ndev->stats;
209362306a36Sopenharmony_ci	stats0 = &priv->stats[RAVB_BE];
209462306a36Sopenharmony_ci
209562306a36Sopenharmony_ci	if (info->tx_counters) {
209662306a36Sopenharmony_ci		nstats->tx_dropped += ravb_read(ndev, TROCR);
209762306a36Sopenharmony_ci		ravb_write(ndev, 0, TROCR);	/* (write clear) */
209862306a36Sopenharmony_ci	}
209962306a36Sopenharmony_ci
210062306a36Sopenharmony_ci	if (info->carrier_counters) {
210162306a36Sopenharmony_ci		nstats->collisions += ravb_read(ndev, CXR41);
210262306a36Sopenharmony_ci		ravb_write(ndev, 0, CXR41);	/* (write clear) */
210362306a36Sopenharmony_ci		nstats->tx_carrier_errors += ravb_read(ndev, CXR42);
210462306a36Sopenharmony_ci		ravb_write(ndev, 0, CXR42);	/* (write clear) */
210562306a36Sopenharmony_ci	}
210662306a36Sopenharmony_ci
210762306a36Sopenharmony_ci	nstats->rx_packets = stats0->rx_packets;
210862306a36Sopenharmony_ci	nstats->tx_packets = stats0->tx_packets;
210962306a36Sopenharmony_ci	nstats->rx_bytes = stats0->rx_bytes;
211062306a36Sopenharmony_ci	nstats->tx_bytes = stats0->tx_bytes;
211162306a36Sopenharmony_ci	nstats->multicast = stats0->multicast;
211262306a36Sopenharmony_ci	nstats->rx_errors = stats0->rx_errors;
211362306a36Sopenharmony_ci	nstats->rx_crc_errors = stats0->rx_crc_errors;
211462306a36Sopenharmony_ci	nstats->rx_frame_errors = stats0->rx_frame_errors;
211562306a36Sopenharmony_ci	nstats->rx_length_errors = stats0->rx_length_errors;
211662306a36Sopenharmony_ci	nstats->rx_missed_errors = stats0->rx_missed_errors;
211762306a36Sopenharmony_ci	nstats->rx_over_errors = stats0->rx_over_errors;
211862306a36Sopenharmony_ci	if (info->nc_queues) {
211962306a36Sopenharmony_ci		stats1 = &priv->stats[RAVB_NC];
212062306a36Sopenharmony_ci
212162306a36Sopenharmony_ci		nstats->rx_packets += stats1->rx_packets;
212262306a36Sopenharmony_ci		nstats->tx_packets += stats1->tx_packets;
212362306a36Sopenharmony_ci		nstats->rx_bytes += stats1->rx_bytes;
212462306a36Sopenharmony_ci		nstats->tx_bytes += stats1->tx_bytes;
212562306a36Sopenharmony_ci		nstats->multicast += stats1->multicast;
212662306a36Sopenharmony_ci		nstats->rx_errors += stats1->rx_errors;
212762306a36Sopenharmony_ci		nstats->rx_crc_errors += stats1->rx_crc_errors;
212862306a36Sopenharmony_ci		nstats->rx_frame_errors += stats1->rx_frame_errors;
212962306a36Sopenharmony_ci		nstats->rx_length_errors += stats1->rx_length_errors;
213062306a36Sopenharmony_ci		nstats->rx_missed_errors += stats1->rx_missed_errors;
213162306a36Sopenharmony_ci		nstats->rx_over_errors += stats1->rx_over_errors;
213262306a36Sopenharmony_ci	}
213362306a36Sopenharmony_ci
213462306a36Sopenharmony_ci	return nstats;
213562306a36Sopenharmony_ci}
213662306a36Sopenharmony_ci
213762306a36Sopenharmony_ci/* Update promiscuous bit */
213862306a36Sopenharmony_cistatic void ravb_set_rx_mode(struct net_device *ndev)
213962306a36Sopenharmony_ci{
214062306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
214162306a36Sopenharmony_ci	unsigned long flags;
214262306a36Sopenharmony_ci
214362306a36Sopenharmony_ci	spin_lock_irqsave(&priv->lock, flags);
214462306a36Sopenharmony_ci	ravb_modify(ndev, ECMR, ECMR_PRM,
214562306a36Sopenharmony_ci		    ndev->flags & IFF_PROMISC ? ECMR_PRM : 0);
214662306a36Sopenharmony_ci	spin_unlock_irqrestore(&priv->lock, flags);
214762306a36Sopenharmony_ci}
214862306a36Sopenharmony_ci
214962306a36Sopenharmony_ci/* Device close function for Ethernet AVB */
215062306a36Sopenharmony_cistatic int ravb_close(struct net_device *ndev)
215162306a36Sopenharmony_ci{
215262306a36Sopenharmony_ci	struct device_node *np = ndev->dev.parent->of_node;
215362306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
215462306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
215562306a36Sopenharmony_ci	struct ravb_tstamp_skb *ts_skb, *ts_skb2;
215662306a36Sopenharmony_ci
215762306a36Sopenharmony_ci	netif_tx_stop_all_queues(ndev);
215862306a36Sopenharmony_ci
215962306a36Sopenharmony_ci	/* Disable interrupts by clearing the interrupt masks. */
216062306a36Sopenharmony_ci	ravb_write(ndev, 0, RIC0);
216162306a36Sopenharmony_ci	ravb_write(ndev, 0, RIC2);
216262306a36Sopenharmony_ci	ravb_write(ndev, 0, TIC);
216362306a36Sopenharmony_ci
216462306a36Sopenharmony_ci	/* Stop PTP Clock driver */
216562306a36Sopenharmony_ci	if (info->gptp)
216662306a36Sopenharmony_ci		ravb_ptp_stop(ndev);
216762306a36Sopenharmony_ci
216862306a36Sopenharmony_ci	/* Set the config mode to stop the AVB-DMAC's processes */
216962306a36Sopenharmony_ci	if (ravb_stop_dma(ndev) < 0)
217062306a36Sopenharmony_ci		netdev_err(ndev,
217162306a36Sopenharmony_ci			   "device will be stopped after h/w processes are done.\n");
217262306a36Sopenharmony_ci
217362306a36Sopenharmony_ci	/* Clear the timestamp list */
217462306a36Sopenharmony_ci	if (info->gptp || info->ccc_gac) {
217562306a36Sopenharmony_ci		list_for_each_entry_safe(ts_skb, ts_skb2, &priv->ts_skb_list, list) {
217662306a36Sopenharmony_ci			list_del(&ts_skb->list);
217762306a36Sopenharmony_ci			kfree_skb(ts_skb->skb);
217862306a36Sopenharmony_ci			kfree(ts_skb);
217962306a36Sopenharmony_ci		}
218062306a36Sopenharmony_ci	}
218162306a36Sopenharmony_ci
218262306a36Sopenharmony_ci	/* PHY disconnect */
218362306a36Sopenharmony_ci	if (ndev->phydev) {
218462306a36Sopenharmony_ci		phy_stop(ndev->phydev);
218562306a36Sopenharmony_ci		phy_disconnect(ndev->phydev);
218662306a36Sopenharmony_ci		if (of_phy_is_fixed_link(np))
218762306a36Sopenharmony_ci			of_phy_deregister_fixed_link(np);
218862306a36Sopenharmony_ci	}
218962306a36Sopenharmony_ci
219062306a36Sopenharmony_ci	cancel_work_sync(&priv->work);
219162306a36Sopenharmony_ci
219262306a36Sopenharmony_ci	if (info->multi_irqs) {
219362306a36Sopenharmony_ci		free_irq(priv->tx_irqs[RAVB_NC], ndev);
219462306a36Sopenharmony_ci		free_irq(priv->rx_irqs[RAVB_NC], ndev);
219562306a36Sopenharmony_ci		free_irq(priv->tx_irqs[RAVB_BE], ndev);
219662306a36Sopenharmony_ci		free_irq(priv->rx_irqs[RAVB_BE], ndev);
219762306a36Sopenharmony_ci		free_irq(priv->emac_irq, ndev);
219862306a36Sopenharmony_ci		if (info->err_mgmt_irqs) {
219962306a36Sopenharmony_ci			free_irq(priv->erra_irq, ndev);
220062306a36Sopenharmony_ci			free_irq(priv->mgmta_irq, ndev);
220162306a36Sopenharmony_ci		}
220262306a36Sopenharmony_ci	}
220362306a36Sopenharmony_ci	free_irq(ndev->irq, ndev);
220462306a36Sopenharmony_ci
220562306a36Sopenharmony_ci	if (info->nc_queues)
220662306a36Sopenharmony_ci		napi_disable(&priv->napi[RAVB_NC]);
220762306a36Sopenharmony_ci	napi_disable(&priv->napi[RAVB_BE]);
220862306a36Sopenharmony_ci
220962306a36Sopenharmony_ci	/* Free all the skb's in the RX queue and the DMA buffers. */
221062306a36Sopenharmony_ci	ravb_ring_free(ndev, RAVB_BE);
221162306a36Sopenharmony_ci	if (info->nc_queues)
221262306a36Sopenharmony_ci		ravb_ring_free(ndev, RAVB_NC);
221362306a36Sopenharmony_ci
221462306a36Sopenharmony_ci	return 0;
221562306a36Sopenharmony_ci}
221662306a36Sopenharmony_ci
221762306a36Sopenharmony_cistatic int ravb_hwtstamp_get(struct net_device *ndev, struct ifreq *req)
221862306a36Sopenharmony_ci{
221962306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
222062306a36Sopenharmony_ci	struct hwtstamp_config config;
222162306a36Sopenharmony_ci
222262306a36Sopenharmony_ci	config.flags = 0;
222362306a36Sopenharmony_ci	config.tx_type = priv->tstamp_tx_ctrl ? HWTSTAMP_TX_ON :
222462306a36Sopenharmony_ci						HWTSTAMP_TX_OFF;
222562306a36Sopenharmony_ci	switch (priv->tstamp_rx_ctrl & RAVB_RXTSTAMP_TYPE) {
222662306a36Sopenharmony_ci	case RAVB_RXTSTAMP_TYPE_V2_L2_EVENT:
222762306a36Sopenharmony_ci		config.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT;
222862306a36Sopenharmony_ci		break;
222962306a36Sopenharmony_ci	case RAVB_RXTSTAMP_TYPE_ALL:
223062306a36Sopenharmony_ci		config.rx_filter = HWTSTAMP_FILTER_ALL;
223162306a36Sopenharmony_ci		break;
223262306a36Sopenharmony_ci	default:
223362306a36Sopenharmony_ci		config.rx_filter = HWTSTAMP_FILTER_NONE;
223462306a36Sopenharmony_ci	}
223562306a36Sopenharmony_ci
223662306a36Sopenharmony_ci	return copy_to_user(req->ifr_data, &config, sizeof(config)) ?
223762306a36Sopenharmony_ci		-EFAULT : 0;
223862306a36Sopenharmony_ci}
223962306a36Sopenharmony_ci
224062306a36Sopenharmony_ci/* Control hardware time stamping */
224162306a36Sopenharmony_cistatic int ravb_hwtstamp_set(struct net_device *ndev, struct ifreq *req)
224262306a36Sopenharmony_ci{
224362306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
224462306a36Sopenharmony_ci	struct hwtstamp_config config;
224562306a36Sopenharmony_ci	u32 tstamp_rx_ctrl = RAVB_RXTSTAMP_ENABLED;
224662306a36Sopenharmony_ci	u32 tstamp_tx_ctrl;
224762306a36Sopenharmony_ci
224862306a36Sopenharmony_ci	if (copy_from_user(&config, req->ifr_data, sizeof(config)))
224962306a36Sopenharmony_ci		return -EFAULT;
225062306a36Sopenharmony_ci
225162306a36Sopenharmony_ci	switch (config.tx_type) {
225262306a36Sopenharmony_ci	case HWTSTAMP_TX_OFF:
225362306a36Sopenharmony_ci		tstamp_tx_ctrl = 0;
225462306a36Sopenharmony_ci		break;
225562306a36Sopenharmony_ci	case HWTSTAMP_TX_ON:
225662306a36Sopenharmony_ci		tstamp_tx_ctrl = RAVB_TXTSTAMP_ENABLED;
225762306a36Sopenharmony_ci		break;
225862306a36Sopenharmony_ci	default:
225962306a36Sopenharmony_ci		return -ERANGE;
226062306a36Sopenharmony_ci	}
226162306a36Sopenharmony_ci
226262306a36Sopenharmony_ci	switch (config.rx_filter) {
226362306a36Sopenharmony_ci	case HWTSTAMP_FILTER_NONE:
226462306a36Sopenharmony_ci		tstamp_rx_ctrl = 0;
226562306a36Sopenharmony_ci		break;
226662306a36Sopenharmony_ci	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
226762306a36Sopenharmony_ci		tstamp_rx_ctrl |= RAVB_RXTSTAMP_TYPE_V2_L2_EVENT;
226862306a36Sopenharmony_ci		break;
226962306a36Sopenharmony_ci	default:
227062306a36Sopenharmony_ci		config.rx_filter = HWTSTAMP_FILTER_ALL;
227162306a36Sopenharmony_ci		tstamp_rx_ctrl |= RAVB_RXTSTAMP_TYPE_ALL;
227262306a36Sopenharmony_ci	}
227362306a36Sopenharmony_ci
227462306a36Sopenharmony_ci	priv->tstamp_tx_ctrl = tstamp_tx_ctrl;
227562306a36Sopenharmony_ci	priv->tstamp_rx_ctrl = tstamp_rx_ctrl;
227662306a36Sopenharmony_ci
227762306a36Sopenharmony_ci	return copy_to_user(req->ifr_data, &config, sizeof(config)) ?
227862306a36Sopenharmony_ci		-EFAULT : 0;
227962306a36Sopenharmony_ci}
228062306a36Sopenharmony_ci
228162306a36Sopenharmony_ci/* ioctl to device function */
228262306a36Sopenharmony_cistatic int ravb_do_ioctl(struct net_device *ndev, struct ifreq *req, int cmd)
228362306a36Sopenharmony_ci{
228462306a36Sopenharmony_ci	struct phy_device *phydev = ndev->phydev;
228562306a36Sopenharmony_ci
228662306a36Sopenharmony_ci	if (!netif_running(ndev))
228762306a36Sopenharmony_ci		return -EINVAL;
228862306a36Sopenharmony_ci
228962306a36Sopenharmony_ci	if (!phydev)
229062306a36Sopenharmony_ci		return -ENODEV;
229162306a36Sopenharmony_ci
229262306a36Sopenharmony_ci	switch (cmd) {
229362306a36Sopenharmony_ci	case SIOCGHWTSTAMP:
229462306a36Sopenharmony_ci		return ravb_hwtstamp_get(ndev, req);
229562306a36Sopenharmony_ci	case SIOCSHWTSTAMP:
229662306a36Sopenharmony_ci		return ravb_hwtstamp_set(ndev, req);
229762306a36Sopenharmony_ci	}
229862306a36Sopenharmony_ci
229962306a36Sopenharmony_ci	return phy_mii_ioctl(phydev, req, cmd);
230062306a36Sopenharmony_ci}
230162306a36Sopenharmony_ci
230262306a36Sopenharmony_cistatic int ravb_change_mtu(struct net_device *ndev, int new_mtu)
230362306a36Sopenharmony_ci{
230462306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
230562306a36Sopenharmony_ci
230662306a36Sopenharmony_ci	ndev->mtu = new_mtu;
230762306a36Sopenharmony_ci
230862306a36Sopenharmony_ci	if (netif_running(ndev)) {
230962306a36Sopenharmony_ci		synchronize_irq(priv->emac_irq);
231062306a36Sopenharmony_ci		ravb_emac_init(ndev);
231162306a36Sopenharmony_ci	}
231262306a36Sopenharmony_ci
231362306a36Sopenharmony_ci	netdev_update_features(ndev);
231462306a36Sopenharmony_ci
231562306a36Sopenharmony_ci	return 0;
231662306a36Sopenharmony_ci}
231762306a36Sopenharmony_ci
231862306a36Sopenharmony_cistatic void ravb_set_rx_csum(struct net_device *ndev, bool enable)
231962306a36Sopenharmony_ci{
232062306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
232162306a36Sopenharmony_ci	unsigned long flags;
232262306a36Sopenharmony_ci
232362306a36Sopenharmony_ci	spin_lock_irqsave(&priv->lock, flags);
232462306a36Sopenharmony_ci
232562306a36Sopenharmony_ci	/* Disable TX and RX */
232662306a36Sopenharmony_ci	ravb_rcv_snd_disable(ndev);
232762306a36Sopenharmony_ci
232862306a36Sopenharmony_ci	/* Modify RX Checksum setting */
232962306a36Sopenharmony_ci	ravb_modify(ndev, ECMR, ECMR_RCSC, enable ? ECMR_RCSC : 0);
233062306a36Sopenharmony_ci
233162306a36Sopenharmony_ci	/* Enable TX and RX */
233262306a36Sopenharmony_ci	ravb_rcv_snd_enable(ndev);
233362306a36Sopenharmony_ci
233462306a36Sopenharmony_ci	spin_unlock_irqrestore(&priv->lock, flags);
233562306a36Sopenharmony_ci}
233662306a36Sopenharmony_ci
233762306a36Sopenharmony_cistatic int ravb_set_features_gbeth(struct net_device *ndev,
233862306a36Sopenharmony_ci				   netdev_features_t features)
233962306a36Sopenharmony_ci{
234062306a36Sopenharmony_ci	/* Place holder */
234162306a36Sopenharmony_ci	return 0;
234262306a36Sopenharmony_ci}
234362306a36Sopenharmony_ci
234462306a36Sopenharmony_cistatic int ravb_set_features_rcar(struct net_device *ndev,
234562306a36Sopenharmony_ci				  netdev_features_t features)
234662306a36Sopenharmony_ci{
234762306a36Sopenharmony_ci	netdev_features_t changed = ndev->features ^ features;
234862306a36Sopenharmony_ci
234962306a36Sopenharmony_ci	if (changed & NETIF_F_RXCSUM)
235062306a36Sopenharmony_ci		ravb_set_rx_csum(ndev, features & NETIF_F_RXCSUM);
235162306a36Sopenharmony_ci
235262306a36Sopenharmony_ci	ndev->features = features;
235362306a36Sopenharmony_ci
235462306a36Sopenharmony_ci	return 0;
235562306a36Sopenharmony_ci}
235662306a36Sopenharmony_ci
235762306a36Sopenharmony_cistatic int ravb_set_features(struct net_device *ndev,
235862306a36Sopenharmony_ci			     netdev_features_t features)
235962306a36Sopenharmony_ci{
236062306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
236162306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
236262306a36Sopenharmony_ci
236362306a36Sopenharmony_ci	return info->set_feature(ndev, features);
236462306a36Sopenharmony_ci}
236562306a36Sopenharmony_ci
236662306a36Sopenharmony_cistatic const struct net_device_ops ravb_netdev_ops = {
236762306a36Sopenharmony_ci	.ndo_open		= ravb_open,
236862306a36Sopenharmony_ci	.ndo_stop		= ravb_close,
236962306a36Sopenharmony_ci	.ndo_start_xmit		= ravb_start_xmit,
237062306a36Sopenharmony_ci	.ndo_select_queue	= ravb_select_queue,
237162306a36Sopenharmony_ci	.ndo_get_stats		= ravb_get_stats,
237262306a36Sopenharmony_ci	.ndo_set_rx_mode	= ravb_set_rx_mode,
237362306a36Sopenharmony_ci	.ndo_tx_timeout		= ravb_tx_timeout,
237462306a36Sopenharmony_ci	.ndo_eth_ioctl		= ravb_do_ioctl,
237562306a36Sopenharmony_ci	.ndo_change_mtu		= ravb_change_mtu,
237662306a36Sopenharmony_ci	.ndo_validate_addr	= eth_validate_addr,
237762306a36Sopenharmony_ci	.ndo_set_mac_address	= eth_mac_addr,
237862306a36Sopenharmony_ci	.ndo_set_features	= ravb_set_features,
237962306a36Sopenharmony_ci};
238062306a36Sopenharmony_ci
238162306a36Sopenharmony_ci/* MDIO bus init function */
238262306a36Sopenharmony_cistatic int ravb_mdio_init(struct ravb_private *priv)
238362306a36Sopenharmony_ci{
238462306a36Sopenharmony_ci	struct platform_device *pdev = priv->pdev;
238562306a36Sopenharmony_ci	struct device *dev = &pdev->dev;
238662306a36Sopenharmony_ci	struct phy_device *phydev;
238762306a36Sopenharmony_ci	struct device_node *pn;
238862306a36Sopenharmony_ci	int error;
238962306a36Sopenharmony_ci
239062306a36Sopenharmony_ci	/* Bitbang init */
239162306a36Sopenharmony_ci	priv->mdiobb.ops = &bb_ops;
239262306a36Sopenharmony_ci
239362306a36Sopenharmony_ci	/* MII controller setting */
239462306a36Sopenharmony_ci	priv->mii_bus = alloc_mdio_bitbang(&priv->mdiobb);
239562306a36Sopenharmony_ci	if (!priv->mii_bus)
239662306a36Sopenharmony_ci		return -ENOMEM;
239762306a36Sopenharmony_ci
239862306a36Sopenharmony_ci	/* Hook up MII support for ethtool */
239962306a36Sopenharmony_ci	priv->mii_bus->name = "ravb_mii";
240062306a36Sopenharmony_ci	priv->mii_bus->parent = dev;
240162306a36Sopenharmony_ci	snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
240262306a36Sopenharmony_ci		 pdev->name, pdev->id);
240362306a36Sopenharmony_ci
240462306a36Sopenharmony_ci	/* Register MDIO bus */
240562306a36Sopenharmony_ci	error = of_mdiobus_register(priv->mii_bus, dev->of_node);
240662306a36Sopenharmony_ci	if (error)
240762306a36Sopenharmony_ci		goto out_free_bus;
240862306a36Sopenharmony_ci
240962306a36Sopenharmony_ci	pn = of_parse_phandle(dev->of_node, "phy-handle", 0);
241062306a36Sopenharmony_ci	phydev = of_phy_find_device(pn);
241162306a36Sopenharmony_ci	if (phydev) {
241262306a36Sopenharmony_ci		phydev->mac_managed_pm = true;
241362306a36Sopenharmony_ci		put_device(&phydev->mdio.dev);
241462306a36Sopenharmony_ci	}
241562306a36Sopenharmony_ci	of_node_put(pn);
241662306a36Sopenharmony_ci
241762306a36Sopenharmony_ci	return 0;
241862306a36Sopenharmony_ci
241962306a36Sopenharmony_ciout_free_bus:
242062306a36Sopenharmony_ci	free_mdio_bitbang(priv->mii_bus);
242162306a36Sopenharmony_ci	return error;
242262306a36Sopenharmony_ci}
242362306a36Sopenharmony_ci
242462306a36Sopenharmony_ci/* MDIO bus release function */
242562306a36Sopenharmony_cistatic int ravb_mdio_release(struct ravb_private *priv)
242662306a36Sopenharmony_ci{
242762306a36Sopenharmony_ci	/* Unregister mdio bus */
242862306a36Sopenharmony_ci	mdiobus_unregister(priv->mii_bus);
242962306a36Sopenharmony_ci
243062306a36Sopenharmony_ci	/* Free bitbang info */
243162306a36Sopenharmony_ci	free_mdio_bitbang(priv->mii_bus);
243262306a36Sopenharmony_ci
243362306a36Sopenharmony_ci	return 0;
243462306a36Sopenharmony_ci}
243562306a36Sopenharmony_ci
243662306a36Sopenharmony_cistatic const struct ravb_hw_info ravb_gen3_hw_info = {
243762306a36Sopenharmony_ci	.rx_ring_free = ravb_rx_ring_free_rcar,
243862306a36Sopenharmony_ci	.rx_ring_format = ravb_rx_ring_format_rcar,
243962306a36Sopenharmony_ci	.alloc_rx_desc = ravb_alloc_rx_desc_rcar,
244062306a36Sopenharmony_ci	.receive = ravb_rx_rcar,
244162306a36Sopenharmony_ci	.set_rate = ravb_set_rate_rcar,
244262306a36Sopenharmony_ci	.set_feature = ravb_set_features_rcar,
244362306a36Sopenharmony_ci	.dmac_init = ravb_dmac_init_rcar,
244462306a36Sopenharmony_ci	.emac_init = ravb_emac_init_rcar,
244562306a36Sopenharmony_ci	.gstrings_stats = ravb_gstrings_stats,
244662306a36Sopenharmony_ci	.gstrings_size = sizeof(ravb_gstrings_stats),
244762306a36Sopenharmony_ci	.net_hw_features = NETIF_F_RXCSUM,
244862306a36Sopenharmony_ci	.net_features = NETIF_F_RXCSUM,
244962306a36Sopenharmony_ci	.stats_len = ARRAY_SIZE(ravb_gstrings_stats),
245062306a36Sopenharmony_ci	.max_rx_len = RX_BUF_SZ + RAVB_ALIGN - 1,
245162306a36Sopenharmony_ci	.tccr_mask = TCCR_TSRQ0 | TCCR_TSRQ1 | TCCR_TSRQ2 | TCCR_TSRQ3,
245262306a36Sopenharmony_ci	.rx_max_buf_size = SZ_2K,
245362306a36Sopenharmony_ci	.internal_delay = 1,
245462306a36Sopenharmony_ci	.tx_counters = 1,
245562306a36Sopenharmony_ci	.multi_irqs = 1,
245662306a36Sopenharmony_ci	.irq_en_dis = 1,
245762306a36Sopenharmony_ci	.ccc_gac = 1,
245862306a36Sopenharmony_ci	.nc_queues = 1,
245962306a36Sopenharmony_ci	.magic_pkt = 1,
246062306a36Sopenharmony_ci};
246162306a36Sopenharmony_ci
246262306a36Sopenharmony_cistatic const struct ravb_hw_info ravb_gen2_hw_info = {
246362306a36Sopenharmony_ci	.rx_ring_free = ravb_rx_ring_free_rcar,
246462306a36Sopenharmony_ci	.rx_ring_format = ravb_rx_ring_format_rcar,
246562306a36Sopenharmony_ci	.alloc_rx_desc = ravb_alloc_rx_desc_rcar,
246662306a36Sopenharmony_ci	.receive = ravb_rx_rcar,
246762306a36Sopenharmony_ci	.set_rate = ravb_set_rate_rcar,
246862306a36Sopenharmony_ci	.set_feature = ravb_set_features_rcar,
246962306a36Sopenharmony_ci	.dmac_init = ravb_dmac_init_rcar,
247062306a36Sopenharmony_ci	.emac_init = ravb_emac_init_rcar,
247162306a36Sopenharmony_ci	.gstrings_stats = ravb_gstrings_stats,
247262306a36Sopenharmony_ci	.gstrings_size = sizeof(ravb_gstrings_stats),
247362306a36Sopenharmony_ci	.net_hw_features = NETIF_F_RXCSUM,
247462306a36Sopenharmony_ci	.net_features = NETIF_F_RXCSUM,
247562306a36Sopenharmony_ci	.stats_len = ARRAY_SIZE(ravb_gstrings_stats),
247662306a36Sopenharmony_ci	.max_rx_len = RX_BUF_SZ + RAVB_ALIGN - 1,
247762306a36Sopenharmony_ci	.tccr_mask = TCCR_TSRQ0 | TCCR_TSRQ1 | TCCR_TSRQ2 | TCCR_TSRQ3,
247862306a36Sopenharmony_ci	.rx_max_buf_size = SZ_2K,
247962306a36Sopenharmony_ci	.aligned_tx = 1,
248062306a36Sopenharmony_ci	.gptp = 1,
248162306a36Sopenharmony_ci	.nc_queues = 1,
248262306a36Sopenharmony_ci	.magic_pkt = 1,
248362306a36Sopenharmony_ci};
248462306a36Sopenharmony_ci
248562306a36Sopenharmony_cistatic const struct ravb_hw_info ravb_rzv2m_hw_info = {
248662306a36Sopenharmony_ci	.rx_ring_free = ravb_rx_ring_free_rcar,
248762306a36Sopenharmony_ci	.rx_ring_format = ravb_rx_ring_format_rcar,
248862306a36Sopenharmony_ci	.alloc_rx_desc = ravb_alloc_rx_desc_rcar,
248962306a36Sopenharmony_ci	.receive = ravb_rx_rcar,
249062306a36Sopenharmony_ci	.set_rate = ravb_set_rate_rcar,
249162306a36Sopenharmony_ci	.set_feature = ravb_set_features_rcar,
249262306a36Sopenharmony_ci	.dmac_init = ravb_dmac_init_rcar,
249362306a36Sopenharmony_ci	.emac_init = ravb_emac_init_rcar,
249462306a36Sopenharmony_ci	.gstrings_stats = ravb_gstrings_stats,
249562306a36Sopenharmony_ci	.gstrings_size = sizeof(ravb_gstrings_stats),
249662306a36Sopenharmony_ci	.net_hw_features = NETIF_F_RXCSUM,
249762306a36Sopenharmony_ci	.net_features = NETIF_F_RXCSUM,
249862306a36Sopenharmony_ci	.stats_len = ARRAY_SIZE(ravb_gstrings_stats),
249962306a36Sopenharmony_ci	.max_rx_len = RX_BUF_SZ + RAVB_ALIGN - 1,
250062306a36Sopenharmony_ci	.tccr_mask = TCCR_TSRQ0 | TCCR_TSRQ1 | TCCR_TSRQ2 | TCCR_TSRQ3,
250162306a36Sopenharmony_ci	.rx_max_buf_size = SZ_2K,
250262306a36Sopenharmony_ci	.multi_irqs = 1,
250362306a36Sopenharmony_ci	.err_mgmt_irqs = 1,
250462306a36Sopenharmony_ci	.gptp = 1,
250562306a36Sopenharmony_ci	.gptp_ref_clk = 1,
250662306a36Sopenharmony_ci	.nc_queues = 1,
250762306a36Sopenharmony_ci	.magic_pkt = 1,
250862306a36Sopenharmony_ci};
250962306a36Sopenharmony_ci
251062306a36Sopenharmony_cistatic const struct ravb_hw_info gbeth_hw_info = {
251162306a36Sopenharmony_ci	.rx_ring_free = ravb_rx_ring_free_gbeth,
251262306a36Sopenharmony_ci	.rx_ring_format = ravb_rx_ring_format_gbeth,
251362306a36Sopenharmony_ci	.alloc_rx_desc = ravb_alloc_rx_desc_gbeth,
251462306a36Sopenharmony_ci	.receive = ravb_rx_gbeth,
251562306a36Sopenharmony_ci	.set_rate = ravb_set_rate_gbeth,
251662306a36Sopenharmony_ci	.set_feature = ravb_set_features_gbeth,
251762306a36Sopenharmony_ci	.dmac_init = ravb_dmac_init_gbeth,
251862306a36Sopenharmony_ci	.emac_init = ravb_emac_init_gbeth,
251962306a36Sopenharmony_ci	.gstrings_stats = ravb_gstrings_stats_gbeth,
252062306a36Sopenharmony_ci	.gstrings_size = sizeof(ravb_gstrings_stats_gbeth),
252162306a36Sopenharmony_ci	.stats_len = ARRAY_SIZE(ravb_gstrings_stats_gbeth),
252262306a36Sopenharmony_ci	.max_rx_len = ALIGN(GBETH_RX_BUFF_MAX, RAVB_ALIGN),
252362306a36Sopenharmony_ci	.tccr_mask = TCCR_TSRQ0,
252462306a36Sopenharmony_ci	.rx_max_buf_size = SZ_8K,
252562306a36Sopenharmony_ci	.aligned_tx = 1,
252662306a36Sopenharmony_ci	.tx_counters = 1,
252762306a36Sopenharmony_ci	.carrier_counters = 1,
252862306a36Sopenharmony_ci	.half_duplex = 1,
252962306a36Sopenharmony_ci};
253062306a36Sopenharmony_ci
253162306a36Sopenharmony_cistatic const struct of_device_id ravb_match_table[] = {
253262306a36Sopenharmony_ci	{ .compatible = "renesas,etheravb-r8a7790", .data = &ravb_gen2_hw_info },
253362306a36Sopenharmony_ci	{ .compatible = "renesas,etheravb-r8a7794", .data = &ravb_gen2_hw_info },
253462306a36Sopenharmony_ci	{ .compatible = "renesas,etheravb-rcar-gen2", .data = &ravb_gen2_hw_info },
253562306a36Sopenharmony_ci	{ .compatible = "renesas,etheravb-r8a7795", .data = &ravb_gen3_hw_info },
253662306a36Sopenharmony_ci	{ .compatible = "renesas,etheravb-rcar-gen3", .data = &ravb_gen3_hw_info },
253762306a36Sopenharmony_ci	{ .compatible = "renesas,etheravb-rcar-gen4", .data = &ravb_gen3_hw_info },
253862306a36Sopenharmony_ci	{ .compatible = "renesas,etheravb-rzv2m", .data = &ravb_rzv2m_hw_info },
253962306a36Sopenharmony_ci	{ .compatible = "renesas,rzg2l-gbeth", .data = &gbeth_hw_info },
254062306a36Sopenharmony_ci	{ }
254162306a36Sopenharmony_ci};
254262306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, ravb_match_table);
254362306a36Sopenharmony_ci
254462306a36Sopenharmony_cistatic int ravb_set_gti(struct net_device *ndev)
254562306a36Sopenharmony_ci{
254662306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
254762306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
254862306a36Sopenharmony_ci	struct device *dev = ndev->dev.parent;
254962306a36Sopenharmony_ci	unsigned long rate;
255062306a36Sopenharmony_ci	uint64_t inc;
255162306a36Sopenharmony_ci
255262306a36Sopenharmony_ci	if (info->gptp_ref_clk)
255362306a36Sopenharmony_ci		rate = clk_get_rate(priv->gptp_clk);
255462306a36Sopenharmony_ci	else
255562306a36Sopenharmony_ci		rate = clk_get_rate(priv->clk);
255662306a36Sopenharmony_ci	if (!rate)
255762306a36Sopenharmony_ci		return -EINVAL;
255862306a36Sopenharmony_ci
255962306a36Sopenharmony_ci	inc = div64_ul(1000000000ULL << 20, rate);
256062306a36Sopenharmony_ci
256162306a36Sopenharmony_ci	if (inc < GTI_TIV_MIN || inc > GTI_TIV_MAX) {
256262306a36Sopenharmony_ci		dev_err(dev, "gti.tiv increment 0x%llx is outside the range 0x%x - 0x%x\n",
256362306a36Sopenharmony_ci			inc, GTI_TIV_MIN, GTI_TIV_MAX);
256462306a36Sopenharmony_ci		return -EINVAL;
256562306a36Sopenharmony_ci	}
256662306a36Sopenharmony_ci
256762306a36Sopenharmony_ci	ravb_write(ndev, inc, GTI);
256862306a36Sopenharmony_ci
256962306a36Sopenharmony_ci	return 0;
257062306a36Sopenharmony_ci}
257162306a36Sopenharmony_ci
257262306a36Sopenharmony_cistatic int ravb_set_config_mode(struct net_device *ndev)
257362306a36Sopenharmony_ci{
257462306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
257562306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
257662306a36Sopenharmony_ci	int error;
257762306a36Sopenharmony_ci
257862306a36Sopenharmony_ci	if (info->gptp) {
257962306a36Sopenharmony_ci		error = ravb_set_opmode(ndev, CCC_OPC_CONFIG);
258062306a36Sopenharmony_ci		if (error)
258162306a36Sopenharmony_ci			return error;
258262306a36Sopenharmony_ci		/* Set CSEL value */
258362306a36Sopenharmony_ci		ravb_modify(ndev, CCC, CCC_CSEL, CCC_CSEL_HPB);
258462306a36Sopenharmony_ci	} else if (info->ccc_gac) {
258562306a36Sopenharmony_ci		error = ravb_set_opmode(ndev, CCC_OPC_CONFIG | CCC_GAC | CCC_CSEL_HPB);
258662306a36Sopenharmony_ci	} else {
258762306a36Sopenharmony_ci		error = ravb_set_opmode(ndev, CCC_OPC_CONFIG);
258862306a36Sopenharmony_ci	}
258962306a36Sopenharmony_ci
259062306a36Sopenharmony_ci	return error;
259162306a36Sopenharmony_ci}
259262306a36Sopenharmony_ci
259362306a36Sopenharmony_ci/* Set tx and rx clock internal delay modes */
259462306a36Sopenharmony_cistatic void ravb_parse_delay_mode(struct device_node *np, struct net_device *ndev)
259562306a36Sopenharmony_ci{
259662306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
259762306a36Sopenharmony_ci	bool explicit_delay = false;
259862306a36Sopenharmony_ci	u32 delay;
259962306a36Sopenharmony_ci
260062306a36Sopenharmony_ci	if (!of_property_read_u32(np, "rx-internal-delay-ps", &delay)) {
260162306a36Sopenharmony_ci		/* Valid values are 0 and 1800, according to DT bindings */
260262306a36Sopenharmony_ci		priv->rxcidm = !!delay;
260362306a36Sopenharmony_ci		explicit_delay = true;
260462306a36Sopenharmony_ci	}
260562306a36Sopenharmony_ci	if (!of_property_read_u32(np, "tx-internal-delay-ps", &delay)) {
260662306a36Sopenharmony_ci		/* Valid values are 0 and 2000, according to DT bindings */
260762306a36Sopenharmony_ci		priv->txcidm = !!delay;
260862306a36Sopenharmony_ci		explicit_delay = true;
260962306a36Sopenharmony_ci	}
261062306a36Sopenharmony_ci
261162306a36Sopenharmony_ci	if (explicit_delay)
261262306a36Sopenharmony_ci		return;
261362306a36Sopenharmony_ci
261462306a36Sopenharmony_ci	/* Fall back to legacy rgmii-*id behavior */
261562306a36Sopenharmony_ci	if (priv->phy_interface == PHY_INTERFACE_MODE_RGMII_ID ||
261662306a36Sopenharmony_ci	    priv->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) {
261762306a36Sopenharmony_ci		priv->rxcidm = 1;
261862306a36Sopenharmony_ci		priv->rgmii_override = 1;
261962306a36Sopenharmony_ci	}
262062306a36Sopenharmony_ci
262162306a36Sopenharmony_ci	if (priv->phy_interface == PHY_INTERFACE_MODE_RGMII_ID ||
262262306a36Sopenharmony_ci	    priv->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) {
262362306a36Sopenharmony_ci		priv->txcidm = 1;
262462306a36Sopenharmony_ci		priv->rgmii_override = 1;
262562306a36Sopenharmony_ci	}
262662306a36Sopenharmony_ci}
262762306a36Sopenharmony_ci
262862306a36Sopenharmony_cistatic void ravb_set_delay_mode(struct net_device *ndev)
262962306a36Sopenharmony_ci{
263062306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
263162306a36Sopenharmony_ci	u32 set = 0;
263262306a36Sopenharmony_ci
263362306a36Sopenharmony_ci	if (priv->rxcidm)
263462306a36Sopenharmony_ci		set |= APSR_RDM;
263562306a36Sopenharmony_ci	if (priv->txcidm)
263662306a36Sopenharmony_ci		set |= APSR_TDM;
263762306a36Sopenharmony_ci	ravb_modify(ndev, APSR, APSR_RDM | APSR_TDM, set);
263862306a36Sopenharmony_ci}
263962306a36Sopenharmony_ci
264062306a36Sopenharmony_cistatic int ravb_probe(struct platform_device *pdev)
264162306a36Sopenharmony_ci{
264262306a36Sopenharmony_ci	struct device_node *np = pdev->dev.of_node;
264362306a36Sopenharmony_ci	const struct ravb_hw_info *info;
264462306a36Sopenharmony_ci	struct reset_control *rstc;
264562306a36Sopenharmony_ci	struct ravb_private *priv;
264662306a36Sopenharmony_ci	struct net_device *ndev;
264762306a36Sopenharmony_ci	int error, irq, q;
264862306a36Sopenharmony_ci	struct resource *res;
264962306a36Sopenharmony_ci	int i;
265062306a36Sopenharmony_ci
265162306a36Sopenharmony_ci	if (!np) {
265262306a36Sopenharmony_ci		dev_err(&pdev->dev,
265362306a36Sopenharmony_ci			"this driver is required to be instantiated from device tree\n");
265462306a36Sopenharmony_ci		return -EINVAL;
265562306a36Sopenharmony_ci	}
265662306a36Sopenharmony_ci
265762306a36Sopenharmony_ci	rstc = devm_reset_control_get_optional_exclusive(&pdev->dev, NULL);
265862306a36Sopenharmony_ci	if (IS_ERR(rstc))
265962306a36Sopenharmony_ci		return dev_err_probe(&pdev->dev, PTR_ERR(rstc),
266062306a36Sopenharmony_ci				     "failed to get cpg reset\n");
266162306a36Sopenharmony_ci
266262306a36Sopenharmony_ci	ndev = alloc_etherdev_mqs(sizeof(struct ravb_private),
266362306a36Sopenharmony_ci				  NUM_TX_QUEUE, NUM_RX_QUEUE);
266462306a36Sopenharmony_ci	if (!ndev)
266562306a36Sopenharmony_ci		return -ENOMEM;
266662306a36Sopenharmony_ci
266762306a36Sopenharmony_ci	info = of_device_get_match_data(&pdev->dev);
266862306a36Sopenharmony_ci
266962306a36Sopenharmony_ci	ndev->features = info->net_features;
267062306a36Sopenharmony_ci	ndev->hw_features = info->net_hw_features;
267162306a36Sopenharmony_ci
267262306a36Sopenharmony_ci	error = reset_control_deassert(rstc);
267362306a36Sopenharmony_ci	if (error)
267462306a36Sopenharmony_ci		goto out_free_netdev;
267562306a36Sopenharmony_ci
267662306a36Sopenharmony_ci	pm_runtime_enable(&pdev->dev);
267762306a36Sopenharmony_ci	error = pm_runtime_resume_and_get(&pdev->dev);
267862306a36Sopenharmony_ci	if (error < 0)
267962306a36Sopenharmony_ci		goto out_rpm_disable;
268062306a36Sopenharmony_ci
268162306a36Sopenharmony_ci	if (info->multi_irqs) {
268262306a36Sopenharmony_ci		if (info->err_mgmt_irqs)
268362306a36Sopenharmony_ci			irq = platform_get_irq_byname(pdev, "dia");
268462306a36Sopenharmony_ci		else
268562306a36Sopenharmony_ci			irq = platform_get_irq_byname(pdev, "ch22");
268662306a36Sopenharmony_ci	} else {
268762306a36Sopenharmony_ci		irq = platform_get_irq(pdev, 0);
268862306a36Sopenharmony_ci	}
268962306a36Sopenharmony_ci	if (irq < 0) {
269062306a36Sopenharmony_ci		error = irq;
269162306a36Sopenharmony_ci		goto out_release;
269262306a36Sopenharmony_ci	}
269362306a36Sopenharmony_ci	ndev->irq = irq;
269462306a36Sopenharmony_ci
269562306a36Sopenharmony_ci	SET_NETDEV_DEV(ndev, &pdev->dev);
269662306a36Sopenharmony_ci
269762306a36Sopenharmony_ci	priv = netdev_priv(ndev);
269862306a36Sopenharmony_ci	priv->info = info;
269962306a36Sopenharmony_ci	priv->rstc = rstc;
270062306a36Sopenharmony_ci	priv->ndev = ndev;
270162306a36Sopenharmony_ci	priv->pdev = pdev;
270262306a36Sopenharmony_ci	priv->num_tx_ring[RAVB_BE] = BE_TX_RING_SIZE;
270362306a36Sopenharmony_ci	priv->num_rx_ring[RAVB_BE] = BE_RX_RING_SIZE;
270462306a36Sopenharmony_ci	if (info->nc_queues) {
270562306a36Sopenharmony_ci		priv->num_tx_ring[RAVB_NC] = NC_TX_RING_SIZE;
270662306a36Sopenharmony_ci		priv->num_rx_ring[RAVB_NC] = NC_RX_RING_SIZE;
270762306a36Sopenharmony_ci	}
270862306a36Sopenharmony_ci
270962306a36Sopenharmony_ci	priv->addr = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
271062306a36Sopenharmony_ci	if (IS_ERR(priv->addr)) {
271162306a36Sopenharmony_ci		error = PTR_ERR(priv->addr);
271262306a36Sopenharmony_ci		goto out_release;
271362306a36Sopenharmony_ci	}
271462306a36Sopenharmony_ci
271562306a36Sopenharmony_ci	/* The Ether-specific entries in the device structure. */
271662306a36Sopenharmony_ci	ndev->base_addr = res->start;
271762306a36Sopenharmony_ci
271862306a36Sopenharmony_ci	spin_lock_init(&priv->lock);
271962306a36Sopenharmony_ci	INIT_WORK(&priv->work, ravb_tx_timeout_work);
272062306a36Sopenharmony_ci
272162306a36Sopenharmony_ci	error = of_get_phy_mode(np, &priv->phy_interface);
272262306a36Sopenharmony_ci	if (error && error != -ENODEV)
272362306a36Sopenharmony_ci		goto out_release;
272462306a36Sopenharmony_ci
272562306a36Sopenharmony_ci	priv->no_avb_link = of_property_read_bool(np, "renesas,no-ether-link");
272662306a36Sopenharmony_ci	priv->avb_link_active_low =
272762306a36Sopenharmony_ci		of_property_read_bool(np, "renesas,ether-link-active-low");
272862306a36Sopenharmony_ci
272962306a36Sopenharmony_ci	if (info->multi_irqs) {
273062306a36Sopenharmony_ci		if (info->err_mgmt_irqs)
273162306a36Sopenharmony_ci			irq = platform_get_irq_byname(pdev, "line3");
273262306a36Sopenharmony_ci		else
273362306a36Sopenharmony_ci			irq = platform_get_irq_byname(pdev, "ch24");
273462306a36Sopenharmony_ci		if (irq < 0) {
273562306a36Sopenharmony_ci			error = irq;
273662306a36Sopenharmony_ci			goto out_release;
273762306a36Sopenharmony_ci		}
273862306a36Sopenharmony_ci		priv->emac_irq = irq;
273962306a36Sopenharmony_ci		for (i = 0; i < NUM_RX_QUEUE; i++) {
274062306a36Sopenharmony_ci			irq = platform_get_irq_byname(pdev, ravb_rx_irqs[i]);
274162306a36Sopenharmony_ci			if (irq < 0) {
274262306a36Sopenharmony_ci				error = irq;
274362306a36Sopenharmony_ci				goto out_release;
274462306a36Sopenharmony_ci			}
274562306a36Sopenharmony_ci			priv->rx_irqs[i] = irq;
274662306a36Sopenharmony_ci		}
274762306a36Sopenharmony_ci		for (i = 0; i < NUM_TX_QUEUE; i++) {
274862306a36Sopenharmony_ci			irq = platform_get_irq_byname(pdev, ravb_tx_irqs[i]);
274962306a36Sopenharmony_ci			if (irq < 0) {
275062306a36Sopenharmony_ci				error = irq;
275162306a36Sopenharmony_ci				goto out_release;
275262306a36Sopenharmony_ci			}
275362306a36Sopenharmony_ci			priv->tx_irqs[i] = irq;
275462306a36Sopenharmony_ci		}
275562306a36Sopenharmony_ci
275662306a36Sopenharmony_ci		if (info->err_mgmt_irqs) {
275762306a36Sopenharmony_ci			irq = platform_get_irq_byname(pdev, "err_a");
275862306a36Sopenharmony_ci			if (irq < 0) {
275962306a36Sopenharmony_ci				error = irq;
276062306a36Sopenharmony_ci				goto out_release;
276162306a36Sopenharmony_ci			}
276262306a36Sopenharmony_ci			priv->erra_irq = irq;
276362306a36Sopenharmony_ci
276462306a36Sopenharmony_ci			irq = platform_get_irq_byname(pdev, "mgmt_a");
276562306a36Sopenharmony_ci			if (irq < 0) {
276662306a36Sopenharmony_ci				error = irq;
276762306a36Sopenharmony_ci				goto out_release;
276862306a36Sopenharmony_ci			}
276962306a36Sopenharmony_ci			priv->mgmta_irq = irq;
277062306a36Sopenharmony_ci		}
277162306a36Sopenharmony_ci	}
277262306a36Sopenharmony_ci
277362306a36Sopenharmony_ci	priv->clk = devm_clk_get(&pdev->dev, NULL);
277462306a36Sopenharmony_ci	if (IS_ERR(priv->clk)) {
277562306a36Sopenharmony_ci		error = PTR_ERR(priv->clk);
277662306a36Sopenharmony_ci		goto out_release;
277762306a36Sopenharmony_ci	}
277862306a36Sopenharmony_ci
277962306a36Sopenharmony_ci	priv->refclk = devm_clk_get_optional(&pdev->dev, "refclk");
278062306a36Sopenharmony_ci	if (IS_ERR(priv->refclk)) {
278162306a36Sopenharmony_ci		error = PTR_ERR(priv->refclk);
278262306a36Sopenharmony_ci		goto out_release;
278362306a36Sopenharmony_ci	}
278462306a36Sopenharmony_ci	clk_prepare_enable(priv->refclk);
278562306a36Sopenharmony_ci
278662306a36Sopenharmony_ci	if (info->gptp_ref_clk) {
278762306a36Sopenharmony_ci		priv->gptp_clk = devm_clk_get(&pdev->dev, "gptp");
278862306a36Sopenharmony_ci		if (IS_ERR(priv->gptp_clk)) {
278962306a36Sopenharmony_ci			error = PTR_ERR(priv->gptp_clk);
279062306a36Sopenharmony_ci			goto out_disable_refclk;
279162306a36Sopenharmony_ci		}
279262306a36Sopenharmony_ci		clk_prepare_enable(priv->gptp_clk);
279362306a36Sopenharmony_ci	}
279462306a36Sopenharmony_ci
279562306a36Sopenharmony_ci	ndev->max_mtu = info->rx_max_buf_size - (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN);
279662306a36Sopenharmony_ci	ndev->min_mtu = ETH_MIN_MTU;
279762306a36Sopenharmony_ci
279862306a36Sopenharmony_ci	/* FIXME: R-Car Gen2 has 4byte alignment restriction for tx buffer
279962306a36Sopenharmony_ci	 * Use two descriptor to handle such situation. First descriptor to
280062306a36Sopenharmony_ci	 * handle aligned data buffer and second descriptor to handle the
280162306a36Sopenharmony_ci	 * overflow data because of alignment.
280262306a36Sopenharmony_ci	 */
280362306a36Sopenharmony_ci	priv->num_tx_desc = info->aligned_tx ? 2 : 1;
280462306a36Sopenharmony_ci
280562306a36Sopenharmony_ci	/* Set function */
280662306a36Sopenharmony_ci	ndev->netdev_ops = &ravb_netdev_ops;
280762306a36Sopenharmony_ci	ndev->ethtool_ops = &ravb_ethtool_ops;
280862306a36Sopenharmony_ci
280962306a36Sopenharmony_ci	/* Set AVB config mode */
281062306a36Sopenharmony_ci	error = ravb_set_config_mode(ndev);
281162306a36Sopenharmony_ci	if (error)
281262306a36Sopenharmony_ci		goto out_disable_gptp_clk;
281362306a36Sopenharmony_ci
281462306a36Sopenharmony_ci	if (info->gptp || info->ccc_gac) {
281562306a36Sopenharmony_ci		/* Set GTI value */
281662306a36Sopenharmony_ci		error = ravb_set_gti(ndev);
281762306a36Sopenharmony_ci		if (error)
281862306a36Sopenharmony_ci			goto out_disable_gptp_clk;
281962306a36Sopenharmony_ci
282062306a36Sopenharmony_ci		/* Request GTI loading */
282162306a36Sopenharmony_ci		ravb_modify(ndev, GCCR, GCCR_LTI, GCCR_LTI);
282262306a36Sopenharmony_ci	}
282362306a36Sopenharmony_ci
282462306a36Sopenharmony_ci	if (info->internal_delay) {
282562306a36Sopenharmony_ci		ravb_parse_delay_mode(np, ndev);
282662306a36Sopenharmony_ci		ravb_set_delay_mode(ndev);
282762306a36Sopenharmony_ci	}
282862306a36Sopenharmony_ci
282962306a36Sopenharmony_ci	/* Allocate descriptor base address table */
283062306a36Sopenharmony_ci	priv->desc_bat_size = sizeof(struct ravb_desc) * DBAT_ENTRY_NUM;
283162306a36Sopenharmony_ci	priv->desc_bat = dma_alloc_coherent(ndev->dev.parent, priv->desc_bat_size,
283262306a36Sopenharmony_ci					    &priv->desc_bat_dma, GFP_KERNEL);
283362306a36Sopenharmony_ci	if (!priv->desc_bat) {
283462306a36Sopenharmony_ci		dev_err(&pdev->dev,
283562306a36Sopenharmony_ci			"Cannot allocate desc base address table (size %d bytes)\n",
283662306a36Sopenharmony_ci			priv->desc_bat_size);
283762306a36Sopenharmony_ci		error = -ENOMEM;
283862306a36Sopenharmony_ci		goto out_disable_gptp_clk;
283962306a36Sopenharmony_ci	}
284062306a36Sopenharmony_ci	for (q = RAVB_BE; q < DBAT_ENTRY_NUM; q++)
284162306a36Sopenharmony_ci		priv->desc_bat[q].die_dt = DT_EOS;
284262306a36Sopenharmony_ci	ravb_write(ndev, priv->desc_bat_dma, DBAT);
284362306a36Sopenharmony_ci
284462306a36Sopenharmony_ci	/* Initialise HW timestamp list */
284562306a36Sopenharmony_ci	INIT_LIST_HEAD(&priv->ts_skb_list);
284662306a36Sopenharmony_ci
284762306a36Sopenharmony_ci	/* Initialise PTP Clock driver */
284862306a36Sopenharmony_ci	if (info->ccc_gac)
284962306a36Sopenharmony_ci		ravb_ptp_init(ndev, pdev);
285062306a36Sopenharmony_ci
285162306a36Sopenharmony_ci	/* Debug message level */
285262306a36Sopenharmony_ci	priv->msg_enable = RAVB_DEF_MSG_ENABLE;
285362306a36Sopenharmony_ci
285462306a36Sopenharmony_ci	/* Read and set MAC address */
285562306a36Sopenharmony_ci	ravb_read_mac_address(np, ndev);
285662306a36Sopenharmony_ci	if (!is_valid_ether_addr(ndev->dev_addr)) {
285762306a36Sopenharmony_ci		dev_warn(&pdev->dev,
285862306a36Sopenharmony_ci			 "no valid MAC address supplied, using a random one\n");
285962306a36Sopenharmony_ci		eth_hw_addr_random(ndev);
286062306a36Sopenharmony_ci	}
286162306a36Sopenharmony_ci
286262306a36Sopenharmony_ci	/* MDIO bus init */
286362306a36Sopenharmony_ci	error = ravb_mdio_init(priv);
286462306a36Sopenharmony_ci	if (error) {
286562306a36Sopenharmony_ci		dev_err(&pdev->dev, "failed to initialize MDIO\n");
286662306a36Sopenharmony_ci		goto out_dma_free;
286762306a36Sopenharmony_ci	}
286862306a36Sopenharmony_ci
286962306a36Sopenharmony_ci	netif_napi_add(ndev, &priv->napi[RAVB_BE], ravb_poll);
287062306a36Sopenharmony_ci	if (info->nc_queues)
287162306a36Sopenharmony_ci		netif_napi_add(ndev, &priv->napi[RAVB_NC], ravb_poll);
287262306a36Sopenharmony_ci
287362306a36Sopenharmony_ci	/* Network device register */
287462306a36Sopenharmony_ci	error = register_netdev(ndev);
287562306a36Sopenharmony_ci	if (error)
287662306a36Sopenharmony_ci		goto out_napi_del;
287762306a36Sopenharmony_ci
287862306a36Sopenharmony_ci	device_set_wakeup_capable(&pdev->dev, 1);
287962306a36Sopenharmony_ci
288062306a36Sopenharmony_ci	/* Print device information */
288162306a36Sopenharmony_ci	netdev_info(ndev, "Base address at %#x, %pM, IRQ %d.\n",
288262306a36Sopenharmony_ci		    (u32)ndev->base_addr, ndev->dev_addr, ndev->irq);
288362306a36Sopenharmony_ci
288462306a36Sopenharmony_ci	platform_set_drvdata(pdev, ndev);
288562306a36Sopenharmony_ci
288662306a36Sopenharmony_ci	return 0;
288762306a36Sopenharmony_ci
288862306a36Sopenharmony_ciout_napi_del:
288962306a36Sopenharmony_ci	if (info->nc_queues)
289062306a36Sopenharmony_ci		netif_napi_del(&priv->napi[RAVB_NC]);
289162306a36Sopenharmony_ci
289262306a36Sopenharmony_ci	netif_napi_del(&priv->napi[RAVB_BE]);
289362306a36Sopenharmony_ci	ravb_mdio_release(priv);
289462306a36Sopenharmony_ciout_dma_free:
289562306a36Sopenharmony_ci	dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat,
289662306a36Sopenharmony_ci			  priv->desc_bat_dma);
289762306a36Sopenharmony_ci
289862306a36Sopenharmony_ci	/* Stop PTP Clock driver */
289962306a36Sopenharmony_ci	if (info->ccc_gac)
290062306a36Sopenharmony_ci		ravb_ptp_stop(ndev);
290162306a36Sopenharmony_ciout_disable_gptp_clk:
290262306a36Sopenharmony_ci	clk_disable_unprepare(priv->gptp_clk);
290362306a36Sopenharmony_ciout_disable_refclk:
290462306a36Sopenharmony_ci	clk_disable_unprepare(priv->refclk);
290562306a36Sopenharmony_ciout_release:
290662306a36Sopenharmony_ci	pm_runtime_put(&pdev->dev);
290762306a36Sopenharmony_ciout_rpm_disable:
290862306a36Sopenharmony_ci	pm_runtime_disable(&pdev->dev);
290962306a36Sopenharmony_ci	reset_control_assert(rstc);
291062306a36Sopenharmony_ciout_free_netdev:
291162306a36Sopenharmony_ci	free_netdev(ndev);
291262306a36Sopenharmony_ci	return error;
291362306a36Sopenharmony_ci}
291462306a36Sopenharmony_ci
291562306a36Sopenharmony_cistatic int ravb_remove(struct platform_device *pdev)
291662306a36Sopenharmony_ci{
291762306a36Sopenharmony_ci	struct net_device *ndev = platform_get_drvdata(pdev);
291862306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
291962306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
292062306a36Sopenharmony_ci
292162306a36Sopenharmony_ci	unregister_netdev(ndev);
292262306a36Sopenharmony_ci	if (info->nc_queues)
292362306a36Sopenharmony_ci		netif_napi_del(&priv->napi[RAVB_NC]);
292462306a36Sopenharmony_ci	netif_napi_del(&priv->napi[RAVB_BE]);
292562306a36Sopenharmony_ci
292662306a36Sopenharmony_ci	ravb_mdio_release(priv);
292762306a36Sopenharmony_ci
292862306a36Sopenharmony_ci	/* Stop PTP Clock driver */
292962306a36Sopenharmony_ci	if (info->ccc_gac)
293062306a36Sopenharmony_ci		ravb_ptp_stop(ndev);
293162306a36Sopenharmony_ci
293262306a36Sopenharmony_ci	dma_free_coherent(ndev->dev.parent, priv->desc_bat_size, priv->desc_bat,
293362306a36Sopenharmony_ci			  priv->desc_bat_dma);
293462306a36Sopenharmony_ci
293562306a36Sopenharmony_ci	ravb_set_opmode(ndev, CCC_OPC_RESET);
293662306a36Sopenharmony_ci
293762306a36Sopenharmony_ci	clk_disable_unprepare(priv->gptp_clk);
293862306a36Sopenharmony_ci	clk_disable_unprepare(priv->refclk);
293962306a36Sopenharmony_ci
294062306a36Sopenharmony_ci	pm_runtime_put_sync(&pdev->dev);
294162306a36Sopenharmony_ci	pm_runtime_disable(&pdev->dev);
294262306a36Sopenharmony_ci	reset_control_assert(priv->rstc);
294362306a36Sopenharmony_ci	free_netdev(ndev);
294462306a36Sopenharmony_ci	platform_set_drvdata(pdev, NULL);
294562306a36Sopenharmony_ci
294662306a36Sopenharmony_ci	return 0;
294762306a36Sopenharmony_ci}
294862306a36Sopenharmony_ci
294962306a36Sopenharmony_cistatic int ravb_wol_setup(struct net_device *ndev)
295062306a36Sopenharmony_ci{
295162306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
295262306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
295362306a36Sopenharmony_ci
295462306a36Sopenharmony_ci	/* Disable interrupts by clearing the interrupt masks. */
295562306a36Sopenharmony_ci	ravb_write(ndev, 0, RIC0);
295662306a36Sopenharmony_ci	ravb_write(ndev, 0, RIC2);
295762306a36Sopenharmony_ci	ravb_write(ndev, 0, TIC);
295862306a36Sopenharmony_ci
295962306a36Sopenharmony_ci	/* Only allow ECI interrupts */
296062306a36Sopenharmony_ci	synchronize_irq(priv->emac_irq);
296162306a36Sopenharmony_ci	if (info->nc_queues)
296262306a36Sopenharmony_ci		napi_disable(&priv->napi[RAVB_NC]);
296362306a36Sopenharmony_ci	napi_disable(&priv->napi[RAVB_BE]);
296462306a36Sopenharmony_ci	ravb_write(ndev, ECSIPR_MPDIP, ECSIPR);
296562306a36Sopenharmony_ci
296662306a36Sopenharmony_ci	/* Enable MagicPacket */
296762306a36Sopenharmony_ci	ravb_modify(ndev, ECMR, ECMR_MPDE, ECMR_MPDE);
296862306a36Sopenharmony_ci
296962306a36Sopenharmony_ci	return enable_irq_wake(priv->emac_irq);
297062306a36Sopenharmony_ci}
297162306a36Sopenharmony_ci
297262306a36Sopenharmony_cistatic int ravb_wol_restore(struct net_device *ndev)
297362306a36Sopenharmony_ci{
297462306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
297562306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
297662306a36Sopenharmony_ci
297762306a36Sopenharmony_ci	if (info->nc_queues)
297862306a36Sopenharmony_ci		napi_enable(&priv->napi[RAVB_NC]);
297962306a36Sopenharmony_ci	napi_enable(&priv->napi[RAVB_BE]);
298062306a36Sopenharmony_ci
298162306a36Sopenharmony_ci	/* Disable MagicPacket */
298262306a36Sopenharmony_ci	ravb_modify(ndev, ECMR, ECMR_MPDE, 0);
298362306a36Sopenharmony_ci
298462306a36Sopenharmony_ci	ravb_close(ndev);
298562306a36Sopenharmony_ci
298662306a36Sopenharmony_ci	return disable_irq_wake(priv->emac_irq);
298762306a36Sopenharmony_ci}
298862306a36Sopenharmony_ci
298962306a36Sopenharmony_cistatic int __maybe_unused ravb_suspend(struct device *dev)
299062306a36Sopenharmony_ci{
299162306a36Sopenharmony_ci	struct net_device *ndev = dev_get_drvdata(dev);
299262306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
299362306a36Sopenharmony_ci	int ret;
299462306a36Sopenharmony_ci
299562306a36Sopenharmony_ci	if (!netif_running(ndev))
299662306a36Sopenharmony_ci		return 0;
299762306a36Sopenharmony_ci
299862306a36Sopenharmony_ci	netif_device_detach(ndev);
299962306a36Sopenharmony_ci
300062306a36Sopenharmony_ci	if (priv->wol_enabled)
300162306a36Sopenharmony_ci		ret = ravb_wol_setup(ndev);
300262306a36Sopenharmony_ci	else
300362306a36Sopenharmony_ci		ret = ravb_close(ndev);
300462306a36Sopenharmony_ci
300562306a36Sopenharmony_ci	if (priv->info->ccc_gac)
300662306a36Sopenharmony_ci		ravb_ptp_stop(ndev);
300762306a36Sopenharmony_ci
300862306a36Sopenharmony_ci	return ret;
300962306a36Sopenharmony_ci}
301062306a36Sopenharmony_ci
301162306a36Sopenharmony_cistatic int __maybe_unused ravb_resume(struct device *dev)
301262306a36Sopenharmony_ci{
301362306a36Sopenharmony_ci	struct net_device *ndev = dev_get_drvdata(dev);
301462306a36Sopenharmony_ci	struct ravb_private *priv = netdev_priv(ndev);
301562306a36Sopenharmony_ci	const struct ravb_hw_info *info = priv->info;
301662306a36Sopenharmony_ci	int ret = 0;
301762306a36Sopenharmony_ci
301862306a36Sopenharmony_ci	/* If WoL is enabled set reset mode to rearm the WoL logic */
301962306a36Sopenharmony_ci	if (priv->wol_enabled) {
302062306a36Sopenharmony_ci		ret = ravb_set_opmode(ndev, CCC_OPC_RESET);
302162306a36Sopenharmony_ci		if (ret)
302262306a36Sopenharmony_ci			return ret;
302362306a36Sopenharmony_ci	}
302462306a36Sopenharmony_ci
302562306a36Sopenharmony_ci	/* All register have been reset to default values.
302662306a36Sopenharmony_ci	 * Restore all registers which where setup at probe time and
302762306a36Sopenharmony_ci	 * reopen device if it was running before system suspended.
302862306a36Sopenharmony_ci	 */
302962306a36Sopenharmony_ci
303062306a36Sopenharmony_ci	/* Set AVB config mode */
303162306a36Sopenharmony_ci	ret = ravb_set_config_mode(ndev);
303262306a36Sopenharmony_ci	if (ret)
303362306a36Sopenharmony_ci		return ret;
303462306a36Sopenharmony_ci
303562306a36Sopenharmony_ci	if (info->gptp || info->ccc_gac) {
303662306a36Sopenharmony_ci		/* Set GTI value */
303762306a36Sopenharmony_ci		ret = ravb_set_gti(ndev);
303862306a36Sopenharmony_ci		if (ret)
303962306a36Sopenharmony_ci			return ret;
304062306a36Sopenharmony_ci
304162306a36Sopenharmony_ci		/* Request GTI loading */
304262306a36Sopenharmony_ci		ravb_modify(ndev, GCCR, GCCR_LTI, GCCR_LTI);
304362306a36Sopenharmony_ci	}
304462306a36Sopenharmony_ci
304562306a36Sopenharmony_ci	if (info->internal_delay)
304662306a36Sopenharmony_ci		ravb_set_delay_mode(ndev);
304762306a36Sopenharmony_ci
304862306a36Sopenharmony_ci	/* Restore descriptor base address table */
304962306a36Sopenharmony_ci	ravb_write(ndev, priv->desc_bat_dma, DBAT);
305062306a36Sopenharmony_ci
305162306a36Sopenharmony_ci	if (priv->info->ccc_gac)
305262306a36Sopenharmony_ci		ravb_ptp_init(ndev, priv->pdev);
305362306a36Sopenharmony_ci
305462306a36Sopenharmony_ci	if (netif_running(ndev)) {
305562306a36Sopenharmony_ci		if (priv->wol_enabled) {
305662306a36Sopenharmony_ci			ret = ravb_wol_restore(ndev);
305762306a36Sopenharmony_ci			if (ret)
305862306a36Sopenharmony_ci				return ret;
305962306a36Sopenharmony_ci		}
306062306a36Sopenharmony_ci		ret = ravb_open(ndev);
306162306a36Sopenharmony_ci		if (ret < 0)
306262306a36Sopenharmony_ci			return ret;
306362306a36Sopenharmony_ci		ravb_set_rx_mode(ndev);
306462306a36Sopenharmony_ci		netif_device_attach(ndev);
306562306a36Sopenharmony_ci	}
306662306a36Sopenharmony_ci
306762306a36Sopenharmony_ci	return ret;
306862306a36Sopenharmony_ci}
306962306a36Sopenharmony_ci
307062306a36Sopenharmony_cistatic int __maybe_unused ravb_runtime_nop(struct device *dev)
307162306a36Sopenharmony_ci{
307262306a36Sopenharmony_ci	/* Runtime PM callback shared between ->runtime_suspend()
307362306a36Sopenharmony_ci	 * and ->runtime_resume(). Simply returns success.
307462306a36Sopenharmony_ci	 *
307562306a36Sopenharmony_ci	 * This driver re-initializes all registers after
307662306a36Sopenharmony_ci	 * pm_runtime_get_sync() anyway so there is no need
307762306a36Sopenharmony_ci	 * to save and restore registers here.
307862306a36Sopenharmony_ci	 */
307962306a36Sopenharmony_ci	return 0;
308062306a36Sopenharmony_ci}
308162306a36Sopenharmony_ci
308262306a36Sopenharmony_cistatic const struct dev_pm_ops ravb_dev_pm_ops = {
308362306a36Sopenharmony_ci	SET_SYSTEM_SLEEP_PM_OPS(ravb_suspend, ravb_resume)
308462306a36Sopenharmony_ci	SET_RUNTIME_PM_OPS(ravb_runtime_nop, ravb_runtime_nop, NULL)
308562306a36Sopenharmony_ci};
308662306a36Sopenharmony_ci
308762306a36Sopenharmony_cistatic struct platform_driver ravb_driver = {
308862306a36Sopenharmony_ci	.probe		= ravb_probe,
308962306a36Sopenharmony_ci	.remove		= ravb_remove,
309062306a36Sopenharmony_ci	.driver = {
309162306a36Sopenharmony_ci		.name	= "ravb",
309262306a36Sopenharmony_ci		.pm	= &ravb_dev_pm_ops,
309362306a36Sopenharmony_ci		.of_match_table = ravb_match_table,
309462306a36Sopenharmony_ci	},
309562306a36Sopenharmony_ci};
309662306a36Sopenharmony_ci
309762306a36Sopenharmony_cimodule_platform_driver(ravb_driver);
309862306a36Sopenharmony_ci
309962306a36Sopenharmony_ciMODULE_AUTHOR("Mitsuhiro Kimura, Masaru Nagai");
310062306a36Sopenharmony_ciMODULE_DESCRIPTION("Renesas Ethernet AVB driver");
310162306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
3102