162306a36Sopenharmony_ci/* Synopsys DesignWare Core Enterprise Ethernet (XLGMAC) Driver
262306a36Sopenharmony_ci *
362306a36Sopenharmony_ci * Copyright (c) 2017 Synopsys, Inc. (www.synopsys.com)
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * This program is dual-licensed; you may select either version 2 of
662306a36Sopenharmony_ci * the GNU General Public License ("GPL") or BSD license ("BSD").
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * This Synopsys DWC XLGMAC software driver and associated documentation
962306a36Sopenharmony_ci * (hereinafter the "Software") is an unsupported proprietary work of
1062306a36Sopenharmony_ci * Synopsys, Inc. unless otherwise expressly agreed to in writing between
1162306a36Sopenharmony_ci * Synopsys and you. The Software IS NOT an item of Licensed Software or a
1262306a36Sopenharmony_ci * Licensed Product under any End User Software License Agreement or
1362306a36Sopenharmony_ci * Agreement for Licensed Products with Synopsys or any supplement thereto.
1462306a36Sopenharmony_ci * Synopsys is a registered trademark of Synopsys, Inc. Other names included
1562306a36Sopenharmony_ci * in the SOFTWARE may be the trademarks of their respective owners.
1662306a36Sopenharmony_ci */
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#include <linux/phy.h>
1962306a36Sopenharmony_ci#include <linux/mdio.h>
2062306a36Sopenharmony_ci#include <linux/clk.h>
2162306a36Sopenharmony_ci#include <linux/bitrev.h>
2262306a36Sopenharmony_ci#include <linux/crc32.h>
2362306a36Sopenharmony_ci#include <linux/crc32poly.h>
2462306a36Sopenharmony_ci#include <linux/dcbnl.h>
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#include "dwc-xlgmac.h"
2762306a36Sopenharmony_ci#include "dwc-xlgmac-reg.h"
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_cistatic int xlgmac_tx_complete(struct xlgmac_dma_desc *dma_desc)
3062306a36Sopenharmony_ci{
3162306a36Sopenharmony_ci	return !XLGMAC_GET_REG_BITS_LE(dma_desc->desc3,
3262306a36Sopenharmony_ci				TX_NORMAL_DESC3_OWN_POS,
3362306a36Sopenharmony_ci				TX_NORMAL_DESC3_OWN_LEN);
3462306a36Sopenharmony_ci}
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cistatic int xlgmac_disable_rx_csum(struct xlgmac_pdata *pdata)
3762306a36Sopenharmony_ci{
3862306a36Sopenharmony_ci	u32 regval;
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_RCR);
4162306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_RCR_IPC_POS,
4262306a36Sopenharmony_ci				     MAC_RCR_IPC_LEN, 0);
4362306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_RCR);
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	return 0;
4662306a36Sopenharmony_ci}
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_cistatic int xlgmac_enable_rx_csum(struct xlgmac_pdata *pdata)
4962306a36Sopenharmony_ci{
5062306a36Sopenharmony_ci	u32 regval;
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_RCR);
5362306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_RCR_IPC_POS,
5462306a36Sopenharmony_ci				     MAC_RCR_IPC_LEN, 1);
5562306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_RCR);
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	return 0;
5862306a36Sopenharmony_ci}
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cistatic int xlgmac_set_mac_address(struct xlgmac_pdata *pdata, const u8 *addr)
6162306a36Sopenharmony_ci{
6262306a36Sopenharmony_ci	unsigned int mac_addr_hi, mac_addr_lo;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	mac_addr_hi = (addr[5] <<  8) | (addr[4] <<  0);
6562306a36Sopenharmony_ci	mac_addr_lo = (addr[3] << 24) | (addr[2] << 16) |
6662306a36Sopenharmony_ci		      (addr[1] <<  8) | (addr[0] <<  0);
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	writel(mac_addr_hi, pdata->mac_regs + MAC_MACA0HR);
6962306a36Sopenharmony_ci	writel(mac_addr_lo, pdata->mac_regs + MAC_MACA0LR);
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci	return 0;
7262306a36Sopenharmony_ci}
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_cistatic void xlgmac_set_mac_reg(struct xlgmac_pdata *pdata,
7562306a36Sopenharmony_ci			       struct netdev_hw_addr *ha,
7662306a36Sopenharmony_ci			       unsigned int *mac_reg)
7762306a36Sopenharmony_ci{
7862306a36Sopenharmony_ci	unsigned int mac_addr_hi, mac_addr_lo;
7962306a36Sopenharmony_ci	u8 *mac_addr;
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_ci	mac_addr_lo = 0;
8262306a36Sopenharmony_ci	mac_addr_hi = 0;
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci	if (ha) {
8562306a36Sopenharmony_ci		mac_addr = (u8 *)&mac_addr_lo;
8662306a36Sopenharmony_ci		mac_addr[0] = ha->addr[0];
8762306a36Sopenharmony_ci		mac_addr[1] = ha->addr[1];
8862306a36Sopenharmony_ci		mac_addr[2] = ha->addr[2];
8962306a36Sopenharmony_ci		mac_addr[3] = ha->addr[3];
9062306a36Sopenharmony_ci		mac_addr = (u8 *)&mac_addr_hi;
9162306a36Sopenharmony_ci		mac_addr[0] = ha->addr[4];
9262306a36Sopenharmony_ci		mac_addr[1] = ha->addr[5];
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci		netif_dbg(pdata, drv, pdata->netdev,
9562306a36Sopenharmony_ci			  "adding mac address %pM at %#x\n",
9662306a36Sopenharmony_ci			  ha->addr, *mac_reg);
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci		mac_addr_hi = XLGMAC_SET_REG_BITS(mac_addr_hi,
9962306a36Sopenharmony_ci						  MAC_MACA1HR_AE_POS,
10062306a36Sopenharmony_ci						MAC_MACA1HR_AE_LEN,
10162306a36Sopenharmony_ci						1);
10262306a36Sopenharmony_ci	}
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	writel(mac_addr_hi, pdata->mac_regs + *mac_reg);
10562306a36Sopenharmony_ci	*mac_reg += MAC_MACA_INC;
10662306a36Sopenharmony_ci	writel(mac_addr_lo, pdata->mac_regs + *mac_reg);
10762306a36Sopenharmony_ci	*mac_reg += MAC_MACA_INC;
10862306a36Sopenharmony_ci}
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_cistatic int xlgmac_enable_rx_vlan_stripping(struct xlgmac_pdata *pdata)
11162306a36Sopenharmony_ci{
11262306a36Sopenharmony_ci	u32 regval;
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_VLANTR);
11562306a36Sopenharmony_ci	/* Put the VLAN tag in the Rx descriptor */
11662306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_VLANTR_EVLRXS_POS,
11762306a36Sopenharmony_ci				     MAC_VLANTR_EVLRXS_LEN, 1);
11862306a36Sopenharmony_ci	/* Don't check the VLAN type */
11962306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_VLANTR_DOVLTC_POS,
12062306a36Sopenharmony_ci				     MAC_VLANTR_DOVLTC_LEN, 1);
12162306a36Sopenharmony_ci	/* Check only C-TAG (0x8100) packets */
12262306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_VLANTR_ERSVLM_POS,
12362306a36Sopenharmony_ci				     MAC_VLANTR_ERSVLM_LEN, 0);
12462306a36Sopenharmony_ci	/* Don't consider an S-TAG (0x88A8) packet as a VLAN packet */
12562306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_VLANTR_ESVL_POS,
12662306a36Sopenharmony_ci				     MAC_VLANTR_ESVL_LEN, 0);
12762306a36Sopenharmony_ci	/* Enable VLAN tag stripping */
12862306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_VLANTR_EVLS_POS,
12962306a36Sopenharmony_ci				     MAC_VLANTR_EVLS_LEN, 0x3);
13062306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_VLANTR);
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ci	return 0;
13362306a36Sopenharmony_ci}
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_cistatic int xlgmac_disable_rx_vlan_stripping(struct xlgmac_pdata *pdata)
13662306a36Sopenharmony_ci{
13762306a36Sopenharmony_ci	u32 regval;
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_VLANTR);
14062306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_VLANTR_EVLS_POS,
14162306a36Sopenharmony_ci				     MAC_VLANTR_EVLS_LEN, 0);
14262306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_VLANTR);
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci	return 0;
14562306a36Sopenharmony_ci}
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_cistatic int xlgmac_enable_rx_vlan_filtering(struct xlgmac_pdata *pdata)
14862306a36Sopenharmony_ci{
14962306a36Sopenharmony_ci	u32 regval;
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_PFR);
15262306a36Sopenharmony_ci	/* Enable VLAN filtering */
15362306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_PFR_VTFE_POS,
15462306a36Sopenharmony_ci				     MAC_PFR_VTFE_LEN, 1);
15562306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_PFR);
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_VLANTR);
15862306a36Sopenharmony_ci	/* Enable VLAN Hash Table filtering */
15962306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_VLANTR_VTHM_POS,
16062306a36Sopenharmony_ci				     MAC_VLANTR_VTHM_LEN, 1);
16162306a36Sopenharmony_ci	/* Disable VLAN tag inverse matching */
16262306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_VLANTR_VTIM_POS,
16362306a36Sopenharmony_ci				     MAC_VLANTR_VTIM_LEN, 0);
16462306a36Sopenharmony_ci	/* Only filter on the lower 12-bits of the VLAN tag */
16562306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_VLANTR_ETV_POS,
16662306a36Sopenharmony_ci				     MAC_VLANTR_ETV_LEN, 1);
16762306a36Sopenharmony_ci	/* In order for the VLAN Hash Table filtering to be effective,
16862306a36Sopenharmony_ci	 * the VLAN tag identifier in the VLAN Tag Register must not
16962306a36Sopenharmony_ci	 * be zero.  Set the VLAN tag identifier to "1" to enable the
17062306a36Sopenharmony_ci	 * VLAN Hash Table filtering.  This implies that a VLAN tag of
17162306a36Sopenharmony_ci	 * 1 will always pass filtering.
17262306a36Sopenharmony_ci	 */
17362306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_VLANTR_VL_POS,
17462306a36Sopenharmony_ci				     MAC_VLANTR_VL_LEN, 1);
17562306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_VLANTR);
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	return 0;
17862306a36Sopenharmony_ci}
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_cistatic int xlgmac_disable_rx_vlan_filtering(struct xlgmac_pdata *pdata)
18162306a36Sopenharmony_ci{
18262306a36Sopenharmony_ci	u32 regval;
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_PFR);
18562306a36Sopenharmony_ci	/* Disable VLAN filtering */
18662306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_PFR_VTFE_POS,
18762306a36Sopenharmony_ci				     MAC_PFR_VTFE_LEN, 0);
18862306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_PFR);
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_ci	return 0;
19162306a36Sopenharmony_ci}
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_cistatic u32 xlgmac_vid_crc32_le(__le16 vid_le)
19462306a36Sopenharmony_ci{
19562306a36Sopenharmony_ci	unsigned char *data = (unsigned char *)&vid_le;
19662306a36Sopenharmony_ci	unsigned char data_byte = 0;
19762306a36Sopenharmony_ci	u32 crc = ~0;
19862306a36Sopenharmony_ci	u32 temp = 0;
19962306a36Sopenharmony_ci	int i, bits;
20062306a36Sopenharmony_ci
20162306a36Sopenharmony_ci	bits = get_bitmask_order(VLAN_VID_MASK);
20262306a36Sopenharmony_ci	for (i = 0; i < bits; i++) {
20362306a36Sopenharmony_ci		if ((i % 8) == 0)
20462306a36Sopenharmony_ci			data_byte = data[i / 8];
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci		temp = ((crc & 1) ^ data_byte) & 1;
20762306a36Sopenharmony_ci		crc >>= 1;
20862306a36Sopenharmony_ci		data_byte >>= 1;
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ci		if (temp)
21162306a36Sopenharmony_ci			crc ^= CRC32_POLY_LE;
21262306a36Sopenharmony_ci	}
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	return crc;
21562306a36Sopenharmony_ci}
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_cistatic int xlgmac_update_vlan_hash_table(struct xlgmac_pdata *pdata)
21862306a36Sopenharmony_ci{
21962306a36Sopenharmony_ci	u16 vlan_hash_table = 0;
22062306a36Sopenharmony_ci	__le16 vid_le;
22162306a36Sopenharmony_ci	u32 regval;
22262306a36Sopenharmony_ci	u32 crc;
22362306a36Sopenharmony_ci	u16 vid;
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci	/* Generate the VLAN Hash Table value */
22662306a36Sopenharmony_ci	for_each_set_bit(vid, pdata->active_vlans, VLAN_N_VID) {
22762306a36Sopenharmony_ci		/* Get the CRC32 value of the VLAN ID */
22862306a36Sopenharmony_ci		vid_le = cpu_to_le16(vid);
22962306a36Sopenharmony_ci		crc = bitrev32(~xlgmac_vid_crc32_le(vid_le)) >> 28;
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci		vlan_hash_table |= (1 << crc);
23262306a36Sopenharmony_ci	}
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_VLANHTR);
23562306a36Sopenharmony_ci	/* Set the VLAN Hash Table filtering register */
23662306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_VLANHTR_VLHT_POS,
23762306a36Sopenharmony_ci				     MAC_VLANHTR_VLHT_LEN, vlan_hash_table);
23862306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_VLANHTR);
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	return 0;
24162306a36Sopenharmony_ci}
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_cistatic int xlgmac_set_promiscuous_mode(struct xlgmac_pdata *pdata,
24462306a36Sopenharmony_ci				       unsigned int enable)
24562306a36Sopenharmony_ci{
24662306a36Sopenharmony_ci	unsigned int val = enable ? 1 : 0;
24762306a36Sopenharmony_ci	u32 regval;
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	regval = XLGMAC_GET_REG_BITS(readl(pdata->mac_regs + MAC_PFR),
25062306a36Sopenharmony_ci				     MAC_PFR_PR_POS, MAC_PFR_PR_LEN);
25162306a36Sopenharmony_ci	if (regval == val)
25262306a36Sopenharmony_ci		return 0;
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci	netif_dbg(pdata, drv, pdata->netdev, "%s promiscuous mode\n",
25562306a36Sopenharmony_ci		  enable ? "entering" : "leaving");
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_PFR);
25862306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_PFR_PR_POS,
25962306a36Sopenharmony_ci				     MAC_PFR_PR_LEN, val);
26062306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_PFR);
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci	/* Hardware will still perform VLAN filtering in promiscuous mode */
26362306a36Sopenharmony_ci	if (enable) {
26462306a36Sopenharmony_ci		xlgmac_disable_rx_vlan_filtering(pdata);
26562306a36Sopenharmony_ci	} else {
26662306a36Sopenharmony_ci		if (pdata->netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
26762306a36Sopenharmony_ci			xlgmac_enable_rx_vlan_filtering(pdata);
26862306a36Sopenharmony_ci	}
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	return 0;
27162306a36Sopenharmony_ci}
27262306a36Sopenharmony_ci
27362306a36Sopenharmony_cistatic int xlgmac_set_all_multicast_mode(struct xlgmac_pdata *pdata,
27462306a36Sopenharmony_ci					 unsigned int enable)
27562306a36Sopenharmony_ci{
27662306a36Sopenharmony_ci	unsigned int val = enable ? 1 : 0;
27762306a36Sopenharmony_ci	u32 regval;
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci	regval = XLGMAC_GET_REG_BITS(readl(pdata->mac_regs + MAC_PFR),
28062306a36Sopenharmony_ci				     MAC_PFR_PM_POS, MAC_PFR_PM_LEN);
28162306a36Sopenharmony_ci	if (regval == val)
28262306a36Sopenharmony_ci		return 0;
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	netif_dbg(pdata, drv, pdata->netdev, "%s allmulti mode\n",
28562306a36Sopenharmony_ci		  enable ? "entering" : "leaving");
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_PFR);
28862306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_PFR_PM_POS,
28962306a36Sopenharmony_ci				     MAC_PFR_PM_LEN, val);
29062306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_PFR);
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci	return 0;
29362306a36Sopenharmony_ci}
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_cistatic void xlgmac_set_mac_addn_addrs(struct xlgmac_pdata *pdata)
29662306a36Sopenharmony_ci{
29762306a36Sopenharmony_ci	struct net_device *netdev = pdata->netdev;
29862306a36Sopenharmony_ci	struct netdev_hw_addr *ha;
29962306a36Sopenharmony_ci	unsigned int addn_macs;
30062306a36Sopenharmony_ci	unsigned int mac_reg;
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	mac_reg = MAC_MACA1HR;
30362306a36Sopenharmony_ci	addn_macs = pdata->hw_feat.addn_mac;
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	if (netdev_uc_count(netdev) > addn_macs) {
30662306a36Sopenharmony_ci		xlgmac_set_promiscuous_mode(pdata, 1);
30762306a36Sopenharmony_ci	} else {
30862306a36Sopenharmony_ci		netdev_for_each_uc_addr(ha, netdev) {
30962306a36Sopenharmony_ci			xlgmac_set_mac_reg(pdata, ha, &mac_reg);
31062306a36Sopenharmony_ci			addn_macs--;
31162306a36Sopenharmony_ci		}
31262306a36Sopenharmony_ci
31362306a36Sopenharmony_ci		if (netdev_mc_count(netdev) > addn_macs) {
31462306a36Sopenharmony_ci			xlgmac_set_all_multicast_mode(pdata, 1);
31562306a36Sopenharmony_ci		} else {
31662306a36Sopenharmony_ci			netdev_for_each_mc_addr(ha, netdev) {
31762306a36Sopenharmony_ci				xlgmac_set_mac_reg(pdata, ha, &mac_reg);
31862306a36Sopenharmony_ci				addn_macs--;
31962306a36Sopenharmony_ci			}
32062306a36Sopenharmony_ci		}
32162306a36Sopenharmony_ci	}
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	/* Clear remaining additional MAC address entries */
32462306a36Sopenharmony_ci	while (addn_macs--)
32562306a36Sopenharmony_ci		xlgmac_set_mac_reg(pdata, NULL, &mac_reg);
32662306a36Sopenharmony_ci}
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_cistatic void xlgmac_set_mac_hash_table(struct xlgmac_pdata *pdata)
32962306a36Sopenharmony_ci{
33062306a36Sopenharmony_ci	unsigned int hash_table_shift, hash_table_count;
33162306a36Sopenharmony_ci	u32 hash_table[XLGMAC_MAC_HASH_TABLE_SIZE];
33262306a36Sopenharmony_ci	struct net_device *netdev = pdata->netdev;
33362306a36Sopenharmony_ci	struct netdev_hw_addr *ha;
33462306a36Sopenharmony_ci	unsigned int hash_reg;
33562306a36Sopenharmony_ci	unsigned int i;
33662306a36Sopenharmony_ci	u32 crc;
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	hash_table_shift = 26 - (pdata->hw_feat.hash_table_size >> 7);
33962306a36Sopenharmony_ci	hash_table_count = pdata->hw_feat.hash_table_size / 32;
34062306a36Sopenharmony_ci	memset(hash_table, 0, sizeof(hash_table));
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ci	/* Build the MAC Hash Table register values */
34362306a36Sopenharmony_ci	netdev_for_each_uc_addr(ha, netdev) {
34462306a36Sopenharmony_ci		crc = bitrev32(~crc32_le(~0, ha->addr, ETH_ALEN));
34562306a36Sopenharmony_ci		crc >>= hash_table_shift;
34662306a36Sopenharmony_ci		hash_table[crc >> 5] |= (1 << (crc & 0x1f));
34762306a36Sopenharmony_ci	}
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_ci	netdev_for_each_mc_addr(ha, netdev) {
35062306a36Sopenharmony_ci		crc = bitrev32(~crc32_le(~0, ha->addr, ETH_ALEN));
35162306a36Sopenharmony_ci		crc >>= hash_table_shift;
35262306a36Sopenharmony_ci		hash_table[crc >> 5] |= (1 << (crc & 0x1f));
35362306a36Sopenharmony_ci	}
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	/* Set the MAC Hash Table registers */
35662306a36Sopenharmony_ci	hash_reg = MAC_HTR0;
35762306a36Sopenharmony_ci	for (i = 0; i < hash_table_count; i++) {
35862306a36Sopenharmony_ci		writel(hash_table[i], pdata->mac_regs + hash_reg);
35962306a36Sopenharmony_ci		hash_reg += MAC_HTR_INC;
36062306a36Sopenharmony_ci	}
36162306a36Sopenharmony_ci}
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_cistatic int xlgmac_add_mac_addresses(struct xlgmac_pdata *pdata)
36462306a36Sopenharmony_ci{
36562306a36Sopenharmony_ci	if (pdata->hw_feat.hash_table_size)
36662306a36Sopenharmony_ci		xlgmac_set_mac_hash_table(pdata);
36762306a36Sopenharmony_ci	else
36862306a36Sopenharmony_ci		xlgmac_set_mac_addn_addrs(pdata);
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci	return 0;
37162306a36Sopenharmony_ci}
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_cistatic void xlgmac_config_mac_address(struct xlgmac_pdata *pdata)
37462306a36Sopenharmony_ci{
37562306a36Sopenharmony_ci	u32 regval;
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	xlgmac_set_mac_address(pdata, pdata->netdev->dev_addr);
37862306a36Sopenharmony_ci
37962306a36Sopenharmony_ci	/* Filtering is done using perfect filtering and hash filtering */
38062306a36Sopenharmony_ci	if (pdata->hw_feat.hash_table_size) {
38162306a36Sopenharmony_ci		regval = readl(pdata->mac_regs + MAC_PFR);
38262306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, MAC_PFR_HPF_POS,
38362306a36Sopenharmony_ci					     MAC_PFR_HPF_LEN, 1);
38462306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, MAC_PFR_HUC_POS,
38562306a36Sopenharmony_ci					     MAC_PFR_HUC_LEN, 1);
38662306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, MAC_PFR_HMC_POS,
38762306a36Sopenharmony_ci					     MAC_PFR_HMC_LEN, 1);
38862306a36Sopenharmony_ci		writel(regval, pdata->mac_regs + MAC_PFR);
38962306a36Sopenharmony_ci	}
39062306a36Sopenharmony_ci}
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_cistatic void xlgmac_config_jumbo_enable(struct xlgmac_pdata *pdata)
39362306a36Sopenharmony_ci{
39462306a36Sopenharmony_ci	unsigned int val;
39562306a36Sopenharmony_ci	u32 regval;
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	val = (pdata->netdev->mtu > XLGMAC_STD_PACKET_MTU) ? 1 : 0;
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_RCR);
40062306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_RCR_JE_POS,
40162306a36Sopenharmony_ci				     MAC_RCR_JE_LEN, val);
40262306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_RCR);
40362306a36Sopenharmony_ci}
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_cistatic void xlgmac_config_checksum_offload(struct xlgmac_pdata *pdata)
40662306a36Sopenharmony_ci{
40762306a36Sopenharmony_ci	if (pdata->netdev->features & NETIF_F_RXCSUM)
40862306a36Sopenharmony_ci		xlgmac_enable_rx_csum(pdata);
40962306a36Sopenharmony_ci	else
41062306a36Sopenharmony_ci		xlgmac_disable_rx_csum(pdata);
41162306a36Sopenharmony_ci}
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_cistatic void xlgmac_config_vlan_support(struct xlgmac_pdata *pdata)
41462306a36Sopenharmony_ci{
41562306a36Sopenharmony_ci	u32 regval;
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_VLANIR);
41862306a36Sopenharmony_ci	/* Indicate that VLAN Tx CTAGs come from context descriptors */
41962306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_VLANIR_CSVL_POS,
42062306a36Sopenharmony_ci				     MAC_VLANIR_CSVL_LEN, 0);
42162306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_VLANIR_VLTI_POS,
42262306a36Sopenharmony_ci				     MAC_VLANIR_VLTI_LEN, 1);
42362306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_VLANIR);
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci	/* Set the current VLAN Hash Table register value */
42662306a36Sopenharmony_ci	xlgmac_update_vlan_hash_table(pdata);
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci	if (pdata->netdev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
42962306a36Sopenharmony_ci		xlgmac_enable_rx_vlan_filtering(pdata);
43062306a36Sopenharmony_ci	else
43162306a36Sopenharmony_ci		xlgmac_disable_rx_vlan_filtering(pdata);
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci	if (pdata->netdev->features & NETIF_F_HW_VLAN_CTAG_RX)
43462306a36Sopenharmony_ci		xlgmac_enable_rx_vlan_stripping(pdata);
43562306a36Sopenharmony_ci	else
43662306a36Sopenharmony_ci		xlgmac_disable_rx_vlan_stripping(pdata);
43762306a36Sopenharmony_ci}
43862306a36Sopenharmony_ci
43962306a36Sopenharmony_cistatic int xlgmac_config_rx_mode(struct xlgmac_pdata *pdata)
44062306a36Sopenharmony_ci{
44162306a36Sopenharmony_ci	struct net_device *netdev = pdata->netdev;
44262306a36Sopenharmony_ci	unsigned int pr_mode, am_mode;
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	pr_mode = ((netdev->flags & IFF_PROMISC) != 0);
44562306a36Sopenharmony_ci	am_mode = ((netdev->flags & IFF_ALLMULTI) != 0);
44662306a36Sopenharmony_ci
44762306a36Sopenharmony_ci	xlgmac_set_promiscuous_mode(pdata, pr_mode);
44862306a36Sopenharmony_ci	xlgmac_set_all_multicast_mode(pdata, am_mode);
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	xlgmac_add_mac_addresses(pdata);
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_ci	return 0;
45362306a36Sopenharmony_ci}
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_cistatic void xlgmac_prepare_tx_stop(struct xlgmac_pdata *pdata,
45662306a36Sopenharmony_ci				   struct xlgmac_channel *channel)
45762306a36Sopenharmony_ci{
45862306a36Sopenharmony_ci	unsigned int tx_dsr, tx_pos, tx_qidx;
45962306a36Sopenharmony_ci	unsigned long tx_timeout;
46062306a36Sopenharmony_ci	unsigned int tx_status;
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci	/* Calculate the status register to read and the position within */
46362306a36Sopenharmony_ci	if (channel->queue_index < DMA_DSRX_FIRST_QUEUE) {
46462306a36Sopenharmony_ci		tx_dsr = DMA_DSR0;
46562306a36Sopenharmony_ci		tx_pos = (channel->queue_index * DMA_DSR_Q_LEN) +
46662306a36Sopenharmony_ci			 DMA_DSR0_TPS_START;
46762306a36Sopenharmony_ci	} else {
46862306a36Sopenharmony_ci		tx_qidx = channel->queue_index - DMA_DSRX_FIRST_QUEUE;
46962306a36Sopenharmony_ci
47062306a36Sopenharmony_ci		tx_dsr = DMA_DSR1 + ((tx_qidx / DMA_DSRX_QPR) * DMA_DSRX_INC);
47162306a36Sopenharmony_ci		tx_pos = ((tx_qidx % DMA_DSRX_QPR) * DMA_DSR_Q_LEN) +
47262306a36Sopenharmony_ci			 DMA_DSRX_TPS_START;
47362306a36Sopenharmony_ci	}
47462306a36Sopenharmony_ci
47562306a36Sopenharmony_ci	/* The Tx engine cannot be stopped if it is actively processing
47662306a36Sopenharmony_ci	 * descriptors. Wait for the Tx engine to enter the stopped or
47762306a36Sopenharmony_ci	 * suspended state.  Don't wait forever though...
47862306a36Sopenharmony_ci	 */
47962306a36Sopenharmony_ci	tx_timeout = jiffies + (XLGMAC_DMA_STOP_TIMEOUT * HZ);
48062306a36Sopenharmony_ci	while (time_before(jiffies, tx_timeout)) {
48162306a36Sopenharmony_ci		tx_status = readl(pdata->mac_regs + tx_dsr);
48262306a36Sopenharmony_ci		tx_status = XLGMAC_GET_REG_BITS(tx_status, tx_pos,
48362306a36Sopenharmony_ci						DMA_DSR_TPS_LEN);
48462306a36Sopenharmony_ci		if ((tx_status == DMA_TPS_STOPPED) ||
48562306a36Sopenharmony_ci		    (tx_status == DMA_TPS_SUSPENDED))
48662306a36Sopenharmony_ci			break;
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci		usleep_range(500, 1000);
48962306a36Sopenharmony_ci	}
49062306a36Sopenharmony_ci
49162306a36Sopenharmony_ci	if (!time_before(jiffies, tx_timeout))
49262306a36Sopenharmony_ci		netdev_info(pdata->netdev,
49362306a36Sopenharmony_ci			    "timed out waiting for Tx DMA channel %u to stop\n",
49462306a36Sopenharmony_ci			    channel->queue_index);
49562306a36Sopenharmony_ci}
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_cistatic void xlgmac_enable_tx(struct xlgmac_pdata *pdata)
49862306a36Sopenharmony_ci{
49962306a36Sopenharmony_ci	struct xlgmac_channel *channel;
50062306a36Sopenharmony_ci	unsigned int i;
50162306a36Sopenharmony_ci	u32 regval;
50262306a36Sopenharmony_ci
50362306a36Sopenharmony_ci	/* Enable each Tx DMA channel */
50462306a36Sopenharmony_ci	channel = pdata->channel_head;
50562306a36Sopenharmony_ci	for (i = 0; i < pdata->channel_count; i++, channel++) {
50662306a36Sopenharmony_ci		if (!channel->tx_ring)
50762306a36Sopenharmony_ci			break;
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci		regval = readl(XLGMAC_DMA_REG(channel, DMA_CH_TCR));
51062306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, DMA_CH_TCR_ST_POS,
51162306a36Sopenharmony_ci					     DMA_CH_TCR_ST_LEN, 1);
51262306a36Sopenharmony_ci		writel(regval, XLGMAC_DMA_REG(channel, DMA_CH_TCR));
51362306a36Sopenharmony_ci	}
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	/* Enable each Tx queue */
51662306a36Sopenharmony_ci	for (i = 0; i < pdata->tx_q_count; i++) {
51762306a36Sopenharmony_ci		regval = readl(XLGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR));
51862306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, MTL_Q_TQOMR_TXQEN_POS,
51962306a36Sopenharmony_ci					     MTL_Q_TQOMR_TXQEN_LEN,
52062306a36Sopenharmony_ci					MTL_Q_ENABLED);
52162306a36Sopenharmony_ci		writel(regval, XLGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR));
52262306a36Sopenharmony_ci	}
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci	/* Enable MAC Tx */
52562306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_TCR);
52662306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_TCR_TE_POS,
52762306a36Sopenharmony_ci				     MAC_TCR_TE_LEN, 1);
52862306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_TCR);
52962306a36Sopenharmony_ci}
53062306a36Sopenharmony_ci
53162306a36Sopenharmony_cistatic void xlgmac_disable_tx(struct xlgmac_pdata *pdata)
53262306a36Sopenharmony_ci{
53362306a36Sopenharmony_ci	struct xlgmac_channel *channel;
53462306a36Sopenharmony_ci	unsigned int i;
53562306a36Sopenharmony_ci	u32 regval;
53662306a36Sopenharmony_ci
53762306a36Sopenharmony_ci	/* Prepare for Tx DMA channel stop */
53862306a36Sopenharmony_ci	channel = pdata->channel_head;
53962306a36Sopenharmony_ci	for (i = 0; i < pdata->channel_count; i++, channel++) {
54062306a36Sopenharmony_ci		if (!channel->tx_ring)
54162306a36Sopenharmony_ci			break;
54262306a36Sopenharmony_ci
54362306a36Sopenharmony_ci		xlgmac_prepare_tx_stop(pdata, channel);
54462306a36Sopenharmony_ci	}
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	/* Disable MAC Tx */
54762306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_TCR);
54862306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_TCR_TE_POS,
54962306a36Sopenharmony_ci				     MAC_TCR_TE_LEN, 0);
55062306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_TCR);
55162306a36Sopenharmony_ci
55262306a36Sopenharmony_ci	/* Disable each Tx queue */
55362306a36Sopenharmony_ci	for (i = 0; i < pdata->tx_q_count; i++) {
55462306a36Sopenharmony_ci		regval = readl(XLGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR));
55562306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, MTL_Q_TQOMR_TXQEN_POS,
55662306a36Sopenharmony_ci					     MTL_Q_TQOMR_TXQEN_LEN, 0);
55762306a36Sopenharmony_ci		writel(regval, XLGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR));
55862306a36Sopenharmony_ci	}
55962306a36Sopenharmony_ci
56062306a36Sopenharmony_ci	/* Disable each Tx DMA channel */
56162306a36Sopenharmony_ci	channel = pdata->channel_head;
56262306a36Sopenharmony_ci	for (i = 0; i < pdata->channel_count; i++, channel++) {
56362306a36Sopenharmony_ci		if (!channel->tx_ring)
56462306a36Sopenharmony_ci			break;
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci		regval = readl(XLGMAC_DMA_REG(channel, DMA_CH_TCR));
56762306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, DMA_CH_TCR_ST_POS,
56862306a36Sopenharmony_ci					     DMA_CH_TCR_ST_LEN, 0);
56962306a36Sopenharmony_ci		writel(regval, XLGMAC_DMA_REG(channel, DMA_CH_TCR));
57062306a36Sopenharmony_ci	}
57162306a36Sopenharmony_ci}
57262306a36Sopenharmony_ci
57362306a36Sopenharmony_cistatic void xlgmac_prepare_rx_stop(struct xlgmac_pdata *pdata,
57462306a36Sopenharmony_ci				   unsigned int queue)
57562306a36Sopenharmony_ci{
57662306a36Sopenharmony_ci	unsigned int rx_status, prxq, rxqsts;
57762306a36Sopenharmony_ci	unsigned long rx_timeout;
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci	/* The Rx engine cannot be stopped if it is actively processing
58062306a36Sopenharmony_ci	 * packets. Wait for the Rx queue to empty the Rx fifo.  Don't
58162306a36Sopenharmony_ci	 * wait forever though...
58262306a36Sopenharmony_ci	 */
58362306a36Sopenharmony_ci	rx_timeout = jiffies + (XLGMAC_DMA_STOP_TIMEOUT * HZ);
58462306a36Sopenharmony_ci	while (time_before(jiffies, rx_timeout)) {
58562306a36Sopenharmony_ci		rx_status = readl(XLGMAC_MTL_REG(pdata, queue, MTL_Q_RQDR));
58662306a36Sopenharmony_ci		prxq = XLGMAC_GET_REG_BITS(rx_status, MTL_Q_RQDR_PRXQ_POS,
58762306a36Sopenharmony_ci					   MTL_Q_RQDR_PRXQ_LEN);
58862306a36Sopenharmony_ci		rxqsts = XLGMAC_GET_REG_BITS(rx_status, MTL_Q_RQDR_RXQSTS_POS,
58962306a36Sopenharmony_ci					     MTL_Q_RQDR_RXQSTS_LEN);
59062306a36Sopenharmony_ci		if ((prxq == 0) && (rxqsts == 0))
59162306a36Sopenharmony_ci			break;
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_ci		usleep_range(500, 1000);
59462306a36Sopenharmony_ci	}
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_ci	if (!time_before(jiffies, rx_timeout))
59762306a36Sopenharmony_ci		netdev_info(pdata->netdev,
59862306a36Sopenharmony_ci			    "timed out waiting for Rx queue %u to empty\n",
59962306a36Sopenharmony_ci			    queue);
60062306a36Sopenharmony_ci}
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_cistatic void xlgmac_enable_rx(struct xlgmac_pdata *pdata)
60362306a36Sopenharmony_ci{
60462306a36Sopenharmony_ci	struct xlgmac_channel *channel;
60562306a36Sopenharmony_ci	unsigned int regval, i;
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_ci	/* Enable each Rx DMA channel */
60862306a36Sopenharmony_ci	channel = pdata->channel_head;
60962306a36Sopenharmony_ci	for (i = 0; i < pdata->channel_count; i++, channel++) {
61062306a36Sopenharmony_ci		if (!channel->rx_ring)
61162306a36Sopenharmony_ci			break;
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci		regval = readl(XLGMAC_DMA_REG(channel, DMA_CH_RCR));
61462306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, DMA_CH_RCR_SR_POS,
61562306a36Sopenharmony_ci					     DMA_CH_RCR_SR_LEN, 1);
61662306a36Sopenharmony_ci		writel(regval, XLGMAC_DMA_REG(channel, DMA_CH_RCR));
61762306a36Sopenharmony_ci	}
61862306a36Sopenharmony_ci
61962306a36Sopenharmony_ci	/* Enable each Rx queue */
62062306a36Sopenharmony_ci	regval = 0;
62162306a36Sopenharmony_ci	for (i = 0; i < pdata->rx_q_count; i++)
62262306a36Sopenharmony_ci		regval |= (0x02 << (i << 1));
62362306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_RQC0R);
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ci	/* Enable MAC Rx */
62662306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_RCR);
62762306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_RCR_DCRCC_POS,
62862306a36Sopenharmony_ci				     MAC_RCR_DCRCC_LEN, 1);
62962306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_RCR_CST_POS,
63062306a36Sopenharmony_ci				     MAC_RCR_CST_LEN, 1);
63162306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_RCR_ACS_POS,
63262306a36Sopenharmony_ci				     MAC_RCR_ACS_LEN, 1);
63362306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_RCR_RE_POS,
63462306a36Sopenharmony_ci				     MAC_RCR_RE_LEN, 1);
63562306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_RCR);
63662306a36Sopenharmony_ci}
63762306a36Sopenharmony_ci
63862306a36Sopenharmony_cistatic void xlgmac_disable_rx(struct xlgmac_pdata *pdata)
63962306a36Sopenharmony_ci{
64062306a36Sopenharmony_ci	struct xlgmac_channel *channel;
64162306a36Sopenharmony_ci	unsigned int i;
64262306a36Sopenharmony_ci	u32 regval;
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	/* Disable MAC Rx */
64562306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_RCR);
64662306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_RCR_DCRCC_POS,
64762306a36Sopenharmony_ci				     MAC_RCR_DCRCC_LEN, 0);
64862306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_RCR_CST_POS,
64962306a36Sopenharmony_ci				     MAC_RCR_CST_LEN, 0);
65062306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_RCR_ACS_POS,
65162306a36Sopenharmony_ci				     MAC_RCR_ACS_LEN, 0);
65262306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_RCR_RE_POS,
65362306a36Sopenharmony_ci				     MAC_RCR_RE_LEN, 0);
65462306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_RCR);
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci	/* Prepare for Rx DMA channel stop */
65762306a36Sopenharmony_ci	for (i = 0; i < pdata->rx_q_count; i++)
65862306a36Sopenharmony_ci		xlgmac_prepare_rx_stop(pdata, i);
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_ci	/* Disable each Rx queue */
66162306a36Sopenharmony_ci	writel(0, pdata->mac_regs + MAC_RQC0R);
66262306a36Sopenharmony_ci
66362306a36Sopenharmony_ci	/* Disable each Rx DMA channel */
66462306a36Sopenharmony_ci	channel = pdata->channel_head;
66562306a36Sopenharmony_ci	for (i = 0; i < pdata->channel_count; i++, channel++) {
66662306a36Sopenharmony_ci		if (!channel->rx_ring)
66762306a36Sopenharmony_ci			break;
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci		regval = readl(XLGMAC_DMA_REG(channel, DMA_CH_RCR));
67062306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, DMA_CH_RCR_SR_POS,
67162306a36Sopenharmony_ci					     DMA_CH_RCR_SR_LEN, 0);
67262306a36Sopenharmony_ci		writel(regval, XLGMAC_DMA_REG(channel, DMA_CH_RCR));
67362306a36Sopenharmony_ci	}
67462306a36Sopenharmony_ci}
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_cistatic void xlgmac_tx_start_xmit(struct xlgmac_channel *channel,
67762306a36Sopenharmony_ci				 struct xlgmac_ring *ring)
67862306a36Sopenharmony_ci{
67962306a36Sopenharmony_ci	struct xlgmac_pdata *pdata = channel->pdata;
68062306a36Sopenharmony_ci	struct xlgmac_desc_data *desc_data;
68162306a36Sopenharmony_ci
68262306a36Sopenharmony_ci	/* Make sure everything is written before the register write */
68362306a36Sopenharmony_ci	wmb();
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ci	/* Issue a poll command to Tx DMA by writing address
68662306a36Sopenharmony_ci	 * of next immediate free descriptor
68762306a36Sopenharmony_ci	 */
68862306a36Sopenharmony_ci	desc_data = XLGMAC_GET_DESC_DATA(ring, ring->cur);
68962306a36Sopenharmony_ci	writel(lower_32_bits(desc_data->dma_desc_addr),
69062306a36Sopenharmony_ci	       XLGMAC_DMA_REG(channel, DMA_CH_TDTR_LO));
69162306a36Sopenharmony_ci
69262306a36Sopenharmony_ci	/* Start the Tx timer */
69362306a36Sopenharmony_ci	if (pdata->tx_usecs && !channel->tx_timer_active) {
69462306a36Sopenharmony_ci		channel->tx_timer_active = 1;
69562306a36Sopenharmony_ci		mod_timer(&channel->tx_timer,
69662306a36Sopenharmony_ci			  jiffies + usecs_to_jiffies(pdata->tx_usecs));
69762306a36Sopenharmony_ci	}
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_ci	ring->tx.xmit_more = 0;
70062306a36Sopenharmony_ci}
70162306a36Sopenharmony_ci
70262306a36Sopenharmony_cistatic void xlgmac_dev_xmit(struct xlgmac_channel *channel)
70362306a36Sopenharmony_ci{
70462306a36Sopenharmony_ci	struct xlgmac_pdata *pdata = channel->pdata;
70562306a36Sopenharmony_ci	struct xlgmac_ring *ring = channel->tx_ring;
70662306a36Sopenharmony_ci	unsigned int tso_context, vlan_context;
70762306a36Sopenharmony_ci	struct xlgmac_desc_data *desc_data;
70862306a36Sopenharmony_ci	struct xlgmac_dma_desc *dma_desc;
70962306a36Sopenharmony_ci	struct xlgmac_pkt_info *pkt_info;
71062306a36Sopenharmony_ci	unsigned int csum, tso, vlan;
71162306a36Sopenharmony_ci	int start_index = ring->cur;
71262306a36Sopenharmony_ci	int cur_index = ring->cur;
71362306a36Sopenharmony_ci	unsigned int tx_set_ic;
71462306a36Sopenharmony_ci	int i;
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_ci	pkt_info = &ring->pkt_info;
71762306a36Sopenharmony_ci	csum = XLGMAC_GET_REG_BITS(pkt_info->attributes,
71862306a36Sopenharmony_ci				   TX_PACKET_ATTRIBUTES_CSUM_ENABLE_POS,
71962306a36Sopenharmony_ci				TX_PACKET_ATTRIBUTES_CSUM_ENABLE_LEN);
72062306a36Sopenharmony_ci	tso = XLGMAC_GET_REG_BITS(pkt_info->attributes,
72162306a36Sopenharmony_ci				  TX_PACKET_ATTRIBUTES_TSO_ENABLE_POS,
72262306a36Sopenharmony_ci				TX_PACKET_ATTRIBUTES_TSO_ENABLE_LEN);
72362306a36Sopenharmony_ci	vlan = XLGMAC_GET_REG_BITS(pkt_info->attributes,
72462306a36Sopenharmony_ci				   TX_PACKET_ATTRIBUTES_VLAN_CTAG_POS,
72562306a36Sopenharmony_ci				TX_PACKET_ATTRIBUTES_VLAN_CTAG_LEN);
72662306a36Sopenharmony_ci
72762306a36Sopenharmony_ci	if (tso && (pkt_info->mss != ring->tx.cur_mss))
72862306a36Sopenharmony_ci		tso_context = 1;
72962306a36Sopenharmony_ci	else
73062306a36Sopenharmony_ci		tso_context = 0;
73162306a36Sopenharmony_ci
73262306a36Sopenharmony_ci	if (vlan && (pkt_info->vlan_ctag != ring->tx.cur_vlan_ctag))
73362306a36Sopenharmony_ci		vlan_context = 1;
73462306a36Sopenharmony_ci	else
73562306a36Sopenharmony_ci		vlan_context = 0;
73662306a36Sopenharmony_ci
73762306a36Sopenharmony_ci	/* Determine if an interrupt should be generated for this Tx:
73862306a36Sopenharmony_ci	 *   Interrupt:
73962306a36Sopenharmony_ci	 *     - Tx frame count exceeds the frame count setting
74062306a36Sopenharmony_ci	 *     - Addition of Tx frame count to the frame count since the
74162306a36Sopenharmony_ci	 *       last interrupt was set exceeds the frame count setting
74262306a36Sopenharmony_ci	 *   No interrupt:
74362306a36Sopenharmony_ci	 *     - No frame count setting specified (ethtool -C ethX tx-frames 0)
74462306a36Sopenharmony_ci	 *     - Addition of Tx frame count to the frame count since the
74562306a36Sopenharmony_ci	 *       last interrupt was set does not exceed the frame count setting
74662306a36Sopenharmony_ci	 */
74762306a36Sopenharmony_ci	ring->coalesce_count += pkt_info->tx_packets;
74862306a36Sopenharmony_ci	if (!pdata->tx_frames)
74962306a36Sopenharmony_ci		tx_set_ic = 0;
75062306a36Sopenharmony_ci	else if (pkt_info->tx_packets > pdata->tx_frames)
75162306a36Sopenharmony_ci		tx_set_ic = 1;
75262306a36Sopenharmony_ci	else if ((ring->coalesce_count % pdata->tx_frames) <
75362306a36Sopenharmony_ci		 pkt_info->tx_packets)
75462306a36Sopenharmony_ci		tx_set_ic = 1;
75562306a36Sopenharmony_ci	else
75662306a36Sopenharmony_ci		tx_set_ic = 0;
75762306a36Sopenharmony_ci
75862306a36Sopenharmony_ci	desc_data = XLGMAC_GET_DESC_DATA(ring, cur_index);
75962306a36Sopenharmony_ci	dma_desc = desc_data->dma_desc;
76062306a36Sopenharmony_ci
76162306a36Sopenharmony_ci	/* Create a context descriptor if this is a TSO pkt_info */
76262306a36Sopenharmony_ci	if (tso_context || vlan_context) {
76362306a36Sopenharmony_ci		if (tso_context) {
76462306a36Sopenharmony_ci			netif_dbg(pdata, tx_queued, pdata->netdev,
76562306a36Sopenharmony_ci				  "TSO context descriptor, mss=%u\n",
76662306a36Sopenharmony_ci				  pkt_info->mss);
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_ci			/* Set the MSS size */
76962306a36Sopenharmony_ci			dma_desc->desc2 = XLGMAC_SET_REG_BITS_LE(
77062306a36Sopenharmony_ci						dma_desc->desc2,
77162306a36Sopenharmony_ci						TX_CONTEXT_DESC2_MSS_POS,
77262306a36Sopenharmony_ci						TX_CONTEXT_DESC2_MSS_LEN,
77362306a36Sopenharmony_ci						pkt_info->mss);
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_ci			/* Mark it as a CONTEXT descriptor */
77662306a36Sopenharmony_ci			dma_desc->desc3 = XLGMAC_SET_REG_BITS_LE(
77762306a36Sopenharmony_ci						dma_desc->desc3,
77862306a36Sopenharmony_ci						TX_CONTEXT_DESC3_CTXT_POS,
77962306a36Sopenharmony_ci						TX_CONTEXT_DESC3_CTXT_LEN,
78062306a36Sopenharmony_ci						1);
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci			/* Indicate this descriptor contains the MSS */
78362306a36Sopenharmony_ci			dma_desc->desc3 = XLGMAC_SET_REG_BITS_LE(
78462306a36Sopenharmony_ci						dma_desc->desc3,
78562306a36Sopenharmony_ci						TX_CONTEXT_DESC3_TCMSSV_POS,
78662306a36Sopenharmony_ci						TX_CONTEXT_DESC3_TCMSSV_LEN,
78762306a36Sopenharmony_ci						1);
78862306a36Sopenharmony_ci
78962306a36Sopenharmony_ci			ring->tx.cur_mss = pkt_info->mss;
79062306a36Sopenharmony_ci		}
79162306a36Sopenharmony_ci
79262306a36Sopenharmony_ci		if (vlan_context) {
79362306a36Sopenharmony_ci			netif_dbg(pdata, tx_queued, pdata->netdev,
79462306a36Sopenharmony_ci				  "VLAN context descriptor, ctag=%u\n",
79562306a36Sopenharmony_ci				  pkt_info->vlan_ctag);
79662306a36Sopenharmony_ci
79762306a36Sopenharmony_ci			/* Mark it as a CONTEXT descriptor */
79862306a36Sopenharmony_ci			dma_desc->desc3 = XLGMAC_SET_REG_BITS_LE(
79962306a36Sopenharmony_ci						dma_desc->desc3,
80062306a36Sopenharmony_ci						TX_CONTEXT_DESC3_CTXT_POS,
80162306a36Sopenharmony_ci						TX_CONTEXT_DESC3_CTXT_LEN,
80262306a36Sopenharmony_ci						1);
80362306a36Sopenharmony_ci
80462306a36Sopenharmony_ci			/* Set the VLAN tag */
80562306a36Sopenharmony_ci			dma_desc->desc3 = XLGMAC_SET_REG_BITS_LE(
80662306a36Sopenharmony_ci						dma_desc->desc3,
80762306a36Sopenharmony_ci						TX_CONTEXT_DESC3_VT_POS,
80862306a36Sopenharmony_ci						TX_CONTEXT_DESC3_VT_LEN,
80962306a36Sopenharmony_ci						pkt_info->vlan_ctag);
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ci			/* Indicate this descriptor contains the VLAN tag */
81262306a36Sopenharmony_ci			dma_desc->desc3 = XLGMAC_SET_REG_BITS_LE(
81362306a36Sopenharmony_ci						dma_desc->desc3,
81462306a36Sopenharmony_ci						TX_CONTEXT_DESC3_VLTV_POS,
81562306a36Sopenharmony_ci						TX_CONTEXT_DESC3_VLTV_LEN,
81662306a36Sopenharmony_ci						1);
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_ci			ring->tx.cur_vlan_ctag = pkt_info->vlan_ctag;
81962306a36Sopenharmony_ci		}
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_ci		cur_index++;
82262306a36Sopenharmony_ci		desc_data = XLGMAC_GET_DESC_DATA(ring, cur_index);
82362306a36Sopenharmony_ci		dma_desc = desc_data->dma_desc;
82462306a36Sopenharmony_ci	}
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ci	/* Update buffer address (for TSO this is the header) */
82762306a36Sopenharmony_ci	dma_desc->desc0 =  cpu_to_le32(lower_32_bits(desc_data->skb_dma));
82862306a36Sopenharmony_ci	dma_desc->desc1 =  cpu_to_le32(upper_32_bits(desc_data->skb_dma));
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ci	/* Update the buffer length */
83162306a36Sopenharmony_ci	dma_desc->desc2 = XLGMAC_SET_REG_BITS_LE(
83262306a36Sopenharmony_ci				dma_desc->desc2,
83362306a36Sopenharmony_ci				TX_NORMAL_DESC2_HL_B1L_POS,
83462306a36Sopenharmony_ci				TX_NORMAL_DESC2_HL_B1L_LEN,
83562306a36Sopenharmony_ci				desc_data->skb_dma_len);
83662306a36Sopenharmony_ci
83762306a36Sopenharmony_ci	/* VLAN tag insertion check */
83862306a36Sopenharmony_ci	if (vlan) {
83962306a36Sopenharmony_ci		dma_desc->desc2 = XLGMAC_SET_REG_BITS_LE(
84062306a36Sopenharmony_ci					dma_desc->desc2,
84162306a36Sopenharmony_ci					TX_NORMAL_DESC2_VTIR_POS,
84262306a36Sopenharmony_ci					TX_NORMAL_DESC2_VTIR_LEN,
84362306a36Sopenharmony_ci					TX_NORMAL_DESC2_VLAN_INSERT);
84462306a36Sopenharmony_ci		pdata->stats.tx_vlan_packets++;
84562306a36Sopenharmony_ci	}
84662306a36Sopenharmony_ci
84762306a36Sopenharmony_ci	/* Timestamp enablement check */
84862306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(pkt_info->attributes,
84962306a36Sopenharmony_ci				TX_PACKET_ATTRIBUTES_PTP_POS,
85062306a36Sopenharmony_ci				TX_PACKET_ATTRIBUTES_PTP_LEN))
85162306a36Sopenharmony_ci		dma_desc->desc2 = XLGMAC_SET_REG_BITS_LE(
85262306a36Sopenharmony_ci					dma_desc->desc2,
85362306a36Sopenharmony_ci					TX_NORMAL_DESC2_TTSE_POS,
85462306a36Sopenharmony_ci					TX_NORMAL_DESC2_TTSE_LEN,
85562306a36Sopenharmony_ci					1);
85662306a36Sopenharmony_ci
85762306a36Sopenharmony_ci	/* Mark it as First Descriptor */
85862306a36Sopenharmony_ci	dma_desc->desc3 = XLGMAC_SET_REG_BITS_LE(
85962306a36Sopenharmony_ci				dma_desc->desc3,
86062306a36Sopenharmony_ci				TX_NORMAL_DESC3_FD_POS,
86162306a36Sopenharmony_ci				TX_NORMAL_DESC3_FD_LEN,
86262306a36Sopenharmony_ci				1);
86362306a36Sopenharmony_ci
86462306a36Sopenharmony_ci	/* Mark it as a NORMAL descriptor */
86562306a36Sopenharmony_ci	dma_desc->desc3 = XLGMAC_SET_REG_BITS_LE(
86662306a36Sopenharmony_ci				dma_desc->desc3,
86762306a36Sopenharmony_ci				TX_NORMAL_DESC3_CTXT_POS,
86862306a36Sopenharmony_ci				TX_NORMAL_DESC3_CTXT_LEN,
86962306a36Sopenharmony_ci				0);
87062306a36Sopenharmony_ci
87162306a36Sopenharmony_ci	/* Set OWN bit if not the first descriptor */
87262306a36Sopenharmony_ci	if (cur_index != start_index)
87362306a36Sopenharmony_ci		dma_desc->desc3 = XLGMAC_SET_REG_BITS_LE(
87462306a36Sopenharmony_ci					dma_desc->desc3,
87562306a36Sopenharmony_ci					TX_NORMAL_DESC3_OWN_POS,
87662306a36Sopenharmony_ci					TX_NORMAL_DESC3_OWN_LEN,
87762306a36Sopenharmony_ci					1);
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci	if (tso) {
88062306a36Sopenharmony_ci		/* Enable TSO */
88162306a36Sopenharmony_ci		dma_desc->desc3 = XLGMAC_SET_REG_BITS_LE(
88262306a36Sopenharmony_ci					dma_desc->desc3,
88362306a36Sopenharmony_ci					TX_NORMAL_DESC3_TSE_POS,
88462306a36Sopenharmony_ci					TX_NORMAL_DESC3_TSE_LEN, 1);
88562306a36Sopenharmony_ci		dma_desc->desc3 = XLGMAC_SET_REG_BITS_LE(
88662306a36Sopenharmony_ci					dma_desc->desc3,
88762306a36Sopenharmony_ci					TX_NORMAL_DESC3_TCPPL_POS,
88862306a36Sopenharmony_ci					TX_NORMAL_DESC3_TCPPL_LEN,
88962306a36Sopenharmony_ci					pkt_info->tcp_payload_len);
89062306a36Sopenharmony_ci		dma_desc->desc3 = XLGMAC_SET_REG_BITS_LE(
89162306a36Sopenharmony_ci					dma_desc->desc3,
89262306a36Sopenharmony_ci					TX_NORMAL_DESC3_TCPHDRLEN_POS,
89362306a36Sopenharmony_ci					TX_NORMAL_DESC3_TCPHDRLEN_LEN,
89462306a36Sopenharmony_ci					pkt_info->tcp_header_len / 4);
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_ci		pdata->stats.tx_tso_packets++;
89762306a36Sopenharmony_ci	} else {
89862306a36Sopenharmony_ci		/* Enable CRC and Pad Insertion */
89962306a36Sopenharmony_ci		dma_desc->desc3 = XLGMAC_SET_REG_BITS_LE(
90062306a36Sopenharmony_ci					dma_desc->desc3,
90162306a36Sopenharmony_ci					TX_NORMAL_DESC3_CPC_POS,
90262306a36Sopenharmony_ci					TX_NORMAL_DESC3_CPC_LEN, 0);
90362306a36Sopenharmony_ci
90462306a36Sopenharmony_ci		/* Enable HW CSUM */
90562306a36Sopenharmony_ci		if (csum)
90662306a36Sopenharmony_ci			dma_desc->desc3 = XLGMAC_SET_REG_BITS_LE(
90762306a36Sopenharmony_ci						dma_desc->desc3,
90862306a36Sopenharmony_ci						TX_NORMAL_DESC3_CIC_POS,
90962306a36Sopenharmony_ci						TX_NORMAL_DESC3_CIC_LEN,
91062306a36Sopenharmony_ci						0x3);
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci		/* Set the total length to be transmitted */
91362306a36Sopenharmony_ci		dma_desc->desc3 = XLGMAC_SET_REG_BITS_LE(
91462306a36Sopenharmony_ci					dma_desc->desc3,
91562306a36Sopenharmony_ci					TX_NORMAL_DESC3_FL_POS,
91662306a36Sopenharmony_ci					TX_NORMAL_DESC3_FL_LEN,
91762306a36Sopenharmony_ci					pkt_info->length);
91862306a36Sopenharmony_ci	}
91962306a36Sopenharmony_ci
92062306a36Sopenharmony_ci	for (i = cur_index - start_index + 1; i < pkt_info->desc_count; i++) {
92162306a36Sopenharmony_ci		cur_index++;
92262306a36Sopenharmony_ci		desc_data = XLGMAC_GET_DESC_DATA(ring, cur_index);
92362306a36Sopenharmony_ci		dma_desc = desc_data->dma_desc;
92462306a36Sopenharmony_ci
92562306a36Sopenharmony_ci		/* Update buffer address */
92662306a36Sopenharmony_ci		dma_desc->desc0 =
92762306a36Sopenharmony_ci			cpu_to_le32(lower_32_bits(desc_data->skb_dma));
92862306a36Sopenharmony_ci		dma_desc->desc1 =
92962306a36Sopenharmony_ci			cpu_to_le32(upper_32_bits(desc_data->skb_dma));
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_ci		/* Update the buffer length */
93262306a36Sopenharmony_ci		dma_desc->desc2 = XLGMAC_SET_REG_BITS_LE(
93362306a36Sopenharmony_ci					dma_desc->desc2,
93462306a36Sopenharmony_ci					TX_NORMAL_DESC2_HL_B1L_POS,
93562306a36Sopenharmony_ci					TX_NORMAL_DESC2_HL_B1L_LEN,
93662306a36Sopenharmony_ci					desc_data->skb_dma_len);
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_ci		/* Set OWN bit */
93962306a36Sopenharmony_ci		dma_desc->desc3 = XLGMAC_SET_REG_BITS_LE(
94062306a36Sopenharmony_ci					dma_desc->desc3,
94162306a36Sopenharmony_ci					TX_NORMAL_DESC3_OWN_POS,
94262306a36Sopenharmony_ci					TX_NORMAL_DESC3_OWN_LEN, 1);
94362306a36Sopenharmony_ci
94462306a36Sopenharmony_ci		/* Mark it as NORMAL descriptor */
94562306a36Sopenharmony_ci		dma_desc->desc3 = XLGMAC_SET_REG_BITS_LE(
94662306a36Sopenharmony_ci					dma_desc->desc3,
94762306a36Sopenharmony_ci					TX_NORMAL_DESC3_CTXT_POS,
94862306a36Sopenharmony_ci					TX_NORMAL_DESC3_CTXT_LEN, 0);
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_ci		/* Enable HW CSUM */
95162306a36Sopenharmony_ci		if (csum)
95262306a36Sopenharmony_ci			dma_desc->desc3 = XLGMAC_SET_REG_BITS_LE(
95362306a36Sopenharmony_ci						dma_desc->desc3,
95462306a36Sopenharmony_ci						TX_NORMAL_DESC3_CIC_POS,
95562306a36Sopenharmony_ci						TX_NORMAL_DESC3_CIC_LEN,
95662306a36Sopenharmony_ci						0x3);
95762306a36Sopenharmony_ci	}
95862306a36Sopenharmony_ci
95962306a36Sopenharmony_ci	/* Set LAST bit for the last descriptor */
96062306a36Sopenharmony_ci	dma_desc->desc3 = XLGMAC_SET_REG_BITS_LE(
96162306a36Sopenharmony_ci				dma_desc->desc3,
96262306a36Sopenharmony_ci				TX_NORMAL_DESC3_LD_POS,
96362306a36Sopenharmony_ci				TX_NORMAL_DESC3_LD_LEN, 1);
96462306a36Sopenharmony_ci
96562306a36Sopenharmony_ci	/* Set IC bit based on Tx coalescing settings */
96662306a36Sopenharmony_ci	if (tx_set_ic)
96762306a36Sopenharmony_ci		dma_desc->desc2 = XLGMAC_SET_REG_BITS_LE(
96862306a36Sopenharmony_ci					dma_desc->desc2,
96962306a36Sopenharmony_ci					TX_NORMAL_DESC2_IC_POS,
97062306a36Sopenharmony_ci					TX_NORMAL_DESC2_IC_LEN, 1);
97162306a36Sopenharmony_ci
97262306a36Sopenharmony_ci	/* Save the Tx info to report back during cleanup */
97362306a36Sopenharmony_ci	desc_data->tx.packets = pkt_info->tx_packets;
97462306a36Sopenharmony_ci	desc_data->tx.bytes = pkt_info->tx_bytes;
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_ci	/* In case the Tx DMA engine is running, make sure everything
97762306a36Sopenharmony_ci	 * is written to the descriptor(s) before setting the OWN bit
97862306a36Sopenharmony_ci	 * for the first descriptor
97962306a36Sopenharmony_ci	 */
98062306a36Sopenharmony_ci	dma_wmb();
98162306a36Sopenharmony_ci
98262306a36Sopenharmony_ci	/* Set OWN bit for the first descriptor */
98362306a36Sopenharmony_ci	desc_data = XLGMAC_GET_DESC_DATA(ring, start_index);
98462306a36Sopenharmony_ci	dma_desc = desc_data->dma_desc;
98562306a36Sopenharmony_ci	dma_desc->desc3 = XLGMAC_SET_REG_BITS_LE(
98662306a36Sopenharmony_ci				dma_desc->desc3,
98762306a36Sopenharmony_ci				TX_NORMAL_DESC3_OWN_POS,
98862306a36Sopenharmony_ci				TX_NORMAL_DESC3_OWN_LEN, 1);
98962306a36Sopenharmony_ci
99062306a36Sopenharmony_ci	if (netif_msg_tx_queued(pdata))
99162306a36Sopenharmony_ci		xlgmac_dump_tx_desc(pdata, ring, start_index,
99262306a36Sopenharmony_ci				    pkt_info->desc_count, 1);
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_ci	/* Make sure ownership is written to the descriptor */
99562306a36Sopenharmony_ci	smp_wmb();
99662306a36Sopenharmony_ci
99762306a36Sopenharmony_ci	ring->cur = cur_index + 1;
99862306a36Sopenharmony_ci	if (!netdev_xmit_more() ||
99962306a36Sopenharmony_ci	    netif_xmit_stopped(netdev_get_tx_queue(pdata->netdev,
100062306a36Sopenharmony_ci						   channel->queue_index)))
100162306a36Sopenharmony_ci		xlgmac_tx_start_xmit(channel, ring);
100262306a36Sopenharmony_ci	else
100362306a36Sopenharmony_ci		ring->tx.xmit_more = 1;
100462306a36Sopenharmony_ci
100562306a36Sopenharmony_ci	XLGMAC_PR("%s: descriptors %u to %u written\n",
100662306a36Sopenharmony_ci		  channel->name, start_index & (ring->dma_desc_count - 1),
100762306a36Sopenharmony_ci		  (ring->cur - 1) & (ring->dma_desc_count - 1));
100862306a36Sopenharmony_ci}
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_cistatic void xlgmac_get_rx_tstamp(struct xlgmac_pkt_info *pkt_info,
101162306a36Sopenharmony_ci				 struct xlgmac_dma_desc *dma_desc)
101262306a36Sopenharmony_ci{
101362306a36Sopenharmony_ci	u32 tsa, tsd;
101462306a36Sopenharmony_ci	u64 nsec;
101562306a36Sopenharmony_ci
101662306a36Sopenharmony_ci	tsa = XLGMAC_GET_REG_BITS_LE(dma_desc->desc3,
101762306a36Sopenharmony_ci				     RX_CONTEXT_DESC3_TSA_POS,
101862306a36Sopenharmony_ci				RX_CONTEXT_DESC3_TSA_LEN);
101962306a36Sopenharmony_ci	tsd = XLGMAC_GET_REG_BITS_LE(dma_desc->desc3,
102062306a36Sopenharmony_ci				     RX_CONTEXT_DESC3_TSD_POS,
102162306a36Sopenharmony_ci				RX_CONTEXT_DESC3_TSD_LEN);
102262306a36Sopenharmony_ci	if (tsa && !tsd) {
102362306a36Sopenharmony_ci		nsec = le32_to_cpu(dma_desc->desc1);
102462306a36Sopenharmony_ci		nsec <<= 32;
102562306a36Sopenharmony_ci		nsec |= le32_to_cpu(dma_desc->desc0);
102662306a36Sopenharmony_ci		if (nsec != 0xffffffffffffffffULL) {
102762306a36Sopenharmony_ci			pkt_info->rx_tstamp = nsec;
102862306a36Sopenharmony_ci			pkt_info->attributes = XLGMAC_SET_REG_BITS(
102962306a36Sopenharmony_ci					pkt_info->attributes,
103062306a36Sopenharmony_ci					RX_PACKET_ATTRIBUTES_RX_TSTAMP_POS,
103162306a36Sopenharmony_ci					RX_PACKET_ATTRIBUTES_RX_TSTAMP_LEN,
103262306a36Sopenharmony_ci					1);
103362306a36Sopenharmony_ci		}
103462306a36Sopenharmony_ci	}
103562306a36Sopenharmony_ci}
103662306a36Sopenharmony_ci
103762306a36Sopenharmony_cistatic void xlgmac_tx_desc_reset(struct xlgmac_desc_data *desc_data)
103862306a36Sopenharmony_ci{
103962306a36Sopenharmony_ci	struct xlgmac_dma_desc *dma_desc = desc_data->dma_desc;
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_ci	/* Reset the Tx descriptor
104262306a36Sopenharmony_ci	 *   Set buffer 1 (lo) address to zero
104362306a36Sopenharmony_ci	 *   Set buffer 1 (hi) address to zero
104462306a36Sopenharmony_ci	 *   Reset all other control bits (IC, TTSE, B2L & B1L)
104562306a36Sopenharmony_ci	 *   Reset all other control bits (OWN, CTXT, FD, LD, CPC, CIC, etc)
104662306a36Sopenharmony_ci	 */
104762306a36Sopenharmony_ci	dma_desc->desc0 = 0;
104862306a36Sopenharmony_ci	dma_desc->desc1 = 0;
104962306a36Sopenharmony_ci	dma_desc->desc2 = 0;
105062306a36Sopenharmony_ci	dma_desc->desc3 = 0;
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_ci	/* Make sure ownership is written to the descriptor */
105362306a36Sopenharmony_ci	dma_wmb();
105462306a36Sopenharmony_ci}
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_cistatic void xlgmac_tx_desc_init(struct xlgmac_channel *channel)
105762306a36Sopenharmony_ci{
105862306a36Sopenharmony_ci	struct xlgmac_ring *ring = channel->tx_ring;
105962306a36Sopenharmony_ci	struct xlgmac_desc_data *desc_data;
106062306a36Sopenharmony_ci	int start_index = ring->cur;
106162306a36Sopenharmony_ci	int i;
106262306a36Sopenharmony_ci
106362306a36Sopenharmony_ci	/* Initialze all descriptors */
106462306a36Sopenharmony_ci	for (i = 0; i < ring->dma_desc_count; i++) {
106562306a36Sopenharmony_ci		desc_data = XLGMAC_GET_DESC_DATA(ring, i);
106662306a36Sopenharmony_ci
106762306a36Sopenharmony_ci		/* Initialize Tx descriptor */
106862306a36Sopenharmony_ci		xlgmac_tx_desc_reset(desc_data);
106962306a36Sopenharmony_ci	}
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_ci	/* Update the total number of Tx descriptors */
107262306a36Sopenharmony_ci	writel(ring->dma_desc_count - 1, XLGMAC_DMA_REG(channel, DMA_CH_TDRLR));
107362306a36Sopenharmony_ci
107462306a36Sopenharmony_ci	/* Update the starting address of descriptor ring */
107562306a36Sopenharmony_ci	desc_data = XLGMAC_GET_DESC_DATA(ring, start_index);
107662306a36Sopenharmony_ci	writel(upper_32_bits(desc_data->dma_desc_addr),
107762306a36Sopenharmony_ci	       XLGMAC_DMA_REG(channel, DMA_CH_TDLR_HI));
107862306a36Sopenharmony_ci	writel(lower_32_bits(desc_data->dma_desc_addr),
107962306a36Sopenharmony_ci	       XLGMAC_DMA_REG(channel, DMA_CH_TDLR_LO));
108062306a36Sopenharmony_ci}
108162306a36Sopenharmony_ci
108262306a36Sopenharmony_cistatic void xlgmac_rx_desc_reset(struct xlgmac_pdata *pdata,
108362306a36Sopenharmony_ci				 struct xlgmac_desc_data *desc_data,
108462306a36Sopenharmony_ci				 unsigned int index)
108562306a36Sopenharmony_ci{
108662306a36Sopenharmony_ci	struct xlgmac_dma_desc *dma_desc = desc_data->dma_desc;
108762306a36Sopenharmony_ci	unsigned int rx_frames = pdata->rx_frames;
108862306a36Sopenharmony_ci	unsigned int rx_usecs = pdata->rx_usecs;
108962306a36Sopenharmony_ci	dma_addr_t hdr_dma, buf_dma;
109062306a36Sopenharmony_ci	unsigned int inte;
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_ci	if (!rx_usecs && !rx_frames) {
109362306a36Sopenharmony_ci		/* No coalescing, interrupt for every descriptor */
109462306a36Sopenharmony_ci		inte = 1;
109562306a36Sopenharmony_ci	} else {
109662306a36Sopenharmony_ci		/* Set interrupt based on Rx frame coalescing setting */
109762306a36Sopenharmony_ci		if (rx_frames && !((index + 1) % rx_frames))
109862306a36Sopenharmony_ci			inte = 1;
109962306a36Sopenharmony_ci		else
110062306a36Sopenharmony_ci			inte = 0;
110162306a36Sopenharmony_ci	}
110262306a36Sopenharmony_ci
110362306a36Sopenharmony_ci	/* Reset the Rx descriptor
110462306a36Sopenharmony_ci	 *   Set buffer 1 (lo) address to header dma address (lo)
110562306a36Sopenharmony_ci	 *   Set buffer 1 (hi) address to header dma address (hi)
110662306a36Sopenharmony_ci	 *   Set buffer 2 (lo) address to buffer dma address (lo)
110762306a36Sopenharmony_ci	 *   Set buffer 2 (hi) address to buffer dma address (hi) and
110862306a36Sopenharmony_ci	 *     set control bits OWN and INTE
110962306a36Sopenharmony_ci	 */
111062306a36Sopenharmony_ci	hdr_dma = desc_data->rx.hdr.dma_base + desc_data->rx.hdr.dma_off;
111162306a36Sopenharmony_ci	buf_dma = desc_data->rx.buf.dma_base + desc_data->rx.buf.dma_off;
111262306a36Sopenharmony_ci	dma_desc->desc0 = cpu_to_le32(lower_32_bits(hdr_dma));
111362306a36Sopenharmony_ci	dma_desc->desc1 = cpu_to_le32(upper_32_bits(hdr_dma));
111462306a36Sopenharmony_ci	dma_desc->desc2 = cpu_to_le32(lower_32_bits(buf_dma));
111562306a36Sopenharmony_ci	dma_desc->desc3 = cpu_to_le32(upper_32_bits(buf_dma));
111662306a36Sopenharmony_ci
111762306a36Sopenharmony_ci	dma_desc->desc3 = XLGMAC_SET_REG_BITS_LE(
111862306a36Sopenharmony_ci				dma_desc->desc3,
111962306a36Sopenharmony_ci				RX_NORMAL_DESC3_INTE_POS,
112062306a36Sopenharmony_ci				RX_NORMAL_DESC3_INTE_LEN,
112162306a36Sopenharmony_ci				inte);
112262306a36Sopenharmony_ci
112362306a36Sopenharmony_ci	/* Since the Rx DMA engine is likely running, make sure everything
112462306a36Sopenharmony_ci	 * is written to the descriptor(s) before setting the OWN bit
112562306a36Sopenharmony_ci	 * for the descriptor
112662306a36Sopenharmony_ci	 */
112762306a36Sopenharmony_ci	dma_wmb();
112862306a36Sopenharmony_ci
112962306a36Sopenharmony_ci	dma_desc->desc3 = XLGMAC_SET_REG_BITS_LE(
113062306a36Sopenharmony_ci				dma_desc->desc3,
113162306a36Sopenharmony_ci				RX_NORMAL_DESC3_OWN_POS,
113262306a36Sopenharmony_ci				RX_NORMAL_DESC3_OWN_LEN,
113362306a36Sopenharmony_ci				1);
113462306a36Sopenharmony_ci
113562306a36Sopenharmony_ci	/* Make sure ownership is written to the descriptor */
113662306a36Sopenharmony_ci	dma_wmb();
113762306a36Sopenharmony_ci}
113862306a36Sopenharmony_ci
113962306a36Sopenharmony_cistatic void xlgmac_rx_desc_init(struct xlgmac_channel *channel)
114062306a36Sopenharmony_ci{
114162306a36Sopenharmony_ci	struct xlgmac_pdata *pdata = channel->pdata;
114262306a36Sopenharmony_ci	struct xlgmac_ring *ring = channel->rx_ring;
114362306a36Sopenharmony_ci	unsigned int start_index = ring->cur;
114462306a36Sopenharmony_ci	struct xlgmac_desc_data *desc_data;
114562306a36Sopenharmony_ci	unsigned int i;
114662306a36Sopenharmony_ci
114762306a36Sopenharmony_ci	/* Initialize all descriptors */
114862306a36Sopenharmony_ci	for (i = 0; i < ring->dma_desc_count; i++) {
114962306a36Sopenharmony_ci		desc_data = XLGMAC_GET_DESC_DATA(ring, i);
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_ci		/* Initialize Rx descriptor */
115262306a36Sopenharmony_ci		xlgmac_rx_desc_reset(pdata, desc_data, i);
115362306a36Sopenharmony_ci	}
115462306a36Sopenharmony_ci
115562306a36Sopenharmony_ci	/* Update the total number of Rx descriptors */
115662306a36Sopenharmony_ci	writel(ring->dma_desc_count - 1, XLGMAC_DMA_REG(channel, DMA_CH_RDRLR));
115762306a36Sopenharmony_ci
115862306a36Sopenharmony_ci	/* Update the starting address of descriptor ring */
115962306a36Sopenharmony_ci	desc_data = XLGMAC_GET_DESC_DATA(ring, start_index);
116062306a36Sopenharmony_ci	writel(upper_32_bits(desc_data->dma_desc_addr),
116162306a36Sopenharmony_ci	       XLGMAC_DMA_REG(channel, DMA_CH_RDLR_HI));
116262306a36Sopenharmony_ci	writel(lower_32_bits(desc_data->dma_desc_addr),
116362306a36Sopenharmony_ci	       XLGMAC_DMA_REG(channel, DMA_CH_RDLR_LO));
116462306a36Sopenharmony_ci
116562306a36Sopenharmony_ci	/* Update the Rx Descriptor Tail Pointer */
116662306a36Sopenharmony_ci	desc_data = XLGMAC_GET_DESC_DATA(ring, start_index +
116762306a36Sopenharmony_ci					  ring->dma_desc_count - 1);
116862306a36Sopenharmony_ci	writel(lower_32_bits(desc_data->dma_desc_addr),
116962306a36Sopenharmony_ci	       XLGMAC_DMA_REG(channel, DMA_CH_RDTR_LO));
117062306a36Sopenharmony_ci}
117162306a36Sopenharmony_ci
117262306a36Sopenharmony_cistatic int xlgmac_is_context_desc(struct xlgmac_dma_desc *dma_desc)
117362306a36Sopenharmony_ci{
117462306a36Sopenharmony_ci	/* Rx and Tx share CTXT bit, so check TDES3.CTXT bit */
117562306a36Sopenharmony_ci	return XLGMAC_GET_REG_BITS_LE(dma_desc->desc3,
117662306a36Sopenharmony_ci				TX_NORMAL_DESC3_CTXT_POS,
117762306a36Sopenharmony_ci				TX_NORMAL_DESC3_CTXT_LEN);
117862306a36Sopenharmony_ci}
117962306a36Sopenharmony_ci
118062306a36Sopenharmony_cistatic int xlgmac_is_last_desc(struct xlgmac_dma_desc *dma_desc)
118162306a36Sopenharmony_ci{
118262306a36Sopenharmony_ci	/* Rx and Tx share LD bit, so check TDES3.LD bit */
118362306a36Sopenharmony_ci	return XLGMAC_GET_REG_BITS_LE(dma_desc->desc3,
118462306a36Sopenharmony_ci				TX_NORMAL_DESC3_LD_POS,
118562306a36Sopenharmony_ci				TX_NORMAL_DESC3_LD_LEN);
118662306a36Sopenharmony_ci}
118762306a36Sopenharmony_ci
118862306a36Sopenharmony_cistatic int xlgmac_disable_tx_flow_control(struct xlgmac_pdata *pdata)
118962306a36Sopenharmony_ci{
119062306a36Sopenharmony_ci	unsigned int max_q_count, q_count;
119162306a36Sopenharmony_ci	unsigned int reg, regval;
119262306a36Sopenharmony_ci	unsigned int i;
119362306a36Sopenharmony_ci
119462306a36Sopenharmony_ci	/* Clear MTL flow control */
119562306a36Sopenharmony_ci	for (i = 0; i < pdata->rx_q_count; i++) {
119662306a36Sopenharmony_ci		regval = readl(XLGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR));
119762306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, MTL_Q_RQOMR_EHFC_POS,
119862306a36Sopenharmony_ci					     MTL_Q_RQOMR_EHFC_LEN, 0);
119962306a36Sopenharmony_ci		writel(regval, XLGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR));
120062306a36Sopenharmony_ci	}
120162306a36Sopenharmony_ci
120262306a36Sopenharmony_ci	/* Clear MAC flow control */
120362306a36Sopenharmony_ci	max_q_count = XLGMAC_MAX_FLOW_CONTROL_QUEUES;
120462306a36Sopenharmony_ci	q_count = min_t(unsigned int, pdata->tx_q_count, max_q_count);
120562306a36Sopenharmony_ci	reg = MAC_Q0TFCR;
120662306a36Sopenharmony_ci	for (i = 0; i < q_count; i++) {
120762306a36Sopenharmony_ci		regval = readl(pdata->mac_regs + reg);
120862306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval,
120962306a36Sopenharmony_ci					     MAC_Q0TFCR_TFE_POS,
121062306a36Sopenharmony_ci					MAC_Q0TFCR_TFE_LEN,
121162306a36Sopenharmony_ci					0);
121262306a36Sopenharmony_ci		writel(regval, pdata->mac_regs + reg);
121362306a36Sopenharmony_ci
121462306a36Sopenharmony_ci		reg += MAC_QTFCR_INC;
121562306a36Sopenharmony_ci	}
121662306a36Sopenharmony_ci
121762306a36Sopenharmony_ci	return 0;
121862306a36Sopenharmony_ci}
121962306a36Sopenharmony_ci
122062306a36Sopenharmony_cistatic int xlgmac_enable_tx_flow_control(struct xlgmac_pdata *pdata)
122162306a36Sopenharmony_ci{
122262306a36Sopenharmony_ci	unsigned int max_q_count, q_count;
122362306a36Sopenharmony_ci	unsigned int reg, regval;
122462306a36Sopenharmony_ci	unsigned int i;
122562306a36Sopenharmony_ci
122662306a36Sopenharmony_ci	/* Set MTL flow control */
122762306a36Sopenharmony_ci	for (i = 0; i < pdata->rx_q_count; i++) {
122862306a36Sopenharmony_ci		regval = readl(XLGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR));
122962306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, MTL_Q_RQOMR_EHFC_POS,
123062306a36Sopenharmony_ci					     MTL_Q_RQOMR_EHFC_LEN, 1);
123162306a36Sopenharmony_ci		writel(regval, XLGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR));
123262306a36Sopenharmony_ci	}
123362306a36Sopenharmony_ci
123462306a36Sopenharmony_ci	/* Set MAC flow control */
123562306a36Sopenharmony_ci	max_q_count = XLGMAC_MAX_FLOW_CONTROL_QUEUES;
123662306a36Sopenharmony_ci	q_count = min_t(unsigned int, pdata->tx_q_count, max_q_count);
123762306a36Sopenharmony_ci	reg = MAC_Q0TFCR;
123862306a36Sopenharmony_ci	for (i = 0; i < q_count; i++) {
123962306a36Sopenharmony_ci		regval = readl(pdata->mac_regs + reg);
124062306a36Sopenharmony_ci
124162306a36Sopenharmony_ci		/* Enable transmit flow control */
124262306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, MAC_Q0TFCR_TFE_POS,
124362306a36Sopenharmony_ci					     MAC_Q0TFCR_TFE_LEN, 1);
124462306a36Sopenharmony_ci		/* Set pause time */
124562306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, MAC_Q0TFCR_PT_POS,
124662306a36Sopenharmony_ci					     MAC_Q0TFCR_PT_LEN, 0xffff);
124762306a36Sopenharmony_ci
124862306a36Sopenharmony_ci		writel(regval, pdata->mac_regs + reg);
124962306a36Sopenharmony_ci
125062306a36Sopenharmony_ci		reg += MAC_QTFCR_INC;
125162306a36Sopenharmony_ci	}
125262306a36Sopenharmony_ci
125362306a36Sopenharmony_ci	return 0;
125462306a36Sopenharmony_ci}
125562306a36Sopenharmony_ci
125662306a36Sopenharmony_cistatic int xlgmac_disable_rx_flow_control(struct xlgmac_pdata *pdata)
125762306a36Sopenharmony_ci{
125862306a36Sopenharmony_ci	u32 regval;
125962306a36Sopenharmony_ci
126062306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_RFCR);
126162306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_RFCR_RFE_POS,
126262306a36Sopenharmony_ci				     MAC_RFCR_RFE_LEN, 0);
126362306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_RFCR);
126462306a36Sopenharmony_ci
126562306a36Sopenharmony_ci	return 0;
126662306a36Sopenharmony_ci}
126762306a36Sopenharmony_ci
126862306a36Sopenharmony_cistatic int xlgmac_enable_rx_flow_control(struct xlgmac_pdata *pdata)
126962306a36Sopenharmony_ci{
127062306a36Sopenharmony_ci	u32 regval;
127162306a36Sopenharmony_ci
127262306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_RFCR);
127362306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_RFCR_RFE_POS,
127462306a36Sopenharmony_ci				     MAC_RFCR_RFE_LEN, 1);
127562306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_RFCR);
127662306a36Sopenharmony_ci
127762306a36Sopenharmony_ci	return 0;
127862306a36Sopenharmony_ci}
127962306a36Sopenharmony_ci
128062306a36Sopenharmony_cistatic int xlgmac_config_tx_flow_control(struct xlgmac_pdata *pdata)
128162306a36Sopenharmony_ci{
128262306a36Sopenharmony_ci	if (pdata->tx_pause)
128362306a36Sopenharmony_ci		xlgmac_enable_tx_flow_control(pdata);
128462306a36Sopenharmony_ci	else
128562306a36Sopenharmony_ci		xlgmac_disable_tx_flow_control(pdata);
128662306a36Sopenharmony_ci
128762306a36Sopenharmony_ci	return 0;
128862306a36Sopenharmony_ci}
128962306a36Sopenharmony_ci
129062306a36Sopenharmony_cistatic int xlgmac_config_rx_flow_control(struct xlgmac_pdata *pdata)
129162306a36Sopenharmony_ci{
129262306a36Sopenharmony_ci	if (pdata->rx_pause)
129362306a36Sopenharmony_ci		xlgmac_enable_rx_flow_control(pdata);
129462306a36Sopenharmony_ci	else
129562306a36Sopenharmony_ci		xlgmac_disable_rx_flow_control(pdata);
129662306a36Sopenharmony_ci
129762306a36Sopenharmony_ci	return 0;
129862306a36Sopenharmony_ci}
129962306a36Sopenharmony_ci
130062306a36Sopenharmony_cistatic int xlgmac_config_rx_coalesce(struct xlgmac_pdata *pdata)
130162306a36Sopenharmony_ci{
130262306a36Sopenharmony_ci	struct xlgmac_channel *channel;
130362306a36Sopenharmony_ci	unsigned int i;
130462306a36Sopenharmony_ci	u32 regval;
130562306a36Sopenharmony_ci
130662306a36Sopenharmony_ci	channel = pdata->channel_head;
130762306a36Sopenharmony_ci	for (i = 0; i < pdata->channel_count; i++, channel++) {
130862306a36Sopenharmony_ci		if (!channel->rx_ring)
130962306a36Sopenharmony_ci			break;
131062306a36Sopenharmony_ci
131162306a36Sopenharmony_ci		regval = readl(XLGMAC_DMA_REG(channel, DMA_CH_RIWT));
131262306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, DMA_CH_RIWT_RWT_POS,
131362306a36Sopenharmony_ci					     DMA_CH_RIWT_RWT_LEN,
131462306a36Sopenharmony_ci					     pdata->rx_riwt);
131562306a36Sopenharmony_ci		writel(regval, XLGMAC_DMA_REG(channel, DMA_CH_RIWT));
131662306a36Sopenharmony_ci	}
131762306a36Sopenharmony_ci
131862306a36Sopenharmony_ci	return 0;
131962306a36Sopenharmony_ci}
132062306a36Sopenharmony_ci
132162306a36Sopenharmony_cistatic void xlgmac_config_flow_control(struct xlgmac_pdata *pdata)
132262306a36Sopenharmony_ci{
132362306a36Sopenharmony_ci	xlgmac_config_tx_flow_control(pdata);
132462306a36Sopenharmony_ci	xlgmac_config_rx_flow_control(pdata);
132562306a36Sopenharmony_ci}
132662306a36Sopenharmony_ci
132762306a36Sopenharmony_cistatic void xlgmac_config_rx_fep_enable(struct xlgmac_pdata *pdata)
132862306a36Sopenharmony_ci{
132962306a36Sopenharmony_ci	unsigned int i;
133062306a36Sopenharmony_ci	u32 regval;
133162306a36Sopenharmony_ci
133262306a36Sopenharmony_ci	for (i = 0; i < pdata->rx_q_count; i++) {
133362306a36Sopenharmony_ci		regval = readl(XLGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR));
133462306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, MTL_Q_RQOMR_FEP_POS,
133562306a36Sopenharmony_ci					     MTL_Q_RQOMR_FEP_LEN, 1);
133662306a36Sopenharmony_ci		writel(regval, XLGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR));
133762306a36Sopenharmony_ci	}
133862306a36Sopenharmony_ci}
133962306a36Sopenharmony_ci
134062306a36Sopenharmony_cistatic void xlgmac_config_rx_fup_enable(struct xlgmac_pdata *pdata)
134162306a36Sopenharmony_ci{
134262306a36Sopenharmony_ci	unsigned int i;
134362306a36Sopenharmony_ci	u32 regval;
134462306a36Sopenharmony_ci
134562306a36Sopenharmony_ci	for (i = 0; i < pdata->rx_q_count; i++) {
134662306a36Sopenharmony_ci		regval = readl(XLGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR));
134762306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, MTL_Q_RQOMR_FUP_POS,
134862306a36Sopenharmony_ci					     MTL_Q_RQOMR_FUP_LEN, 1);
134962306a36Sopenharmony_ci		writel(regval, XLGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR));
135062306a36Sopenharmony_ci	}
135162306a36Sopenharmony_ci}
135262306a36Sopenharmony_ci
135362306a36Sopenharmony_cistatic int xlgmac_config_tx_coalesce(struct xlgmac_pdata *pdata)
135462306a36Sopenharmony_ci{
135562306a36Sopenharmony_ci	return 0;
135662306a36Sopenharmony_ci}
135762306a36Sopenharmony_ci
135862306a36Sopenharmony_cistatic void xlgmac_config_rx_buffer_size(struct xlgmac_pdata *pdata)
135962306a36Sopenharmony_ci{
136062306a36Sopenharmony_ci	struct xlgmac_channel *channel;
136162306a36Sopenharmony_ci	unsigned int i;
136262306a36Sopenharmony_ci	u32 regval;
136362306a36Sopenharmony_ci
136462306a36Sopenharmony_ci	channel = pdata->channel_head;
136562306a36Sopenharmony_ci	for (i = 0; i < pdata->channel_count; i++, channel++) {
136662306a36Sopenharmony_ci		if (!channel->rx_ring)
136762306a36Sopenharmony_ci			break;
136862306a36Sopenharmony_ci
136962306a36Sopenharmony_ci		regval = readl(XLGMAC_DMA_REG(channel, DMA_CH_RCR));
137062306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, DMA_CH_RCR_RBSZ_POS,
137162306a36Sopenharmony_ci					     DMA_CH_RCR_RBSZ_LEN,
137262306a36Sopenharmony_ci					pdata->rx_buf_size);
137362306a36Sopenharmony_ci		writel(regval, XLGMAC_DMA_REG(channel, DMA_CH_RCR));
137462306a36Sopenharmony_ci	}
137562306a36Sopenharmony_ci}
137662306a36Sopenharmony_ci
137762306a36Sopenharmony_cistatic void xlgmac_config_tso_mode(struct xlgmac_pdata *pdata)
137862306a36Sopenharmony_ci{
137962306a36Sopenharmony_ci	struct xlgmac_channel *channel;
138062306a36Sopenharmony_ci	unsigned int i;
138162306a36Sopenharmony_ci	u32 regval;
138262306a36Sopenharmony_ci
138362306a36Sopenharmony_ci	channel = pdata->channel_head;
138462306a36Sopenharmony_ci	for (i = 0; i < pdata->channel_count; i++, channel++) {
138562306a36Sopenharmony_ci		if (!channel->tx_ring)
138662306a36Sopenharmony_ci			break;
138762306a36Sopenharmony_ci
138862306a36Sopenharmony_ci		if (pdata->hw_feat.tso) {
138962306a36Sopenharmony_ci			regval = readl(XLGMAC_DMA_REG(channel, DMA_CH_TCR));
139062306a36Sopenharmony_ci			regval = XLGMAC_SET_REG_BITS(regval, DMA_CH_TCR_TSE_POS,
139162306a36Sopenharmony_ci						     DMA_CH_TCR_TSE_LEN, 1);
139262306a36Sopenharmony_ci			writel(regval, XLGMAC_DMA_REG(channel, DMA_CH_TCR));
139362306a36Sopenharmony_ci		}
139462306a36Sopenharmony_ci	}
139562306a36Sopenharmony_ci}
139662306a36Sopenharmony_ci
139762306a36Sopenharmony_cistatic void xlgmac_config_sph_mode(struct xlgmac_pdata *pdata)
139862306a36Sopenharmony_ci{
139962306a36Sopenharmony_ci	struct xlgmac_channel *channel;
140062306a36Sopenharmony_ci	unsigned int i;
140162306a36Sopenharmony_ci	u32 regval;
140262306a36Sopenharmony_ci
140362306a36Sopenharmony_ci	channel = pdata->channel_head;
140462306a36Sopenharmony_ci	for (i = 0; i < pdata->channel_count; i++, channel++) {
140562306a36Sopenharmony_ci		if (!channel->rx_ring)
140662306a36Sopenharmony_ci			break;
140762306a36Sopenharmony_ci
140862306a36Sopenharmony_ci		regval = readl(XLGMAC_DMA_REG(channel, DMA_CH_CR));
140962306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, DMA_CH_CR_SPH_POS,
141062306a36Sopenharmony_ci					     DMA_CH_CR_SPH_LEN, 1);
141162306a36Sopenharmony_ci		writel(regval, XLGMAC_DMA_REG(channel, DMA_CH_CR));
141262306a36Sopenharmony_ci	}
141362306a36Sopenharmony_ci
141462306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_RCR);
141562306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_RCR_HDSMS_POS,
141662306a36Sopenharmony_ci				     MAC_RCR_HDSMS_LEN,
141762306a36Sopenharmony_ci				XLGMAC_SPH_HDSMS_SIZE);
141862306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_RCR);
141962306a36Sopenharmony_ci}
142062306a36Sopenharmony_ci
142162306a36Sopenharmony_cistatic unsigned int xlgmac_usec_to_riwt(struct xlgmac_pdata *pdata,
142262306a36Sopenharmony_ci					unsigned int usec)
142362306a36Sopenharmony_ci{
142462306a36Sopenharmony_ci	unsigned long rate;
142562306a36Sopenharmony_ci	unsigned int ret;
142662306a36Sopenharmony_ci
142762306a36Sopenharmony_ci	rate = pdata->sysclk_rate;
142862306a36Sopenharmony_ci
142962306a36Sopenharmony_ci	/* Convert the input usec value to the watchdog timer value. Each
143062306a36Sopenharmony_ci	 * watchdog timer value is equivalent to 256 clock cycles.
143162306a36Sopenharmony_ci	 * Calculate the required value as:
143262306a36Sopenharmony_ci	 *   ( usec * ( system_clock_mhz / 10^6 ) / 256
143362306a36Sopenharmony_ci	 */
143462306a36Sopenharmony_ci	ret = (usec * (rate / 1000000)) / 256;
143562306a36Sopenharmony_ci
143662306a36Sopenharmony_ci	return ret;
143762306a36Sopenharmony_ci}
143862306a36Sopenharmony_ci
143962306a36Sopenharmony_cistatic unsigned int xlgmac_riwt_to_usec(struct xlgmac_pdata *pdata,
144062306a36Sopenharmony_ci					unsigned int riwt)
144162306a36Sopenharmony_ci{
144262306a36Sopenharmony_ci	unsigned long rate;
144362306a36Sopenharmony_ci	unsigned int ret;
144462306a36Sopenharmony_ci
144562306a36Sopenharmony_ci	rate = pdata->sysclk_rate;
144662306a36Sopenharmony_ci
144762306a36Sopenharmony_ci	/* Convert the input watchdog timer value to the usec value. Each
144862306a36Sopenharmony_ci	 * watchdog timer value is equivalent to 256 clock cycles.
144962306a36Sopenharmony_ci	 * Calculate the required value as:
145062306a36Sopenharmony_ci	 *   ( riwt * 256 ) / ( system_clock_mhz / 10^6 )
145162306a36Sopenharmony_ci	 */
145262306a36Sopenharmony_ci	ret = (riwt * 256) / (rate / 1000000);
145362306a36Sopenharmony_ci
145462306a36Sopenharmony_ci	return ret;
145562306a36Sopenharmony_ci}
145662306a36Sopenharmony_ci
145762306a36Sopenharmony_cistatic int xlgmac_config_rx_threshold(struct xlgmac_pdata *pdata,
145862306a36Sopenharmony_ci				      unsigned int val)
145962306a36Sopenharmony_ci{
146062306a36Sopenharmony_ci	unsigned int i;
146162306a36Sopenharmony_ci	u32 regval;
146262306a36Sopenharmony_ci
146362306a36Sopenharmony_ci	for (i = 0; i < pdata->rx_q_count; i++) {
146462306a36Sopenharmony_ci		regval = readl(XLGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR));
146562306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, MTL_Q_RQOMR_RTC_POS,
146662306a36Sopenharmony_ci					     MTL_Q_RQOMR_RTC_LEN, val);
146762306a36Sopenharmony_ci		writel(regval, XLGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR));
146862306a36Sopenharmony_ci	}
146962306a36Sopenharmony_ci
147062306a36Sopenharmony_ci	return 0;
147162306a36Sopenharmony_ci}
147262306a36Sopenharmony_ci
147362306a36Sopenharmony_cistatic void xlgmac_config_mtl_mode(struct xlgmac_pdata *pdata)
147462306a36Sopenharmony_ci{
147562306a36Sopenharmony_ci	unsigned int i;
147662306a36Sopenharmony_ci	u32 regval;
147762306a36Sopenharmony_ci
147862306a36Sopenharmony_ci	/* Set Tx to weighted round robin scheduling algorithm */
147962306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MTL_OMR);
148062306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MTL_OMR_ETSALG_POS,
148162306a36Sopenharmony_ci				     MTL_OMR_ETSALG_LEN, MTL_ETSALG_WRR);
148262306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MTL_OMR);
148362306a36Sopenharmony_ci
148462306a36Sopenharmony_ci	/* Set Tx traffic classes to use WRR algorithm with equal weights */
148562306a36Sopenharmony_ci	for (i = 0; i < pdata->hw_feat.tc_cnt; i++) {
148662306a36Sopenharmony_ci		regval = readl(XLGMAC_MTL_REG(pdata, i, MTL_TC_ETSCR));
148762306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, MTL_TC_ETSCR_TSA_POS,
148862306a36Sopenharmony_ci					     MTL_TC_ETSCR_TSA_LEN, MTL_TSA_ETS);
148962306a36Sopenharmony_ci		writel(regval, XLGMAC_MTL_REG(pdata, i, MTL_TC_ETSCR));
149062306a36Sopenharmony_ci
149162306a36Sopenharmony_ci		regval = readl(XLGMAC_MTL_REG(pdata, i, MTL_TC_QWR));
149262306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, MTL_TC_QWR_QW_POS,
149362306a36Sopenharmony_ci					     MTL_TC_QWR_QW_LEN, 1);
149462306a36Sopenharmony_ci		writel(regval, XLGMAC_MTL_REG(pdata, i, MTL_TC_QWR));
149562306a36Sopenharmony_ci	}
149662306a36Sopenharmony_ci
149762306a36Sopenharmony_ci	/* Set Rx to strict priority algorithm */
149862306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MTL_OMR);
149962306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MTL_OMR_RAA_POS,
150062306a36Sopenharmony_ci				     MTL_OMR_RAA_LEN, MTL_RAA_SP);
150162306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MTL_OMR);
150262306a36Sopenharmony_ci}
150362306a36Sopenharmony_ci
150462306a36Sopenharmony_cistatic void xlgmac_config_queue_mapping(struct xlgmac_pdata *pdata)
150562306a36Sopenharmony_ci{
150662306a36Sopenharmony_ci	unsigned int ppq, ppq_extra, prio, prio_queues;
150762306a36Sopenharmony_ci	unsigned int qptc, qptc_extra, queue;
150862306a36Sopenharmony_ci	unsigned int reg, regval;
150962306a36Sopenharmony_ci	unsigned int mask;
151062306a36Sopenharmony_ci	unsigned int i, j;
151162306a36Sopenharmony_ci
151262306a36Sopenharmony_ci	/* Map the MTL Tx Queues to Traffic Classes
151362306a36Sopenharmony_ci	 *   Note: Tx Queues >= Traffic Classes
151462306a36Sopenharmony_ci	 */
151562306a36Sopenharmony_ci	qptc = pdata->tx_q_count / pdata->hw_feat.tc_cnt;
151662306a36Sopenharmony_ci	qptc_extra = pdata->tx_q_count % pdata->hw_feat.tc_cnt;
151762306a36Sopenharmony_ci
151862306a36Sopenharmony_ci	for (i = 0, queue = 0; i < pdata->hw_feat.tc_cnt; i++) {
151962306a36Sopenharmony_ci		for (j = 0; j < qptc; j++) {
152062306a36Sopenharmony_ci			netif_dbg(pdata, drv, pdata->netdev,
152162306a36Sopenharmony_ci				  "TXq%u mapped to TC%u\n", queue, i);
152262306a36Sopenharmony_ci			regval = readl(XLGMAC_MTL_REG(pdata, queue,
152362306a36Sopenharmony_ci						      MTL_Q_TQOMR));
152462306a36Sopenharmony_ci			regval = XLGMAC_SET_REG_BITS(regval,
152562306a36Sopenharmony_ci						     MTL_Q_TQOMR_Q2TCMAP_POS,
152662306a36Sopenharmony_ci						     MTL_Q_TQOMR_Q2TCMAP_LEN,
152762306a36Sopenharmony_ci						     i);
152862306a36Sopenharmony_ci			writel(regval, XLGMAC_MTL_REG(pdata, queue,
152962306a36Sopenharmony_ci						      MTL_Q_TQOMR));
153062306a36Sopenharmony_ci			queue++;
153162306a36Sopenharmony_ci		}
153262306a36Sopenharmony_ci
153362306a36Sopenharmony_ci		if (i < qptc_extra) {
153462306a36Sopenharmony_ci			netif_dbg(pdata, drv, pdata->netdev,
153562306a36Sopenharmony_ci				  "TXq%u mapped to TC%u\n", queue, i);
153662306a36Sopenharmony_ci			regval = readl(XLGMAC_MTL_REG(pdata, queue,
153762306a36Sopenharmony_ci						      MTL_Q_TQOMR));
153862306a36Sopenharmony_ci			regval = XLGMAC_SET_REG_BITS(regval,
153962306a36Sopenharmony_ci						     MTL_Q_TQOMR_Q2TCMAP_POS,
154062306a36Sopenharmony_ci						     MTL_Q_TQOMR_Q2TCMAP_LEN,
154162306a36Sopenharmony_ci						     i);
154262306a36Sopenharmony_ci			writel(regval, XLGMAC_MTL_REG(pdata, queue,
154362306a36Sopenharmony_ci						      MTL_Q_TQOMR));
154462306a36Sopenharmony_ci			queue++;
154562306a36Sopenharmony_ci		}
154662306a36Sopenharmony_ci	}
154762306a36Sopenharmony_ci
154862306a36Sopenharmony_ci	/* Map the 8 VLAN priority values to available MTL Rx queues */
154962306a36Sopenharmony_ci	prio_queues = min_t(unsigned int, IEEE_8021QAZ_MAX_TCS,
155062306a36Sopenharmony_ci			    pdata->rx_q_count);
155162306a36Sopenharmony_ci	ppq = IEEE_8021QAZ_MAX_TCS / prio_queues;
155262306a36Sopenharmony_ci	ppq_extra = IEEE_8021QAZ_MAX_TCS % prio_queues;
155362306a36Sopenharmony_ci
155462306a36Sopenharmony_ci	reg = MAC_RQC2R;
155562306a36Sopenharmony_ci	regval = 0;
155662306a36Sopenharmony_ci	for (i = 0, prio = 0; i < prio_queues;) {
155762306a36Sopenharmony_ci		mask = 0;
155862306a36Sopenharmony_ci		for (j = 0; j < ppq; j++) {
155962306a36Sopenharmony_ci			netif_dbg(pdata, drv, pdata->netdev,
156062306a36Sopenharmony_ci				  "PRIO%u mapped to RXq%u\n", prio, i);
156162306a36Sopenharmony_ci			mask |= (1 << prio);
156262306a36Sopenharmony_ci			prio++;
156362306a36Sopenharmony_ci		}
156462306a36Sopenharmony_ci
156562306a36Sopenharmony_ci		if (i < ppq_extra) {
156662306a36Sopenharmony_ci			netif_dbg(pdata, drv, pdata->netdev,
156762306a36Sopenharmony_ci				  "PRIO%u mapped to RXq%u\n", prio, i);
156862306a36Sopenharmony_ci			mask |= (1 << prio);
156962306a36Sopenharmony_ci			prio++;
157062306a36Sopenharmony_ci		}
157162306a36Sopenharmony_ci
157262306a36Sopenharmony_ci		regval |= (mask << ((i++ % MAC_RQC2_Q_PER_REG) << 3));
157362306a36Sopenharmony_ci
157462306a36Sopenharmony_ci		if ((i % MAC_RQC2_Q_PER_REG) && (i != prio_queues))
157562306a36Sopenharmony_ci			continue;
157662306a36Sopenharmony_ci
157762306a36Sopenharmony_ci		writel(regval, pdata->mac_regs + reg);
157862306a36Sopenharmony_ci		reg += MAC_RQC2_INC;
157962306a36Sopenharmony_ci		regval = 0;
158062306a36Sopenharmony_ci	}
158162306a36Sopenharmony_ci
158262306a36Sopenharmony_ci	/* Configure one to one, MTL Rx queue to DMA Rx channel mapping
158362306a36Sopenharmony_ci	 *  ie Q0 <--> CH0, Q1 <--> CH1 ... Q11 <--> CH11
158462306a36Sopenharmony_ci	 */
158562306a36Sopenharmony_ci	reg = MTL_RQDCM0R;
158662306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + reg);
158762306a36Sopenharmony_ci	regval |= (MTL_RQDCM0R_Q0MDMACH | MTL_RQDCM0R_Q1MDMACH |
158862306a36Sopenharmony_ci		    MTL_RQDCM0R_Q2MDMACH | MTL_RQDCM0R_Q3MDMACH);
158962306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + reg);
159062306a36Sopenharmony_ci
159162306a36Sopenharmony_ci	reg += MTL_RQDCM_INC;
159262306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + reg);
159362306a36Sopenharmony_ci	regval |= (MTL_RQDCM1R_Q4MDMACH | MTL_RQDCM1R_Q5MDMACH |
159462306a36Sopenharmony_ci		    MTL_RQDCM1R_Q6MDMACH | MTL_RQDCM1R_Q7MDMACH);
159562306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + reg);
159662306a36Sopenharmony_ci
159762306a36Sopenharmony_ci	reg += MTL_RQDCM_INC;
159862306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + reg);
159962306a36Sopenharmony_ci	regval |= (MTL_RQDCM2R_Q8MDMACH | MTL_RQDCM2R_Q9MDMACH |
160062306a36Sopenharmony_ci		    MTL_RQDCM2R_Q10MDMACH | MTL_RQDCM2R_Q11MDMACH);
160162306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + reg);
160262306a36Sopenharmony_ci}
160362306a36Sopenharmony_ci
160462306a36Sopenharmony_cistatic unsigned int xlgmac_calculate_per_queue_fifo(
160562306a36Sopenharmony_ci					unsigned int fifo_size,
160662306a36Sopenharmony_ci					unsigned int queue_count)
160762306a36Sopenharmony_ci{
160862306a36Sopenharmony_ci	unsigned int q_fifo_size;
160962306a36Sopenharmony_ci	unsigned int p_fifo;
161062306a36Sopenharmony_ci
161162306a36Sopenharmony_ci	/* Calculate the configured fifo size */
161262306a36Sopenharmony_ci	q_fifo_size = 1 << (fifo_size + 7);
161362306a36Sopenharmony_ci
161462306a36Sopenharmony_ci	/* The configured value may not be the actual amount of fifo RAM */
161562306a36Sopenharmony_ci	q_fifo_size = min_t(unsigned int, XLGMAC_MAX_FIFO, q_fifo_size);
161662306a36Sopenharmony_ci
161762306a36Sopenharmony_ci	q_fifo_size = q_fifo_size / queue_count;
161862306a36Sopenharmony_ci
161962306a36Sopenharmony_ci	/* Each increment in the queue fifo size represents 256 bytes of
162062306a36Sopenharmony_ci	 * fifo, with 0 representing 256 bytes. Distribute the fifo equally
162162306a36Sopenharmony_ci	 * between the queues.
162262306a36Sopenharmony_ci	 */
162362306a36Sopenharmony_ci	p_fifo = q_fifo_size / 256;
162462306a36Sopenharmony_ci	if (p_fifo)
162562306a36Sopenharmony_ci		p_fifo--;
162662306a36Sopenharmony_ci
162762306a36Sopenharmony_ci	return p_fifo;
162862306a36Sopenharmony_ci}
162962306a36Sopenharmony_ci
163062306a36Sopenharmony_cistatic void xlgmac_config_tx_fifo_size(struct xlgmac_pdata *pdata)
163162306a36Sopenharmony_ci{
163262306a36Sopenharmony_ci	unsigned int fifo_size;
163362306a36Sopenharmony_ci	unsigned int i;
163462306a36Sopenharmony_ci	u32 regval;
163562306a36Sopenharmony_ci
163662306a36Sopenharmony_ci	fifo_size = xlgmac_calculate_per_queue_fifo(
163762306a36Sopenharmony_ci				pdata->hw_feat.tx_fifo_size,
163862306a36Sopenharmony_ci				pdata->tx_q_count);
163962306a36Sopenharmony_ci
164062306a36Sopenharmony_ci	for (i = 0; i < pdata->tx_q_count; i++) {
164162306a36Sopenharmony_ci		regval = readl(XLGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR));
164262306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, MTL_Q_TQOMR_TQS_POS,
164362306a36Sopenharmony_ci					     MTL_Q_TQOMR_TQS_LEN, fifo_size);
164462306a36Sopenharmony_ci		writel(regval, XLGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR));
164562306a36Sopenharmony_ci	}
164662306a36Sopenharmony_ci
164762306a36Sopenharmony_ci	netif_info(pdata, drv, pdata->netdev,
164862306a36Sopenharmony_ci		   "%d Tx hardware queues, %d byte fifo per queue\n",
164962306a36Sopenharmony_ci		   pdata->tx_q_count, ((fifo_size + 1) * 256));
165062306a36Sopenharmony_ci}
165162306a36Sopenharmony_ci
165262306a36Sopenharmony_cistatic void xlgmac_config_rx_fifo_size(struct xlgmac_pdata *pdata)
165362306a36Sopenharmony_ci{
165462306a36Sopenharmony_ci	unsigned int fifo_size;
165562306a36Sopenharmony_ci	unsigned int i;
165662306a36Sopenharmony_ci	u32 regval;
165762306a36Sopenharmony_ci
165862306a36Sopenharmony_ci	fifo_size = xlgmac_calculate_per_queue_fifo(
165962306a36Sopenharmony_ci					pdata->hw_feat.rx_fifo_size,
166062306a36Sopenharmony_ci					pdata->rx_q_count);
166162306a36Sopenharmony_ci
166262306a36Sopenharmony_ci	for (i = 0; i < pdata->rx_q_count; i++) {
166362306a36Sopenharmony_ci		regval = readl(XLGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR));
166462306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, MTL_Q_RQOMR_RQS_POS,
166562306a36Sopenharmony_ci					     MTL_Q_RQOMR_RQS_LEN, fifo_size);
166662306a36Sopenharmony_ci		writel(regval, XLGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR));
166762306a36Sopenharmony_ci	}
166862306a36Sopenharmony_ci
166962306a36Sopenharmony_ci	netif_info(pdata, drv, pdata->netdev,
167062306a36Sopenharmony_ci		   "%d Rx hardware queues, %d byte fifo per queue\n",
167162306a36Sopenharmony_ci		   pdata->rx_q_count, ((fifo_size + 1) * 256));
167262306a36Sopenharmony_ci}
167362306a36Sopenharmony_ci
167462306a36Sopenharmony_cistatic void xlgmac_config_flow_control_threshold(struct xlgmac_pdata *pdata)
167562306a36Sopenharmony_ci{
167662306a36Sopenharmony_ci	unsigned int i;
167762306a36Sopenharmony_ci	u32 regval;
167862306a36Sopenharmony_ci
167962306a36Sopenharmony_ci	for (i = 0; i < pdata->rx_q_count; i++) {
168062306a36Sopenharmony_ci		regval = readl(XLGMAC_MTL_REG(pdata, i, MTL_Q_RQFCR));
168162306a36Sopenharmony_ci		/* Activate flow control when less than 4k left in fifo */
168262306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, MTL_Q_RQFCR_RFA_POS,
168362306a36Sopenharmony_ci					     MTL_Q_RQFCR_RFA_LEN, 2);
168462306a36Sopenharmony_ci		/* De-activate flow control when more than 6k left in fifo */
168562306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, MTL_Q_RQFCR_RFD_POS,
168662306a36Sopenharmony_ci					     MTL_Q_RQFCR_RFD_LEN, 4);
168762306a36Sopenharmony_ci		writel(regval, XLGMAC_MTL_REG(pdata, i, MTL_Q_RQFCR));
168862306a36Sopenharmony_ci	}
168962306a36Sopenharmony_ci}
169062306a36Sopenharmony_ci
169162306a36Sopenharmony_cistatic int xlgmac_config_tx_threshold(struct xlgmac_pdata *pdata,
169262306a36Sopenharmony_ci				      unsigned int val)
169362306a36Sopenharmony_ci{
169462306a36Sopenharmony_ci	unsigned int i;
169562306a36Sopenharmony_ci	u32 regval;
169662306a36Sopenharmony_ci
169762306a36Sopenharmony_ci	for (i = 0; i < pdata->tx_q_count; i++) {
169862306a36Sopenharmony_ci		regval = readl(XLGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR));
169962306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, MTL_Q_TQOMR_TTC_POS,
170062306a36Sopenharmony_ci					     MTL_Q_TQOMR_TTC_LEN, val);
170162306a36Sopenharmony_ci		writel(regval, XLGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR));
170262306a36Sopenharmony_ci	}
170362306a36Sopenharmony_ci
170462306a36Sopenharmony_ci	return 0;
170562306a36Sopenharmony_ci}
170662306a36Sopenharmony_ci
170762306a36Sopenharmony_cistatic int xlgmac_config_rsf_mode(struct xlgmac_pdata *pdata,
170862306a36Sopenharmony_ci				  unsigned int val)
170962306a36Sopenharmony_ci{
171062306a36Sopenharmony_ci	unsigned int i;
171162306a36Sopenharmony_ci	u32 regval;
171262306a36Sopenharmony_ci
171362306a36Sopenharmony_ci	for (i = 0; i < pdata->rx_q_count; i++) {
171462306a36Sopenharmony_ci		regval = readl(XLGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR));
171562306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, MTL_Q_RQOMR_RSF_POS,
171662306a36Sopenharmony_ci					     MTL_Q_RQOMR_RSF_LEN, val);
171762306a36Sopenharmony_ci		writel(regval, XLGMAC_MTL_REG(pdata, i, MTL_Q_RQOMR));
171862306a36Sopenharmony_ci	}
171962306a36Sopenharmony_ci
172062306a36Sopenharmony_ci	return 0;
172162306a36Sopenharmony_ci}
172262306a36Sopenharmony_ci
172362306a36Sopenharmony_cistatic int xlgmac_config_tsf_mode(struct xlgmac_pdata *pdata,
172462306a36Sopenharmony_ci				  unsigned int val)
172562306a36Sopenharmony_ci{
172662306a36Sopenharmony_ci	unsigned int i;
172762306a36Sopenharmony_ci	u32 regval;
172862306a36Sopenharmony_ci
172962306a36Sopenharmony_ci	for (i = 0; i < pdata->tx_q_count; i++) {
173062306a36Sopenharmony_ci		regval = readl(XLGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR));
173162306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, MTL_Q_TQOMR_TSF_POS,
173262306a36Sopenharmony_ci					     MTL_Q_TQOMR_TSF_LEN, val);
173362306a36Sopenharmony_ci		writel(regval, XLGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR));
173462306a36Sopenharmony_ci	}
173562306a36Sopenharmony_ci
173662306a36Sopenharmony_ci	return 0;
173762306a36Sopenharmony_ci}
173862306a36Sopenharmony_ci
173962306a36Sopenharmony_cistatic int xlgmac_config_osp_mode(struct xlgmac_pdata *pdata)
174062306a36Sopenharmony_ci{
174162306a36Sopenharmony_ci	struct xlgmac_channel *channel;
174262306a36Sopenharmony_ci	unsigned int i;
174362306a36Sopenharmony_ci	u32 regval;
174462306a36Sopenharmony_ci
174562306a36Sopenharmony_ci	channel = pdata->channel_head;
174662306a36Sopenharmony_ci	for (i = 0; i < pdata->channel_count; i++, channel++) {
174762306a36Sopenharmony_ci		if (!channel->tx_ring)
174862306a36Sopenharmony_ci			break;
174962306a36Sopenharmony_ci
175062306a36Sopenharmony_ci		regval = readl(XLGMAC_DMA_REG(channel, DMA_CH_TCR));
175162306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, DMA_CH_TCR_OSP_POS,
175262306a36Sopenharmony_ci					     DMA_CH_TCR_OSP_LEN,
175362306a36Sopenharmony_ci					pdata->tx_osp_mode);
175462306a36Sopenharmony_ci		writel(regval, XLGMAC_DMA_REG(channel, DMA_CH_TCR));
175562306a36Sopenharmony_ci	}
175662306a36Sopenharmony_ci
175762306a36Sopenharmony_ci	return 0;
175862306a36Sopenharmony_ci}
175962306a36Sopenharmony_ci
176062306a36Sopenharmony_cistatic int xlgmac_config_pblx8(struct xlgmac_pdata *pdata)
176162306a36Sopenharmony_ci{
176262306a36Sopenharmony_ci	struct xlgmac_channel *channel;
176362306a36Sopenharmony_ci	unsigned int i;
176462306a36Sopenharmony_ci	u32 regval;
176562306a36Sopenharmony_ci
176662306a36Sopenharmony_ci	channel = pdata->channel_head;
176762306a36Sopenharmony_ci	for (i = 0; i < pdata->channel_count; i++, channel++) {
176862306a36Sopenharmony_ci		regval = readl(XLGMAC_DMA_REG(channel, DMA_CH_CR));
176962306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, DMA_CH_CR_PBLX8_POS,
177062306a36Sopenharmony_ci					     DMA_CH_CR_PBLX8_LEN,
177162306a36Sopenharmony_ci					pdata->pblx8);
177262306a36Sopenharmony_ci		writel(regval, XLGMAC_DMA_REG(channel, DMA_CH_CR));
177362306a36Sopenharmony_ci	}
177462306a36Sopenharmony_ci
177562306a36Sopenharmony_ci	return 0;
177662306a36Sopenharmony_ci}
177762306a36Sopenharmony_ci
177862306a36Sopenharmony_cistatic int xlgmac_get_tx_pbl_val(struct xlgmac_pdata *pdata)
177962306a36Sopenharmony_ci{
178062306a36Sopenharmony_ci	u32 regval;
178162306a36Sopenharmony_ci
178262306a36Sopenharmony_ci	regval = readl(XLGMAC_DMA_REG(pdata->channel_head, DMA_CH_TCR));
178362306a36Sopenharmony_ci	regval = XLGMAC_GET_REG_BITS(regval, DMA_CH_TCR_PBL_POS,
178462306a36Sopenharmony_ci				     DMA_CH_TCR_PBL_LEN);
178562306a36Sopenharmony_ci	return regval;
178662306a36Sopenharmony_ci}
178762306a36Sopenharmony_ci
178862306a36Sopenharmony_cistatic int xlgmac_config_tx_pbl_val(struct xlgmac_pdata *pdata)
178962306a36Sopenharmony_ci{
179062306a36Sopenharmony_ci	struct xlgmac_channel *channel;
179162306a36Sopenharmony_ci	unsigned int i;
179262306a36Sopenharmony_ci	u32 regval;
179362306a36Sopenharmony_ci
179462306a36Sopenharmony_ci	channel = pdata->channel_head;
179562306a36Sopenharmony_ci	for (i = 0; i < pdata->channel_count; i++, channel++) {
179662306a36Sopenharmony_ci		if (!channel->tx_ring)
179762306a36Sopenharmony_ci			break;
179862306a36Sopenharmony_ci
179962306a36Sopenharmony_ci		regval = readl(XLGMAC_DMA_REG(channel, DMA_CH_TCR));
180062306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, DMA_CH_TCR_PBL_POS,
180162306a36Sopenharmony_ci					     DMA_CH_TCR_PBL_LEN,
180262306a36Sopenharmony_ci					pdata->tx_pbl);
180362306a36Sopenharmony_ci		writel(regval, XLGMAC_DMA_REG(channel, DMA_CH_TCR));
180462306a36Sopenharmony_ci	}
180562306a36Sopenharmony_ci
180662306a36Sopenharmony_ci	return 0;
180762306a36Sopenharmony_ci}
180862306a36Sopenharmony_ci
180962306a36Sopenharmony_cistatic int xlgmac_get_rx_pbl_val(struct xlgmac_pdata *pdata)
181062306a36Sopenharmony_ci{
181162306a36Sopenharmony_ci	u32 regval;
181262306a36Sopenharmony_ci
181362306a36Sopenharmony_ci	regval = readl(XLGMAC_DMA_REG(pdata->channel_head, DMA_CH_RCR));
181462306a36Sopenharmony_ci	regval = XLGMAC_GET_REG_BITS(regval, DMA_CH_RCR_PBL_POS,
181562306a36Sopenharmony_ci				     DMA_CH_RCR_PBL_LEN);
181662306a36Sopenharmony_ci	return regval;
181762306a36Sopenharmony_ci}
181862306a36Sopenharmony_ci
181962306a36Sopenharmony_cistatic int xlgmac_config_rx_pbl_val(struct xlgmac_pdata *pdata)
182062306a36Sopenharmony_ci{
182162306a36Sopenharmony_ci	struct xlgmac_channel *channel;
182262306a36Sopenharmony_ci	unsigned int i;
182362306a36Sopenharmony_ci	u32 regval;
182462306a36Sopenharmony_ci
182562306a36Sopenharmony_ci	channel = pdata->channel_head;
182662306a36Sopenharmony_ci	for (i = 0; i < pdata->channel_count; i++, channel++) {
182762306a36Sopenharmony_ci		if (!channel->rx_ring)
182862306a36Sopenharmony_ci			break;
182962306a36Sopenharmony_ci
183062306a36Sopenharmony_ci		regval = readl(XLGMAC_DMA_REG(channel, DMA_CH_RCR));
183162306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, DMA_CH_RCR_PBL_POS,
183262306a36Sopenharmony_ci					     DMA_CH_RCR_PBL_LEN,
183362306a36Sopenharmony_ci					pdata->rx_pbl);
183462306a36Sopenharmony_ci		writel(regval, XLGMAC_DMA_REG(channel, DMA_CH_RCR));
183562306a36Sopenharmony_ci	}
183662306a36Sopenharmony_ci
183762306a36Sopenharmony_ci	return 0;
183862306a36Sopenharmony_ci}
183962306a36Sopenharmony_ci
184062306a36Sopenharmony_cistatic u64 xlgmac_mmc_read(struct xlgmac_pdata *pdata, unsigned int reg_lo)
184162306a36Sopenharmony_ci{
184262306a36Sopenharmony_ci	bool read_hi;
184362306a36Sopenharmony_ci	u64 val;
184462306a36Sopenharmony_ci
184562306a36Sopenharmony_ci	switch (reg_lo) {
184662306a36Sopenharmony_ci	/* These registers are always 64 bit */
184762306a36Sopenharmony_ci	case MMC_TXOCTETCOUNT_GB_LO:
184862306a36Sopenharmony_ci	case MMC_TXOCTETCOUNT_G_LO:
184962306a36Sopenharmony_ci	case MMC_RXOCTETCOUNT_GB_LO:
185062306a36Sopenharmony_ci	case MMC_RXOCTETCOUNT_G_LO:
185162306a36Sopenharmony_ci		read_hi = true;
185262306a36Sopenharmony_ci		break;
185362306a36Sopenharmony_ci
185462306a36Sopenharmony_ci	default:
185562306a36Sopenharmony_ci		read_hi = false;
185662306a36Sopenharmony_ci	}
185762306a36Sopenharmony_ci
185862306a36Sopenharmony_ci	val = (u64)readl(pdata->mac_regs + reg_lo);
185962306a36Sopenharmony_ci
186062306a36Sopenharmony_ci	if (read_hi)
186162306a36Sopenharmony_ci		val |= ((u64)readl(pdata->mac_regs + reg_lo + 4) << 32);
186262306a36Sopenharmony_ci
186362306a36Sopenharmony_ci	return val;
186462306a36Sopenharmony_ci}
186562306a36Sopenharmony_ci
186662306a36Sopenharmony_cistatic void xlgmac_tx_mmc_int(struct xlgmac_pdata *pdata)
186762306a36Sopenharmony_ci{
186862306a36Sopenharmony_ci	unsigned int mmc_isr = readl(pdata->mac_regs + MMC_TISR);
186962306a36Sopenharmony_ci	struct xlgmac_stats *stats = &pdata->stats;
187062306a36Sopenharmony_ci
187162306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
187262306a36Sopenharmony_ci				MMC_TISR_TXOCTETCOUNT_GB_POS,
187362306a36Sopenharmony_ci				MMC_TISR_TXOCTETCOUNT_GB_LEN))
187462306a36Sopenharmony_ci		stats->txoctetcount_gb +=
187562306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_TXOCTETCOUNT_GB_LO);
187662306a36Sopenharmony_ci
187762306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
187862306a36Sopenharmony_ci				MMC_TISR_TXFRAMECOUNT_GB_POS,
187962306a36Sopenharmony_ci				MMC_TISR_TXFRAMECOUNT_GB_LEN))
188062306a36Sopenharmony_ci		stats->txframecount_gb +=
188162306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_TXFRAMECOUNT_GB_LO);
188262306a36Sopenharmony_ci
188362306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
188462306a36Sopenharmony_ci				MMC_TISR_TXBROADCASTFRAMES_G_POS,
188562306a36Sopenharmony_ci				MMC_TISR_TXBROADCASTFRAMES_G_LEN))
188662306a36Sopenharmony_ci		stats->txbroadcastframes_g +=
188762306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_TXBROADCASTFRAMES_G_LO);
188862306a36Sopenharmony_ci
188962306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
189062306a36Sopenharmony_ci				MMC_TISR_TXMULTICASTFRAMES_G_POS,
189162306a36Sopenharmony_ci				MMC_TISR_TXMULTICASTFRAMES_G_LEN))
189262306a36Sopenharmony_ci		stats->txmulticastframes_g +=
189362306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_TXMULTICASTFRAMES_G_LO);
189462306a36Sopenharmony_ci
189562306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
189662306a36Sopenharmony_ci				MMC_TISR_TX64OCTETS_GB_POS,
189762306a36Sopenharmony_ci				MMC_TISR_TX64OCTETS_GB_LEN))
189862306a36Sopenharmony_ci		stats->tx64octets_gb +=
189962306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_TX64OCTETS_GB_LO);
190062306a36Sopenharmony_ci
190162306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
190262306a36Sopenharmony_ci				MMC_TISR_TX65TO127OCTETS_GB_POS,
190362306a36Sopenharmony_ci				MMC_TISR_TX65TO127OCTETS_GB_LEN))
190462306a36Sopenharmony_ci		stats->tx65to127octets_gb +=
190562306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_TX65TO127OCTETS_GB_LO);
190662306a36Sopenharmony_ci
190762306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
190862306a36Sopenharmony_ci				MMC_TISR_TX128TO255OCTETS_GB_POS,
190962306a36Sopenharmony_ci				MMC_TISR_TX128TO255OCTETS_GB_LEN))
191062306a36Sopenharmony_ci		stats->tx128to255octets_gb +=
191162306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_TX128TO255OCTETS_GB_LO);
191262306a36Sopenharmony_ci
191362306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
191462306a36Sopenharmony_ci				MMC_TISR_TX256TO511OCTETS_GB_POS,
191562306a36Sopenharmony_ci				MMC_TISR_TX256TO511OCTETS_GB_LEN))
191662306a36Sopenharmony_ci		stats->tx256to511octets_gb +=
191762306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_TX256TO511OCTETS_GB_LO);
191862306a36Sopenharmony_ci
191962306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
192062306a36Sopenharmony_ci				MMC_TISR_TX512TO1023OCTETS_GB_POS,
192162306a36Sopenharmony_ci				MMC_TISR_TX512TO1023OCTETS_GB_LEN))
192262306a36Sopenharmony_ci		stats->tx512to1023octets_gb +=
192362306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_TX512TO1023OCTETS_GB_LO);
192462306a36Sopenharmony_ci
192562306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
192662306a36Sopenharmony_ci				MMC_TISR_TX1024TOMAXOCTETS_GB_POS,
192762306a36Sopenharmony_ci				MMC_TISR_TX1024TOMAXOCTETS_GB_LEN))
192862306a36Sopenharmony_ci		stats->tx1024tomaxoctets_gb +=
192962306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_TX1024TOMAXOCTETS_GB_LO);
193062306a36Sopenharmony_ci
193162306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
193262306a36Sopenharmony_ci				MMC_TISR_TXUNICASTFRAMES_GB_POS,
193362306a36Sopenharmony_ci				MMC_TISR_TXUNICASTFRAMES_GB_LEN))
193462306a36Sopenharmony_ci		stats->txunicastframes_gb +=
193562306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_TXUNICASTFRAMES_GB_LO);
193662306a36Sopenharmony_ci
193762306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
193862306a36Sopenharmony_ci				MMC_TISR_TXMULTICASTFRAMES_GB_POS,
193962306a36Sopenharmony_ci				MMC_TISR_TXMULTICASTFRAMES_GB_LEN))
194062306a36Sopenharmony_ci		stats->txmulticastframes_gb +=
194162306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_TXMULTICASTFRAMES_GB_LO);
194262306a36Sopenharmony_ci
194362306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
194462306a36Sopenharmony_ci				MMC_TISR_TXBROADCASTFRAMES_GB_POS,
194562306a36Sopenharmony_ci				MMC_TISR_TXBROADCASTFRAMES_GB_LEN))
194662306a36Sopenharmony_ci		stats->txbroadcastframes_g +=
194762306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_TXBROADCASTFRAMES_GB_LO);
194862306a36Sopenharmony_ci
194962306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
195062306a36Sopenharmony_ci				MMC_TISR_TXUNDERFLOWERROR_POS,
195162306a36Sopenharmony_ci				MMC_TISR_TXUNDERFLOWERROR_LEN))
195262306a36Sopenharmony_ci		stats->txunderflowerror +=
195362306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_TXUNDERFLOWERROR_LO);
195462306a36Sopenharmony_ci
195562306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
195662306a36Sopenharmony_ci				MMC_TISR_TXOCTETCOUNT_G_POS,
195762306a36Sopenharmony_ci				MMC_TISR_TXOCTETCOUNT_G_LEN))
195862306a36Sopenharmony_ci		stats->txoctetcount_g +=
195962306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_TXOCTETCOUNT_G_LO);
196062306a36Sopenharmony_ci
196162306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
196262306a36Sopenharmony_ci				MMC_TISR_TXFRAMECOUNT_G_POS,
196362306a36Sopenharmony_ci				MMC_TISR_TXFRAMECOUNT_G_LEN))
196462306a36Sopenharmony_ci		stats->txframecount_g +=
196562306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_TXFRAMECOUNT_G_LO);
196662306a36Sopenharmony_ci
196762306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
196862306a36Sopenharmony_ci				MMC_TISR_TXPAUSEFRAMES_POS,
196962306a36Sopenharmony_ci				MMC_TISR_TXPAUSEFRAMES_LEN))
197062306a36Sopenharmony_ci		stats->txpauseframes +=
197162306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_TXPAUSEFRAMES_LO);
197262306a36Sopenharmony_ci
197362306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
197462306a36Sopenharmony_ci				MMC_TISR_TXVLANFRAMES_G_POS,
197562306a36Sopenharmony_ci				MMC_TISR_TXVLANFRAMES_G_LEN))
197662306a36Sopenharmony_ci		stats->txvlanframes_g +=
197762306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_TXVLANFRAMES_G_LO);
197862306a36Sopenharmony_ci}
197962306a36Sopenharmony_ci
198062306a36Sopenharmony_cistatic void xlgmac_rx_mmc_int(struct xlgmac_pdata *pdata)
198162306a36Sopenharmony_ci{
198262306a36Sopenharmony_ci	unsigned int mmc_isr = readl(pdata->mac_regs + MMC_RISR);
198362306a36Sopenharmony_ci	struct xlgmac_stats *stats = &pdata->stats;
198462306a36Sopenharmony_ci
198562306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
198662306a36Sopenharmony_ci				MMC_RISR_RXFRAMECOUNT_GB_POS,
198762306a36Sopenharmony_ci				MMC_RISR_RXFRAMECOUNT_GB_LEN))
198862306a36Sopenharmony_ci		stats->rxframecount_gb +=
198962306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_RXFRAMECOUNT_GB_LO);
199062306a36Sopenharmony_ci
199162306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
199262306a36Sopenharmony_ci				MMC_RISR_RXOCTETCOUNT_GB_POS,
199362306a36Sopenharmony_ci				MMC_RISR_RXOCTETCOUNT_GB_LEN))
199462306a36Sopenharmony_ci		stats->rxoctetcount_gb +=
199562306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_RXOCTETCOUNT_GB_LO);
199662306a36Sopenharmony_ci
199762306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
199862306a36Sopenharmony_ci				MMC_RISR_RXOCTETCOUNT_G_POS,
199962306a36Sopenharmony_ci				MMC_RISR_RXOCTETCOUNT_G_LEN))
200062306a36Sopenharmony_ci		stats->rxoctetcount_g +=
200162306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_RXOCTETCOUNT_G_LO);
200262306a36Sopenharmony_ci
200362306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
200462306a36Sopenharmony_ci				MMC_RISR_RXBROADCASTFRAMES_G_POS,
200562306a36Sopenharmony_ci				MMC_RISR_RXBROADCASTFRAMES_G_LEN))
200662306a36Sopenharmony_ci		stats->rxbroadcastframes_g +=
200762306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_RXBROADCASTFRAMES_G_LO);
200862306a36Sopenharmony_ci
200962306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
201062306a36Sopenharmony_ci				MMC_RISR_RXMULTICASTFRAMES_G_POS,
201162306a36Sopenharmony_ci				MMC_RISR_RXMULTICASTFRAMES_G_LEN))
201262306a36Sopenharmony_ci		stats->rxmulticastframes_g +=
201362306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_RXMULTICASTFRAMES_G_LO);
201462306a36Sopenharmony_ci
201562306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
201662306a36Sopenharmony_ci				MMC_RISR_RXCRCERROR_POS,
201762306a36Sopenharmony_ci				MMC_RISR_RXCRCERROR_LEN))
201862306a36Sopenharmony_ci		stats->rxcrcerror +=
201962306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_RXCRCERROR_LO);
202062306a36Sopenharmony_ci
202162306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
202262306a36Sopenharmony_ci				MMC_RISR_RXRUNTERROR_POS,
202362306a36Sopenharmony_ci				MMC_RISR_RXRUNTERROR_LEN))
202462306a36Sopenharmony_ci		stats->rxrunterror +=
202562306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_RXRUNTERROR);
202662306a36Sopenharmony_ci
202762306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
202862306a36Sopenharmony_ci				MMC_RISR_RXJABBERERROR_POS,
202962306a36Sopenharmony_ci				MMC_RISR_RXJABBERERROR_LEN))
203062306a36Sopenharmony_ci		stats->rxjabbererror +=
203162306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_RXJABBERERROR);
203262306a36Sopenharmony_ci
203362306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
203462306a36Sopenharmony_ci				MMC_RISR_RXUNDERSIZE_G_POS,
203562306a36Sopenharmony_ci				MMC_RISR_RXUNDERSIZE_G_LEN))
203662306a36Sopenharmony_ci		stats->rxundersize_g +=
203762306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_RXUNDERSIZE_G);
203862306a36Sopenharmony_ci
203962306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
204062306a36Sopenharmony_ci				MMC_RISR_RXOVERSIZE_G_POS,
204162306a36Sopenharmony_ci				MMC_RISR_RXOVERSIZE_G_LEN))
204262306a36Sopenharmony_ci		stats->rxoversize_g +=
204362306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_RXOVERSIZE_G);
204462306a36Sopenharmony_ci
204562306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
204662306a36Sopenharmony_ci				MMC_RISR_RX64OCTETS_GB_POS,
204762306a36Sopenharmony_ci				MMC_RISR_RX64OCTETS_GB_LEN))
204862306a36Sopenharmony_ci		stats->rx64octets_gb +=
204962306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_RX64OCTETS_GB_LO);
205062306a36Sopenharmony_ci
205162306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
205262306a36Sopenharmony_ci				MMC_RISR_RX65TO127OCTETS_GB_POS,
205362306a36Sopenharmony_ci				MMC_RISR_RX65TO127OCTETS_GB_LEN))
205462306a36Sopenharmony_ci		stats->rx65to127octets_gb +=
205562306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_RX65TO127OCTETS_GB_LO);
205662306a36Sopenharmony_ci
205762306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
205862306a36Sopenharmony_ci				MMC_RISR_RX128TO255OCTETS_GB_POS,
205962306a36Sopenharmony_ci				MMC_RISR_RX128TO255OCTETS_GB_LEN))
206062306a36Sopenharmony_ci		stats->rx128to255octets_gb +=
206162306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_RX128TO255OCTETS_GB_LO);
206262306a36Sopenharmony_ci
206362306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
206462306a36Sopenharmony_ci				MMC_RISR_RX256TO511OCTETS_GB_POS,
206562306a36Sopenharmony_ci				MMC_RISR_RX256TO511OCTETS_GB_LEN))
206662306a36Sopenharmony_ci		stats->rx256to511octets_gb +=
206762306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_RX256TO511OCTETS_GB_LO);
206862306a36Sopenharmony_ci
206962306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
207062306a36Sopenharmony_ci				MMC_RISR_RX512TO1023OCTETS_GB_POS,
207162306a36Sopenharmony_ci				MMC_RISR_RX512TO1023OCTETS_GB_LEN))
207262306a36Sopenharmony_ci		stats->rx512to1023octets_gb +=
207362306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_RX512TO1023OCTETS_GB_LO);
207462306a36Sopenharmony_ci
207562306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
207662306a36Sopenharmony_ci				MMC_RISR_RX1024TOMAXOCTETS_GB_POS,
207762306a36Sopenharmony_ci				MMC_RISR_RX1024TOMAXOCTETS_GB_LEN))
207862306a36Sopenharmony_ci		stats->rx1024tomaxoctets_gb +=
207962306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_RX1024TOMAXOCTETS_GB_LO);
208062306a36Sopenharmony_ci
208162306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
208262306a36Sopenharmony_ci				MMC_RISR_RXUNICASTFRAMES_G_POS,
208362306a36Sopenharmony_ci				MMC_RISR_RXUNICASTFRAMES_G_LEN))
208462306a36Sopenharmony_ci		stats->rxunicastframes_g +=
208562306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_RXUNICASTFRAMES_G_LO);
208662306a36Sopenharmony_ci
208762306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
208862306a36Sopenharmony_ci				MMC_RISR_RXLENGTHERROR_POS,
208962306a36Sopenharmony_ci				MMC_RISR_RXLENGTHERROR_LEN))
209062306a36Sopenharmony_ci		stats->rxlengtherror +=
209162306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_RXLENGTHERROR_LO);
209262306a36Sopenharmony_ci
209362306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
209462306a36Sopenharmony_ci				MMC_RISR_RXOUTOFRANGETYPE_POS,
209562306a36Sopenharmony_ci				MMC_RISR_RXOUTOFRANGETYPE_LEN))
209662306a36Sopenharmony_ci		stats->rxoutofrangetype +=
209762306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_RXOUTOFRANGETYPE_LO);
209862306a36Sopenharmony_ci
209962306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
210062306a36Sopenharmony_ci				MMC_RISR_RXPAUSEFRAMES_POS,
210162306a36Sopenharmony_ci				MMC_RISR_RXPAUSEFRAMES_LEN))
210262306a36Sopenharmony_ci		stats->rxpauseframes +=
210362306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_RXPAUSEFRAMES_LO);
210462306a36Sopenharmony_ci
210562306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
210662306a36Sopenharmony_ci				MMC_RISR_RXFIFOOVERFLOW_POS,
210762306a36Sopenharmony_ci				MMC_RISR_RXFIFOOVERFLOW_LEN))
210862306a36Sopenharmony_ci		stats->rxfifooverflow +=
210962306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_RXFIFOOVERFLOW_LO);
211062306a36Sopenharmony_ci
211162306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
211262306a36Sopenharmony_ci				MMC_RISR_RXVLANFRAMES_GB_POS,
211362306a36Sopenharmony_ci				MMC_RISR_RXVLANFRAMES_GB_LEN))
211462306a36Sopenharmony_ci		stats->rxvlanframes_gb +=
211562306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_RXVLANFRAMES_GB_LO);
211662306a36Sopenharmony_ci
211762306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS(mmc_isr,
211862306a36Sopenharmony_ci				MMC_RISR_RXWATCHDOGERROR_POS,
211962306a36Sopenharmony_ci				MMC_RISR_RXWATCHDOGERROR_LEN))
212062306a36Sopenharmony_ci		stats->rxwatchdogerror +=
212162306a36Sopenharmony_ci			xlgmac_mmc_read(pdata, MMC_RXWATCHDOGERROR);
212262306a36Sopenharmony_ci}
212362306a36Sopenharmony_ci
212462306a36Sopenharmony_cistatic void xlgmac_read_mmc_stats(struct xlgmac_pdata *pdata)
212562306a36Sopenharmony_ci{
212662306a36Sopenharmony_ci	struct xlgmac_stats *stats = &pdata->stats;
212762306a36Sopenharmony_ci	u32 regval;
212862306a36Sopenharmony_ci
212962306a36Sopenharmony_ci	/* Freeze counters */
213062306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MMC_CR);
213162306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MMC_CR_MCF_POS,
213262306a36Sopenharmony_ci				     MMC_CR_MCF_LEN, 1);
213362306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MMC_CR);
213462306a36Sopenharmony_ci
213562306a36Sopenharmony_ci	stats->txoctetcount_gb +=
213662306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_TXOCTETCOUNT_GB_LO);
213762306a36Sopenharmony_ci
213862306a36Sopenharmony_ci	stats->txframecount_gb +=
213962306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_TXFRAMECOUNT_GB_LO);
214062306a36Sopenharmony_ci
214162306a36Sopenharmony_ci	stats->txbroadcastframes_g +=
214262306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_TXBROADCASTFRAMES_G_LO);
214362306a36Sopenharmony_ci
214462306a36Sopenharmony_ci	stats->txmulticastframes_g +=
214562306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_TXMULTICASTFRAMES_G_LO);
214662306a36Sopenharmony_ci
214762306a36Sopenharmony_ci	stats->tx64octets_gb +=
214862306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_TX64OCTETS_GB_LO);
214962306a36Sopenharmony_ci
215062306a36Sopenharmony_ci	stats->tx65to127octets_gb +=
215162306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_TX65TO127OCTETS_GB_LO);
215262306a36Sopenharmony_ci
215362306a36Sopenharmony_ci	stats->tx128to255octets_gb +=
215462306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_TX128TO255OCTETS_GB_LO);
215562306a36Sopenharmony_ci
215662306a36Sopenharmony_ci	stats->tx256to511octets_gb +=
215762306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_TX256TO511OCTETS_GB_LO);
215862306a36Sopenharmony_ci
215962306a36Sopenharmony_ci	stats->tx512to1023octets_gb +=
216062306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_TX512TO1023OCTETS_GB_LO);
216162306a36Sopenharmony_ci
216262306a36Sopenharmony_ci	stats->tx1024tomaxoctets_gb +=
216362306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_TX1024TOMAXOCTETS_GB_LO);
216462306a36Sopenharmony_ci
216562306a36Sopenharmony_ci	stats->txunicastframes_gb +=
216662306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_TXUNICASTFRAMES_GB_LO);
216762306a36Sopenharmony_ci
216862306a36Sopenharmony_ci	stats->txmulticastframes_gb +=
216962306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_TXMULTICASTFRAMES_GB_LO);
217062306a36Sopenharmony_ci
217162306a36Sopenharmony_ci	stats->txbroadcastframes_g +=
217262306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_TXBROADCASTFRAMES_GB_LO);
217362306a36Sopenharmony_ci
217462306a36Sopenharmony_ci	stats->txunderflowerror +=
217562306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_TXUNDERFLOWERROR_LO);
217662306a36Sopenharmony_ci
217762306a36Sopenharmony_ci	stats->txoctetcount_g +=
217862306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_TXOCTETCOUNT_G_LO);
217962306a36Sopenharmony_ci
218062306a36Sopenharmony_ci	stats->txframecount_g +=
218162306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_TXFRAMECOUNT_G_LO);
218262306a36Sopenharmony_ci
218362306a36Sopenharmony_ci	stats->txpauseframes +=
218462306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_TXPAUSEFRAMES_LO);
218562306a36Sopenharmony_ci
218662306a36Sopenharmony_ci	stats->txvlanframes_g +=
218762306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_TXVLANFRAMES_G_LO);
218862306a36Sopenharmony_ci
218962306a36Sopenharmony_ci	stats->rxframecount_gb +=
219062306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_RXFRAMECOUNT_GB_LO);
219162306a36Sopenharmony_ci
219262306a36Sopenharmony_ci	stats->rxoctetcount_gb +=
219362306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_RXOCTETCOUNT_GB_LO);
219462306a36Sopenharmony_ci
219562306a36Sopenharmony_ci	stats->rxoctetcount_g +=
219662306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_RXOCTETCOUNT_G_LO);
219762306a36Sopenharmony_ci
219862306a36Sopenharmony_ci	stats->rxbroadcastframes_g +=
219962306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_RXBROADCASTFRAMES_G_LO);
220062306a36Sopenharmony_ci
220162306a36Sopenharmony_ci	stats->rxmulticastframes_g +=
220262306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_RXMULTICASTFRAMES_G_LO);
220362306a36Sopenharmony_ci
220462306a36Sopenharmony_ci	stats->rxcrcerror +=
220562306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_RXCRCERROR_LO);
220662306a36Sopenharmony_ci
220762306a36Sopenharmony_ci	stats->rxrunterror +=
220862306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_RXRUNTERROR);
220962306a36Sopenharmony_ci
221062306a36Sopenharmony_ci	stats->rxjabbererror +=
221162306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_RXJABBERERROR);
221262306a36Sopenharmony_ci
221362306a36Sopenharmony_ci	stats->rxundersize_g +=
221462306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_RXUNDERSIZE_G);
221562306a36Sopenharmony_ci
221662306a36Sopenharmony_ci	stats->rxoversize_g +=
221762306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_RXOVERSIZE_G);
221862306a36Sopenharmony_ci
221962306a36Sopenharmony_ci	stats->rx64octets_gb +=
222062306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_RX64OCTETS_GB_LO);
222162306a36Sopenharmony_ci
222262306a36Sopenharmony_ci	stats->rx65to127octets_gb +=
222362306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_RX65TO127OCTETS_GB_LO);
222462306a36Sopenharmony_ci
222562306a36Sopenharmony_ci	stats->rx128to255octets_gb +=
222662306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_RX128TO255OCTETS_GB_LO);
222762306a36Sopenharmony_ci
222862306a36Sopenharmony_ci	stats->rx256to511octets_gb +=
222962306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_RX256TO511OCTETS_GB_LO);
223062306a36Sopenharmony_ci
223162306a36Sopenharmony_ci	stats->rx512to1023octets_gb +=
223262306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_RX512TO1023OCTETS_GB_LO);
223362306a36Sopenharmony_ci
223462306a36Sopenharmony_ci	stats->rx1024tomaxoctets_gb +=
223562306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_RX1024TOMAXOCTETS_GB_LO);
223662306a36Sopenharmony_ci
223762306a36Sopenharmony_ci	stats->rxunicastframes_g +=
223862306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_RXUNICASTFRAMES_G_LO);
223962306a36Sopenharmony_ci
224062306a36Sopenharmony_ci	stats->rxlengtherror +=
224162306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_RXLENGTHERROR_LO);
224262306a36Sopenharmony_ci
224362306a36Sopenharmony_ci	stats->rxoutofrangetype +=
224462306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_RXOUTOFRANGETYPE_LO);
224562306a36Sopenharmony_ci
224662306a36Sopenharmony_ci	stats->rxpauseframes +=
224762306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_RXPAUSEFRAMES_LO);
224862306a36Sopenharmony_ci
224962306a36Sopenharmony_ci	stats->rxfifooverflow +=
225062306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_RXFIFOOVERFLOW_LO);
225162306a36Sopenharmony_ci
225262306a36Sopenharmony_ci	stats->rxvlanframes_gb +=
225362306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_RXVLANFRAMES_GB_LO);
225462306a36Sopenharmony_ci
225562306a36Sopenharmony_ci	stats->rxwatchdogerror +=
225662306a36Sopenharmony_ci		xlgmac_mmc_read(pdata, MMC_RXWATCHDOGERROR);
225762306a36Sopenharmony_ci
225862306a36Sopenharmony_ci	/* Un-freeze counters */
225962306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MMC_CR);
226062306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MMC_CR_MCF_POS,
226162306a36Sopenharmony_ci				     MMC_CR_MCF_LEN, 0);
226262306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MMC_CR);
226362306a36Sopenharmony_ci}
226462306a36Sopenharmony_ci
226562306a36Sopenharmony_cistatic void xlgmac_config_mmc(struct xlgmac_pdata *pdata)
226662306a36Sopenharmony_ci{
226762306a36Sopenharmony_ci	u32 regval;
226862306a36Sopenharmony_ci
226962306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MMC_CR);
227062306a36Sopenharmony_ci	/* Set counters to reset on read */
227162306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MMC_CR_ROR_POS,
227262306a36Sopenharmony_ci				     MMC_CR_ROR_LEN, 1);
227362306a36Sopenharmony_ci	/* Reset the counters */
227462306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MMC_CR_CR_POS,
227562306a36Sopenharmony_ci				     MMC_CR_CR_LEN, 1);
227662306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MMC_CR);
227762306a36Sopenharmony_ci}
227862306a36Sopenharmony_ci
227962306a36Sopenharmony_cistatic int xlgmac_write_rss_reg(struct xlgmac_pdata *pdata, unsigned int type,
228062306a36Sopenharmony_ci				unsigned int index, unsigned int val)
228162306a36Sopenharmony_ci{
228262306a36Sopenharmony_ci	unsigned int wait;
228362306a36Sopenharmony_ci	int ret = 0;
228462306a36Sopenharmony_ci	u32 regval;
228562306a36Sopenharmony_ci
228662306a36Sopenharmony_ci	mutex_lock(&pdata->rss_mutex);
228762306a36Sopenharmony_ci
228862306a36Sopenharmony_ci	regval = XLGMAC_GET_REG_BITS(readl(pdata->mac_regs + MAC_RSSAR),
228962306a36Sopenharmony_ci				     MAC_RSSAR_OB_POS, MAC_RSSAR_OB_LEN);
229062306a36Sopenharmony_ci	if (regval) {
229162306a36Sopenharmony_ci		ret = -EBUSY;
229262306a36Sopenharmony_ci		goto unlock;
229362306a36Sopenharmony_ci	}
229462306a36Sopenharmony_ci
229562306a36Sopenharmony_ci	writel(val, pdata->mac_regs + MAC_RSSDR);
229662306a36Sopenharmony_ci
229762306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_RSSAR);
229862306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_RSSAR_RSSIA_POS,
229962306a36Sopenharmony_ci				     MAC_RSSAR_RSSIA_LEN, index);
230062306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_RSSAR_ADDRT_POS,
230162306a36Sopenharmony_ci				     MAC_RSSAR_ADDRT_LEN, type);
230262306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_RSSAR_CT_POS,
230362306a36Sopenharmony_ci				     MAC_RSSAR_CT_LEN, 0);
230462306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_RSSAR_OB_POS,
230562306a36Sopenharmony_ci				     MAC_RSSAR_OB_LEN, 1);
230662306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_RSSAR);
230762306a36Sopenharmony_ci
230862306a36Sopenharmony_ci	wait = 1000;
230962306a36Sopenharmony_ci	while (wait--) {
231062306a36Sopenharmony_ci		regval = XLGMAC_GET_REG_BITS(readl(pdata->mac_regs + MAC_RSSAR),
231162306a36Sopenharmony_ci					     MAC_RSSAR_OB_POS,
231262306a36Sopenharmony_ci					     MAC_RSSAR_OB_LEN);
231362306a36Sopenharmony_ci		if (!regval)
231462306a36Sopenharmony_ci			goto unlock;
231562306a36Sopenharmony_ci
231662306a36Sopenharmony_ci		usleep_range(1000, 1500);
231762306a36Sopenharmony_ci	}
231862306a36Sopenharmony_ci
231962306a36Sopenharmony_ci	ret = -EBUSY;
232062306a36Sopenharmony_ci
232162306a36Sopenharmony_ciunlock:
232262306a36Sopenharmony_ci	mutex_unlock(&pdata->rss_mutex);
232362306a36Sopenharmony_ci
232462306a36Sopenharmony_ci	return ret;
232562306a36Sopenharmony_ci}
232662306a36Sopenharmony_ci
232762306a36Sopenharmony_cistatic int xlgmac_write_rss_hash_key(struct xlgmac_pdata *pdata)
232862306a36Sopenharmony_ci{
232962306a36Sopenharmony_ci	unsigned int key_regs = sizeof(pdata->rss_key) / sizeof(u32);
233062306a36Sopenharmony_ci	unsigned int *key = (unsigned int *)&pdata->rss_key;
233162306a36Sopenharmony_ci	int ret;
233262306a36Sopenharmony_ci
233362306a36Sopenharmony_ci	while (key_regs--) {
233462306a36Sopenharmony_ci		ret = xlgmac_write_rss_reg(pdata, XLGMAC_RSS_HASH_KEY_TYPE,
233562306a36Sopenharmony_ci					   key_regs, *key++);
233662306a36Sopenharmony_ci		if (ret)
233762306a36Sopenharmony_ci			return ret;
233862306a36Sopenharmony_ci	}
233962306a36Sopenharmony_ci
234062306a36Sopenharmony_ci	return 0;
234162306a36Sopenharmony_ci}
234262306a36Sopenharmony_ci
234362306a36Sopenharmony_cistatic int xlgmac_write_rss_lookup_table(struct xlgmac_pdata *pdata)
234462306a36Sopenharmony_ci{
234562306a36Sopenharmony_ci	unsigned int i;
234662306a36Sopenharmony_ci	int ret;
234762306a36Sopenharmony_ci
234862306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(pdata->rss_table); i++) {
234962306a36Sopenharmony_ci		ret = xlgmac_write_rss_reg(pdata,
235062306a36Sopenharmony_ci					   XLGMAC_RSS_LOOKUP_TABLE_TYPE, i,
235162306a36Sopenharmony_ci					   pdata->rss_table[i]);
235262306a36Sopenharmony_ci		if (ret)
235362306a36Sopenharmony_ci			return ret;
235462306a36Sopenharmony_ci	}
235562306a36Sopenharmony_ci
235662306a36Sopenharmony_ci	return 0;
235762306a36Sopenharmony_ci}
235862306a36Sopenharmony_ci
235962306a36Sopenharmony_cistatic int xlgmac_set_rss_hash_key(struct xlgmac_pdata *pdata, const u8 *key)
236062306a36Sopenharmony_ci{
236162306a36Sopenharmony_ci	memcpy(pdata->rss_key, key, sizeof(pdata->rss_key));
236262306a36Sopenharmony_ci
236362306a36Sopenharmony_ci	return xlgmac_write_rss_hash_key(pdata);
236462306a36Sopenharmony_ci}
236562306a36Sopenharmony_ci
236662306a36Sopenharmony_cistatic int xlgmac_set_rss_lookup_table(struct xlgmac_pdata *pdata,
236762306a36Sopenharmony_ci				       const u32 *table)
236862306a36Sopenharmony_ci{
236962306a36Sopenharmony_ci	unsigned int i;
237062306a36Sopenharmony_ci	u32 tval;
237162306a36Sopenharmony_ci
237262306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(pdata->rss_table); i++) {
237362306a36Sopenharmony_ci		tval = table[i];
237462306a36Sopenharmony_ci		pdata->rss_table[i] = XLGMAC_SET_REG_BITS(
237562306a36Sopenharmony_ci						pdata->rss_table[i],
237662306a36Sopenharmony_ci						MAC_RSSDR_DMCH_POS,
237762306a36Sopenharmony_ci						MAC_RSSDR_DMCH_LEN,
237862306a36Sopenharmony_ci						tval);
237962306a36Sopenharmony_ci	}
238062306a36Sopenharmony_ci
238162306a36Sopenharmony_ci	return xlgmac_write_rss_lookup_table(pdata);
238262306a36Sopenharmony_ci}
238362306a36Sopenharmony_ci
238462306a36Sopenharmony_cistatic int xlgmac_enable_rss(struct xlgmac_pdata *pdata)
238562306a36Sopenharmony_ci{
238662306a36Sopenharmony_ci	u32 regval;
238762306a36Sopenharmony_ci	int ret;
238862306a36Sopenharmony_ci
238962306a36Sopenharmony_ci	if (!pdata->hw_feat.rss)
239062306a36Sopenharmony_ci		return -EOPNOTSUPP;
239162306a36Sopenharmony_ci
239262306a36Sopenharmony_ci	/* Program the hash key */
239362306a36Sopenharmony_ci	ret = xlgmac_write_rss_hash_key(pdata);
239462306a36Sopenharmony_ci	if (ret)
239562306a36Sopenharmony_ci		return ret;
239662306a36Sopenharmony_ci
239762306a36Sopenharmony_ci	/* Program the lookup table */
239862306a36Sopenharmony_ci	ret = xlgmac_write_rss_lookup_table(pdata);
239962306a36Sopenharmony_ci	if (ret)
240062306a36Sopenharmony_ci		return ret;
240162306a36Sopenharmony_ci
240262306a36Sopenharmony_ci	/* Set the RSS options */
240362306a36Sopenharmony_ci	writel(pdata->rss_options, pdata->mac_regs + MAC_RSSCR);
240462306a36Sopenharmony_ci
240562306a36Sopenharmony_ci	/* Enable RSS */
240662306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_RSSCR);
240762306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_RSSCR_RSSE_POS,
240862306a36Sopenharmony_ci				     MAC_RSSCR_RSSE_LEN, 1);
240962306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_RSSCR);
241062306a36Sopenharmony_ci
241162306a36Sopenharmony_ci	return 0;
241262306a36Sopenharmony_ci}
241362306a36Sopenharmony_ci
241462306a36Sopenharmony_cistatic int xlgmac_disable_rss(struct xlgmac_pdata *pdata)
241562306a36Sopenharmony_ci{
241662306a36Sopenharmony_ci	u32 regval;
241762306a36Sopenharmony_ci
241862306a36Sopenharmony_ci	if (!pdata->hw_feat.rss)
241962306a36Sopenharmony_ci		return -EOPNOTSUPP;
242062306a36Sopenharmony_ci
242162306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_RSSCR);
242262306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_RSSCR_RSSE_POS,
242362306a36Sopenharmony_ci				     MAC_RSSCR_RSSE_LEN, 0);
242462306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_RSSCR);
242562306a36Sopenharmony_ci
242662306a36Sopenharmony_ci	return 0;
242762306a36Sopenharmony_ci}
242862306a36Sopenharmony_ci
242962306a36Sopenharmony_cistatic void xlgmac_config_rss(struct xlgmac_pdata *pdata)
243062306a36Sopenharmony_ci{
243162306a36Sopenharmony_ci	int ret;
243262306a36Sopenharmony_ci
243362306a36Sopenharmony_ci	if (!pdata->hw_feat.rss)
243462306a36Sopenharmony_ci		return;
243562306a36Sopenharmony_ci
243662306a36Sopenharmony_ci	if (pdata->netdev->features & NETIF_F_RXHASH)
243762306a36Sopenharmony_ci		ret = xlgmac_enable_rss(pdata);
243862306a36Sopenharmony_ci	else
243962306a36Sopenharmony_ci		ret = xlgmac_disable_rss(pdata);
244062306a36Sopenharmony_ci
244162306a36Sopenharmony_ci	if (ret)
244262306a36Sopenharmony_ci		netdev_err(pdata->netdev,
244362306a36Sopenharmony_ci			   "error configuring RSS, RSS disabled\n");
244462306a36Sopenharmony_ci}
244562306a36Sopenharmony_ci
244662306a36Sopenharmony_cistatic void xlgmac_enable_dma_interrupts(struct xlgmac_pdata *pdata)
244762306a36Sopenharmony_ci{
244862306a36Sopenharmony_ci	unsigned int dma_ch_isr, dma_ch_ier;
244962306a36Sopenharmony_ci	struct xlgmac_channel *channel;
245062306a36Sopenharmony_ci	unsigned int i;
245162306a36Sopenharmony_ci
245262306a36Sopenharmony_ci	channel = pdata->channel_head;
245362306a36Sopenharmony_ci	for (i = 0; i < pdata->channel_count; i++, channel++) {
245462306a36Sopenharmony_ci		/* Clear all the interrupts which are set */
245562306a36Sopenharmony_ci		dma_ch_isr = readl(XLGMAC_DMA_REG(channel, DMA_CH_SR));
245662306a36Sopenharmony_ci		writel(dma_ch_isr, XLGMAC_DMA_REG(channel, DMA_CH_SR));
245762306a36Sopenharmony_ci
245862306a36Sopenharmony_ci		/* Clear all interrupt enable bits */
245962306a36Sopenharmony_ci		dma_ch_ier = 0;
246062306a36Sopenharmony_ci
246162306a36Sopenharmony_ci		/* Enable following interrupts
246262306a36Sopenharmony_ci		 *   NIE  - Normal Interrupt Summary Enable
246362306a36Sopenharmony_ci		 *   AIE  - Abnormal Interrupt Summary Enable
246462306a36Sopenharmony_ci		 *   FBEE - Fatal Bus Error Enable
246562306a36Sopenharmony_ci		 */
246662306a36Sopenharmony_ci		dma_ch_ier = XLGMAC_SET_REG_BITS(dma_ch_ier,
246762306a36Sopenharmony_ci						 DMA_CH_IER_NIE_POS,
246862306a36Sopenharmony_ci					DMA_CH_IER_NIE_LEN, 1);
246962306a36Sopenharmony_ci		dma_ch_ier = XLGMAC_SET_REG_BITS(dma_ch_ier,
247062306a36Sopenharmony_ci						 DMA_CH_IER_AIE_POS,
247162306a36Sopenharmony_ci					DMA_CH_IER_AIE_LEN, 1);
247262306a36Sopenharmony_ci		dma_ch_ier = XLGMAC_SET_REG_BITS(dma_ch_ier,
247362306a36Sopenharmony_ci						 DMA_CH_IER_FBEE_POS,
247462306a36Sopenharmony_ci					DMA_CH_IER_FBEE_LEN, 1);
247562306a36Sopenharmony_ci
247662306a36Sopenharmony_ci		if (channel->tx_ring) {
247762306a36Sopenharmony_ci			/* Enable the following Tx interrupts
247862306a36Sopenharmony_ci			 *   TIE  - Transmit Interrupt Enable (unless using
247962306a36Sopenharmony_ci			 *          per channel interrupts)
248062306a36Sopenharmony_ci			 */
248162306a36Sopenharmony_ci			if (!pdata->per_channel_irq)
248262306a36Sopenharmony_ci				dma_ch_ier = XLGMAC_SET_REG_BITS(
248362306a36Sopenharmony_ci						dma_ch_ier,
248462306a36Sopenharmony_ci						DMA_CH_IER_TIE_POS,
248562306a36Sopenharmony_ci						DMA_CH_IER_TIE_LEN,
248662306a36Sopenharmony_ci						1);
248762306a36Sopenharmony_ci		}
248862306a36Sopenharmony_ci		if (channel->rx_ring) {
248962306a36Sopenharmony_ci			/* Enable following Rx interrupts
249062306a36Sopenharmony_ci			 *   RBUE - Receive Buffer Unavailable Enable
249162306a36Sopenharmony_ci			 *   RIE  - Receive Interrupt Enable (unless using
249262306a36Sopenharmony_ci			 *          per channel interrupts)
249362306a36Sopenharmony_ci			 */
249462306a36Sopenharmony_ci			dma_ch_ier = XLGMAC_SET_REG_BITS(
249562306a36Sopenharmony_ci					dma_ch_ier,
249662306a36Sopenharmony_ci					DMA_CH_IER_RBUE_POS,
249762306a36Sopenharmony_ci					DMA_CH_IER_RBUE_LEN,
249862306a36Sopenharmony_ci					1);
249962306a36Sopenharmony_ci			if (!pdata->per_channel_irq)
250062306a36Sopenharmony_ci				dma_ch_ier = XLGMAC_SET_REG_BITS(
250162306a36Sopenharmony_ci						dma_ch_ier,
250262306a36Sopenharmony_ci						DMA_CH_IER_RIE_POS,
250362306a36Sopenharmony_ci						DMA_CH_IER_RIE_LEN,
250462306a36Sopenharmony_ci						1);
250562306a36Sopenharmony_ci		}
250662306a36Sopenharmony_ci
250762306a36Sopenharmony_ci		writel(dma_ch_isr, XLGMAC_DMA_REG(channel, DMA_CH_IER));
250862306a36Sopenharmony_ci	}
250962306a36Sopenharmony_ci}
251062306a36Sopenharmony_ci
251162306a36Sopenharmony_cistatic void xlgmac_enable_mtl_interrupts(struct xlgmac_pdata *pdata)
251262306a36Sopenharmony_ci{
251362306a36Sopenharmony_ci	unsigned int q_count, i;
251462306a36Sopenharmony_ci	unsigned int mtl_q_isr;
251562306a36Sopenharmony_ci
251662306a36Sopenharmony_ci	q_count = max(pdata->hw_feat.tx_q_cnt, pdata->hw_feat.rx_q_cnt);
251762306a36Sopenharmony_ci	for (i = 0; i < q_count; i++) {
251862306a36Sopenharmony_ci		/* Clear all the interrupts which are set */
251962306a36Sopenharmony_ci		mtl_q_isr = readl(XLGMAC_MTL_REG(pdata, i, MTL_Q_ISR));
252062306a36Sopenharmony_ci		writel(mtl_q_isr, XLGMAC_MTL_REG(pdata, i, MTL_Q_ISR));
252162306a36Sopenharmony_ci
252262306a36Sopenharmony_ci		/* No MTL interrupts to be enabled */
252362306a36Sopenharmony_ci		writel(0, XLGMAC_MTL_REG(pdata, i, MTL_Q_IER));
252462306a36Sopenharmony_ci	}
252562306a36Sopenharmony_ci}
252662306a36Sopenharmony_ci
252762306a36Sopenharmony_cistatic void xlgmac_enable_mac_interrupts(struct xlgmac_pdata *pdata)
252862306a36Sopenharmony_ci{
252962306a36Sopenharmony_ci	unsigned int mac_ier = 0;
253062306a36Sopenharmony_ci	u32 regval;
253162306a36Sopenharmony_ci
253262306a36Sopenharmony_ci	/* Enable Timestamp interrupt */
253362306a36Sopenharmony_ci	mac_ier = XLGMAC_SET_REG_BITS(mac_ier, MAC_IER_TSIE_POS,
253462306a36Sopenharmony_ci				      MAC_IER_TSIE_LEN, 1);
253562306a36Sopenharmony_ci
253662306a36Sopenharmony_ci	writel(mac_ier, pdata->mac_regs + MAC_IER);
253762306a36Sopenharmony_ci
253862306a36Sopenharmony_ci	/* Enable all counter interrupts */
253962306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MMC_RIER);
254062306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MMC_RIER_ALL_INTERRUPTS_POS,
254162306a36Sopenharmony_ci				     MMC_RIER_ALL_INTERRUPTS_LEN, 0xffffffff);
254262306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MMC_RIER);
254362306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MMC_TIER);
254462306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MMC_TIER_ALL_INTERRUPTS_POS,
254562306a36Sopenharmony_ci				     MMC_TIER_ALL_INTERRUPTS_LEN, 0xffffffff);
254662306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MMC_TIER);
254762306a36Sopenharmony_ci}
254862306a36Sopenharmony_ci
254962306a36Sopenharmony_cistatic int xlgmac_set_xlgmii_25000_speed(struct xlgmac_pdata *pdata)
255062306a36Sopenharmony_ci{
255162306a36Sopenharmony_ci	u32 regval;
255262306a36Sopenharmony_ci
255362306a36Sopenharmony_ci	regval = XLGMAC_GET_REG_BITS(readl(pdata->mac_regs + MAC_TCR),
255462306a36Sopenharmony_ci				     MAC_TCR_SS_POS, MAC_TCR_SS_LEN);
255562306a36Sopenharmony_ci	if (regval == 0x1)
255662306a36Sopenharmony_ci		return 0;
255762306a36Sopenharmony_ci
255862306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_TCR);
255962306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_TCR_SS_POS,
256062306a36Sopenharmony_ci				     MAC_TCR_SS_LEN, 0x1);
256162306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_TCR);
256262306a36Sopenharmony_ci
256362306a36Sopenharmony_ci	return 0;
256462306a36Sopenharmony_ci}
256562306a36Sopenharmony_ci
256662306a36Sopenharmony_cistatic int xlgmac_set_xlgmii_40000_speed(struct xlgmac_pdata *pdata)
256762306a36Sopenharmony_ci{
256862306a36Sopenharmony_ci	u32 regval;
256962306a36Sopenharmony_ci
257062306a36Sopenharmony_ci	regval = XLGMAC_GET_REG_BITS(readl(pdata->mac_regs + MAC_TCR),
257162306a36Sopenharmony_ci				     MAC_TCR_SS_POS, MAC_TCR_SS_LEN);
257262306a36Sopenharmony_ci	if (regval == 0)
257362306a36Sopenharmony_ci		return 0;
257462306a36Sopenharmony_ci
257562306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_TCR);
257662306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_TCR_SS_POS,
257762306a36Sopenharmony_ci				     MAC_TCR_SS_LEN, 0);
257862306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_TCR);
257962306a36Sopenharmony_ci
258062306a36Sopenharmony_ci	return 0;
258162306a36Sopenharmony_ci}
258262306a36Sopenharmony_ci
258362306a36Sopenharmony_cistatic int xlgmac_set_xlgmii_50000_speed(struct xlgmac_pdata *pdata)
258462306a36Sopenharmony_ci{
258562306a36Sopenharmony_ci	u32 regval;
258662306a36Sopenharmony_ci
258762306a36Sopenharmony_ci	regval = XLGMAC_GET_REG_BITS(readl(pdata->mac_regs + MAC_TCR),
258862306a36Sopenharmony_ci				     MAC_TCR_SS_POS, MAC_TCR_SS_LEN);
258962306a36Sopenharmony_ci	if (regval == 0x2)
259062306a36Sopenharmony_ci		return 0;
259162306a36Sopenharmony_ci
259262306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_TCR);
259362306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_TCR_SS_POS,
259462306a36Sopenharmony_ci				     MAC_TCR_SS_LEN, 0x2);
259562306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_TCR);
259662306a36Sopenharmony_ci
259762306a36Sopenharmony_ci	return 0;
259862306a36Sopenharmony_ci}
259962306a36Sopenharmony_ci
260062306a36Sopenharmony_cistatic int xlgmac_set_xlgmii_100000_speed(struct xlgmac_pdata *pdata)
260162306a36Sopenharmony_ci{
260262306a36Sopenharmony_ci	u32 regval;
260362306a36Sopenharmony_ci
260462306a36Sopenharmony_ci	regval = XLGMAC_GET_REG_BITS(readl(pdata->mac_regs + MAC_TCR),
260562306a36Sopenharmony_ci				     MAC_TCR_SS_POS, MAC_TCR_SS_LEN);
260662306a36Sopenharmony_ci	if (regval == 0x3)
260762306a36Sopenharmony_ci		return 0;
260862306a36Sopenharmony_ci
260962306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + MAC_TCR);
261062306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, MAC_TCR_SS_POS,
261162306a36Sopenharmony_ci				     MAC_TCR_SS_LEN, 0x3);
261262306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + MAC_TCR);
261362306a36Sopenharmony_ci
261462306a36Sopenharmony_ci	return 0;
261562306a36Sopenharmony_ci}
261662306a36Sopenharmony_ci
261762306a36Sopenharmony_cistatic void xlgmac_config_mac_speed(struct xlgmac_pdata *pdata)
261862306a36Sopenharmony_ci{
261962306a36Sopenharmony_ci	switch (pdata->phy_speed) {
262062306a36Sopenharmony_ci	case SPEED_100000:
262162306a36Sopenharmony_ci		xlgmac_set_xlgmii_100000_speed(pdata);
262262306a36Sopenharmony_ci		break;
262362306a36Sopenharmony_ci
262462306a36Sopenharmony_ci	case SPEED_50000:
262562306a36Sopenharmony_ci		xlgmac_set_xlgmii_50000_speed(pdata);
262662306a36Sopenharmony_ci		break;
262762306a36Sopenharmony_ci
262862306a36Sopenharmony_ci	case SPEED_40000:
262962306a36Sopenharmony_ci		xlgmac_set_xlgmii_40000_speed(pdata);
263062306a36Sopenharmony_ci		break;
263162306a36Sopenharmony_ci
263262306a36Sopenharmony_ci	case SPEED_25000:
263362306a36Sopenharmony_ci		xlgmac_set_xlgmii_25000_speed(pdata);
263462306a36Sopenharmony_ci		break;
263562306a36Sopenharmony_ci	}
263662306a36Sopenharmony_ci}
263762306a36Sopenharmony_ci
263862306a36Sopenharmony_cistatic int xlgmac_dev_read(struct xlgmac_channel *channel)
263962306a36Sopenharmony_ci{
264062306a36Sopenharmony_ci	struct xlgmac_pdata *pdata = channel->pdata;
264162306a36Sopenharmony_ci	struct xlgmac_ring *ring = channel->rx_ring;
264262306a36Sopenharmony_ci	struct net_device *netdev = pdata->netdev;
264362306a36Sopenharmony_ci	struct xlgmac_desc_data *desc_data;
264462306a36Sopenharmony_ci	struct xlgmac_dma_desc *dma_desc;
264562306a36Sopenharmony_ci	struct xlgmac_pkt_info *pkt_info;
264662306a36Sopenharmony_ci	unsigned int err, etlt, l34t;
264762306a36Sopenharmony_ci
264862306a36Sopenharmony_ci	desc_data = XLGMAC_GET_DESC_DATA(ring, ring->cur);
264962306a36Sopenharmony_ci	dma_desc = desc_data->dma_desc;
265062306a36Sopenharmony_ci	pkt_info = &ring->pkt_info;
265162306a36Sopenharmony_ci
265262306a36Sopenharmony_ci	/* Check for data availability */
265362306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS_LE(dma_desc->desc3,
265462306a36Sopenharmony_ci				   RX_NORMAL_DESC3_OWN_POS,
265562306a36Sopenharmony_ci				   RX_NORMAL_DESC3_OWN_LEN))
265662306a36Sopenharmony_ci		return 1;
265762306a36Sopenharmony_ci
265862306a36Sopenharmony_ci	/* Make sure descriptor fields are read after reading the OWN bit */
265962306a36Sopenharmony_ci	dma_rmb();
266062306a36Sopenharmony_ci
266162306a36Sopenharmony_ci	if (netif_msg_rx_status(pdata))
266262306a36Sopenharmony_ci		xlgmac_dump_rx_desc(pdata, ring, ring->cur);
266362306a36Sopenharmony_ci
266462306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS_LE(dma_desc->desc3,
266562306a36Sopenharmony_ci				   RX_NORMAL_DESC3_CTXT_POS,
266662306a36Sopenharmony_ci				   RX_NORMAL_DESC3_CTXT_LEN)) {
266762306a36Sopenharmony_ci		/* Timestamp Context Descriptor */
266862306a36Sopenharmony_ci		xlgmac_get_rx_tstamp(pkt_info, dma_desc);
266962306a36Sopenharmony_ci
267062306a36Sopenharmony_ci		pkt_info->attributes = XLGMAC_SET_REG_BITS(
267162306a36Sopenharmony_ci					pkt_info->attributes,
267262306a36Sopenharmony_ci					RX_PACKET_ATTRIBUTES_CONTEXT_POS,
267362306a36Sopenharmony_ci					RX_PACKET_ATTRIBUTES_CONTEXT_LEN,
267462306a36Sopenharmony_ci					1);
267562306a36Sopenharmony_ci		pkt_info->attributes = XLGMAC_SET_REG_BITS(
267662306a36Sopenharmony_ci				pkt_info->attributes,
267762306a36Sopenharmony_ci				RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_POS,
267862306a36Sopenharmony_ci				RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_LEN,
267962306a36Sopenharmony_ci				0);
268062306a36Sopenharmony_ci		return 0;
268162306a36Sopenharmony_ci	}
268262306a36Sopenharmony_ci
268362306a36Sopenharmony_ci	/* Normal Descriptor, be sure Context Descriptor bit is off */
268462306a36Sopenharmony_ci	pkt_info->attributes = XLGMAC_SET_REG_BITS(
268562306a36Sopenharmony_ci				pkt_info->attributes,
268662306a36Sopenharmony_ci				RX_PACKET_ATTRIBUTES_CONTEXT_POS,
268762306a36Sopenharmony_ci				RX_PACKET_ATTRIBUTES_CONTEXT_LEN,
268862306a36Sopenharmony_ci				0);
268962306a36Sopenharmony_ci
269062306a36Sopenharmony_ci	/* Indicate if a Context Descriptor is next */
269162306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS_LE(dma_desc->desc3,
269262306a36Sopenharmony_ci				   RX_NORMAL_DESC3_CDA_POS,
269362306a36Sopenharmony_ci				   RX_NORMAL_DESC3_CDA_LEN))
269462306a36Sopenharmony_ci		pkt_info->attributes = XLGMAC_SET_REG_BITS(
269562306a36Sopenharmony_ci				pkt_info->attributes,
269662306a36Sopenharmony_ci				RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_POS,
269762306a36Sopenharmony_ci				RX_PACKET_ATTRIBUTES_CONTEXT_NEXT_LEN,
269862306a36Sopenharmony_ci				1);
269962306a36Sopenharmony_ci
270062306a36Sopenharmony_ci	/* Get the header length */
270162306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS_LE(dma_desc->desc3,
270262306a36Sopenharmony_ci				   RX_NORMAL_DESC3_FD_POS,
270362306a36Sopenharmony_ci				   RX_NORMAL_DESC3_FD_LEN)) {
270462306a36Sopenharmony_ci		desc_data->rx.hdr_len = XLGMAC_GET_REG_BITS_LE(dma_desc->desc2,
270562306a36Sopenharmony_ci							RX_NORMAL_DESC2_HL_POS,
270662306a36Sopenharmony_ci							RX_NORMAL_DESC2_HL_LEN);
270762306a36Sopenharmony_ci		if (desc_data->rx.hdr_len)
270862306a36Sopenharmony_ci			pdata->stats.rx_split_header_packets++;
270962306a36Sopenharmony_ci	}
271062306a36Sopenharmony_ci
271162306a36Sopenharmony_ci	/* Get the RSS hash */
271262306a36Sopenharmony_ci	if (XLGMAC_GET_REG_BITS_LE(dma_desc->desc3,
271362306a36Sopenharmony_ci				   RX_NORMAL_DESC3_RSV_POS,
271462306a36Sopenharmony_ci				   RX_NORMAL_DESC3_RSV_LEN)) {
271562306a36Sopenharmony_ci		pkt_info->attributes = XLGMAC_SET_REG_BITS(
271662306a36Sopenharmony_ci				pkt_info->attributes,
271762306a36Sopenharmony_ci				RX_PACKET_ATTRIBUTES_RSS_HASH_POS,
271862306a36Sopenharmony_ci				RX_PACKET_ATTRIBUTES_RSS_HASH_LEN,
271962306a36Sopenharmony_ci				1);
272062306a36Sopenharmony_ci
272162306a36Sopenharmony_ci		pkt_info->rss_hash = le32_to_cpu(dma_desc->desc1);
272262306a36Sopenharmony_ci
272362306a36Sopenharmony_ci		l34t = XLGMAC_GET_REG_BITS_LE(dma_desc->desc3,
272462306a36Sopenharmony_ci					      RX_NORMAL_DESC3_L34T_POS,
272562306a36Sopenharmony_ci					  RX_NORMAL_DESC3_L34T_LEN);
272662306a36Sopenharmony_ci		switch (l34t) {
272762306a36Sopenharmony_ci		case RX_DESC3_L34T_IPV4_TCP:
272862306a36Sopenharmony_ci		case RX_DESC3_L34T_IPV4_UDP:
272962306a36Sopenharmony_ci		case RX_DESC3_L34T_IPV6_TCP:
273062306a36Sopenharmony_ci		case RX_DESC3_L34T_IPV6_UDP:
273162306a36Sopenharmony_ci			pkt_info->rss_hash_type = PKT_HASH_TYPE_L4;
273262306a36Sopenharmony_ci			break;
273362306a36Sopenharmony_ci		default:
273462306a36Sopenharmony_ci			pkt_info->rss_hash_type = PKT_HASH_TYPE_L3;
273562306a36Sopenharmony_ci		}
273662306a36Sopenharmony_ci	}
273762306a36Sopenharmony_ci
273862306a36Sopenharmony_ci	/* Get the pkt_info length */
273962306a36Sopenharmony_ci	desc_data->rx.len = XLGMAC_GET_REG_BITS_LE(dma_desc->desc3,
274062306a36Sopenharmony_ci					RX_NORMAL_DESC3_PL_POS,
274162306a36Sopenharmony_ci					RX_NORMAL_DESC3_PL_LEN);
274262306a36Sopenharmony_ci
274362306a36Sopenharmony_ci	if (!XLGMAC_GET_REG_BITS_LE(dma_desc->desc3,
274462306a36Sopenharmony_ci				    RX_NORMAL_DESC3_LD_POS,
274562306a36Sopenharmony_ci				    RX_NORMAL_DESC3_LD_LEN)) {
274662306a36Sopenharmony_ci		/* Not all the data has been transferred for this pkt_info */
274762306a36Sopenharmony_ci		pkt_info->attributes = XLGMAC_SET_REG_BITS(
274862306a36Sopenharmony_ci				pkt_info->attributes,
274962306a36Sopenharmony_ci				RX_PACKET_ATTRIBUTES_INCOMPLETE_POS,
275062306a36Sopenharmony_ci				RX_PACKET_ATTRIBUTES_INCOMPLETE_LEN,
275162306a36Sopenharmony_ci				1);
275262306a36Sopenharmony_ci		return 0;
275362306a36Sopenharmony_ci	}
275462306a36Sopenharmony_ci
275562306a36Sopenharmony_ci	/* This is the last of the data for this pkt_info */
275662306a36Sopenharmony_ci	pkt_info->attributes = XLGMAC_SET_REG_BITS(
275762306a36Sopenharmony_ci			pkt_info->attributes,
275862306a36Sopenharmony_ci			RX_PACKET_ATTRIBUTES_INCOMPLETE_POS,
275962306a36Sopenharmony_ci			RX_PACKET_ATTRIBUTES_INCOMPLETE_LEN,
276062306a36Sopenharmony_ci			0);
276162306a36Sopenharmony_ci
276262306a36Sopenharmony_ci	/* Set checksum done indicator as appropriate */
276362306a36Sopenharmony_ci	if (netdev->features & NETIF_F_RXCSUM)
276462306a36Sopenharmony_ci		pkt_info->attributes = XLGMAC_SET_REG_BITS(
276562306a36Sopenharmony_ci				pkt_info->attributes,
276662306a36Sopenharmony_ci				RX_PACKET_ATTRIBUTES_CSUM_DONE_POS,
276762306a36Sopenharmony_ci				RX_PACKET_ATTRIBUTES_CSUM_DONE_LEN,
276862306a36Sopenharmony_ci				1);
276962306a36Sopenharmony_ci
277062306a36Sopenharmony_ci	/* Check for errors (only valid in last descriptor) */
277162306a36Sopenharmony_ci	err = XLGMAC_GET_REG_BITS_LE(dma_desc->desc3,
277262306a36Sopenharmony_ci				     RX_NORMAL_DESC3_ES_POS,
277362306a36Sopenharmony_ci				     RX_NORMAL_DESC3_ES_LEN);
277462306a36Sopenharmony_ci	etlt = XLGMAC_GET_REG_BITS_LE(dma_desc->desc3,
277562306a36Sopenharmony_ci				      RX_NORMAL_DESC3_ETLT_POS,
277662306a36Sopenharmony_ci				      RX_NORMAL_DESC3_ETLT_LEN);
277762306a36Sopenharmony_ci	netif_dbg(pdata, rx_status, netdev, "err=%u, etlt=%#x\n", err, etlt);
277862306a36Sopenharmony_ci
277962306a36Sopenharmony_ci	if (!err || !etlt) {
278062306a36Sopenharmony_ci		/* No error if err is 0 or etlt is 0 */
278162306a36Sopenharmony_ci		if ((etlt == 0x09) &&
278262306a36Sopenharmony_ci		    (netdev->features & NETIF_F_HW_VLAN_CTAG_RX)) {
278362306a36Sopenharmony_ci			pkt_info->attributes = XLGMAC_SET_REG_BITS(
278462306a36Sopenharmony_ci					pkt_info->attributes,
278562306a36Sopenharmony_ci					RX_PACKET_ATTRIBUTES_VLAN_CTAG_POS,
278662306a36Sopenharmony_ci					RX_PACKET_ATTRIBUTES_VLAN_CTAG_LEN,
278762306a36Sopenharmony_ci					1);
278862306a36Sopenharmony_ci			pkt_info->vlan_ctag =
278962306a36Sopenharmony_ci				XLGMAC_GET_REG_BITS_LE(dma_desc->desc0,
279062306a36Sopenharmony_ci						       RX_NORMAL_DESC0_OVT_POS,
279162306a36Sopenharmony_ci						   RX_NORMAL_DESC0_OVT_LEN);
279262306a36Sopenharmony_ci			netif_dbg(pdata, rx_status, netdev, "vlan-ctag=%#06x\n",
279362306a36Sopenharmony_ci				  pkt_info->vlan_ctag);
279462306a36Sopenharmony_ci		}
279562306a36Sopenharmony_ci	} else {
279662306a36Sopenharmony_ci		if ((etlt == 0x05) || (etlt == 0x06))
279762306a36Sopenharmony_ci			pkt_info->attributes = XLGMAC_SET_REG_BITS(
279862306a36Sopenharmony_ci					pkt_info->attributes,
279962306a36Sopenharmony_ci					RX_PACKET_ATTRIBUTES_CSUM_DONE_POS,
280062306a36Sopenharmony_ci					RX_PACKET_ATTRIBUTES_CSUM_DONE_LEN,
280162306a36Sopenharmony_ci					0);
280262306a36Sopenharmony_ci		else
280362306a36Sopenharmony_ci			pkt_info->errors = XLGMAC_SET_REG_BITS(
280462306a36Sopenharmony_ci					pkt_info->errors,
280562306a36Sopenharmony_ci					RX_PACKET_ERRORS_FRAME_POS,
280662306a36Sopenharmony_ci					RX_PACKET_ERRORS_FRAME_LEN,
280762306a36Sopenharmony_ci					1);
280862306a36Sopenharmony_ci	}
280962306a36Sopenharmony_ci
281062306a36Sopenharmony_ci	XLGMAC_PR("%s - descriptor=%u (cur=%d)\n", channel->name,
281162306a36Sopenharmony_ci		  ring->cur & (ring->dma_desc_count - 1), ring->cur);
281262306a36Sopenharmony_ci
281362306a36Sopenharmony_ci	return 0;
281462306a36Sopenharmony_ci}
281562306a36Sopenharmony_ci
281662306a36Sopenharmony_cistatic int xlgmac_enable_int(struct xlgmac_channel *channel,
281762306a36Sopenharmony_ci			     enum xlgmac_int int_id)
281862306a36Sopenharmony_ci{
281962306a36Sopenharmony_ci	unsigned int dma_ch_ier;
282062306a36Sopenharmony_ci
282162306a36Sopenharmony_ci	dma_ch_ier = readl(XLGMAC_DMA_REG(channel, DMA_CH_IER));
282262306a36Sopenharmony_ci
282362306a36Sopenharmony_ci	switch (int_id) {
282462306a36Sopenharmony_ci	case XLGMAC_INT_DMA_CH_SR_TI:
282562306a36Sopenharmony_ci		dma_ch_ier = XLGMAC_SET_REG_BITS(
282662306a36Sopenharmony_ci				dma_ch_ier, DMA_CH_IER_TIE_POS,
282762306a36Sopenharmony_ci				DMA_CH_IER_TIE_LEN, 1);
282862306a36Sopenharmony_ci		break;
282962306a36Sopenharmony_ci	case XLGMAC_INT_DMA_CH_SR_TPS:
283062306a36Sopenharmony_ci		dma_ch_ier = XLGMAC_SET_REG_BITS(
283162306a36Sopenharmony_ci				dma_ch_ier, DMA_CH_IER_TXSE_POS,
283262306a36Sopenharmony_ci				DMA_CH_IER_TXSE_LEN, 1);
283362306a36Sopenharmony_ci		break;
283462306a36Sopenharmony_ci	case XLGMAC_INT_DMA_CH_SR_TBU:
283562306a36Sopenharmony_ci		dma_ch_ier = XLGMAC_SET_REG_BITS(
283662306a36Sopenharmony_ci				dma_ch_ier, DMA_CH_IER_TBUE_POS,
283762306a36Sopenharmony_ci				DMA_CH_IER_TBUE_LEN, 1);
283862306a36Sopenharmony_ci		break;
283962306a36Sopenharmony_ci	case XLGMAC_INT_DMA_CH_SR_RI:
284062306a36Sopenharmony_ci		dma_ch_ier = XLGMAC_SET_REG_BITS(
284162306a36Sopenharmony_ci				dma_ch_ier, DMA_CH_IER_RIE_POS,
284262306a36Sopenharmony_ci				DMA_CH_IER_RIE_LEN, 1);
284362306a36Sopenharmony_ci		break;
284462306a36Sopenharmony_ci	case XLGMAC_INT_DMA_CH_SR_RBU:
284562306a36Sopenharmony_ci		dma_ch_ier = XLGMAC_SET_REG_BITS(
284662306a36Sopenharmony_ci				dma_ch_ier, DMA_CH_IER_RBUE_POS,
284762306a36Sopenharmony_ci				DMA_CH_IER_RBUE_LEN, 1);
284862306a36Sopenharmony_ci		break;
284962306a36Sopenharmony_ci	case XLGMAC_INT_DMA_CH_SR_RPS:
285062306a36Sopenharmony_ci		dma_ch_ier = XLGMAC_SET_REG_BITS(
285162306a36Sopenharmony_ci				dma_ch_ier, DMA_CH_IER_RSE_POS,
285262306a36Sopenharmony_ci				DMA_CH_IER_RSE_LEN, 1);
285362306a36Sopenharmony_ci		break;
285462306a36Sopenharmony_ci	case XLGMAC_INT_DMA_CH_SR_TI_RI:
285562306a36Sopenharmony_ci		dma_ch_ier = XLGMAC_SET_REG_BITS(
285662306a36Sopenharmony_ci				dma_ch_ier, DMA_CH_IER_TIE_POS,
285762306a36Sopenharmony_ci				DMA_CH_IER_TIE_LEN, 1);
285862306a36Sopenharmony_ci		dma_ch_ier = XLGMAC_SET_REG_BITS(
285962306a36Sopenharmony_ci				dma_ch_ier, DMA_CH_IER_RIE_POS,
286062306a36Sopenharmony_ci				DMA_CH_IER_RIE_LEN, 1);
286162306a36Sopenharmony_ci		break;
286262306a36Sopenharmony_ci	case XLGMAC_INT_DMA_CH_SR_FBE:
286362306a36Sopenharmony_ci		dma_ch_ier = XLGMAC_SET_REG_BITS(
286462306a36Sopenharmony_ci				dma_ch_ier, DMA_CH_IER_FBEE_POS,
286562306a36Sopenharmony_ci				DMA_CH_IER_FBEE_LEN, 1);
286662306a36Sopenharmony_ci		break;
286762306a36Sopenharmony_ci	case XLGMAC_INT_DMA_ALL:
286862306a36Sopenharmony_ci		dma_ch_ier |= channel->saved_ier;
286962306a36Sopenharmony_ci		break;
287062306a36Sopenharmony_ci	default:
287162306a36Sopenharmony_ci		return -1;
287262306a36Sopenharmony_ci	}
287362306a36Sopenharmony_ci
287462306a36Sopenharmony_ci	writel(dma_ch_ier, XLGMAC_DMA_REG(channel, DMA_CH_IER));
287562306a36Sopenharmony_ci
287662306a36Sopenharmony_ci	return 0;
287762306a36Sopenharmony_ci}
287862306a36Sopenharmony_ci
287962306a36Sopenharmony_cistatic int xlgmac_disable_int(struct xlgmac_channel *channel,
288062306a36Sopenharmony_ci			      enum xlgmac_int int_id)
288162306a36Sopenharmony_ci{
288262306a36Sopenharmony_ci	unsigned int dma_ch_ier;
288362306a36Sopenharmony_ci
288462306a36Sopenharmony_ci	dma_ch_ier = readl(XLGMAC_DMA_REG(channel, DMA_CH_IER));
288562306a36Sopenharmony_ci
288662306a36Sopenharmony_ci	switch (int_id) {
288762306a36Sopenharmony_ci	case XLGMAC_INT_DMA_CH_SR_TI:
288862306a36Sopenharmony_ci		dma_ch_ier = XLGMAC_SET_REG_BITS(
288962306a36Sopenharmony_ci				dma_ch_ier, DMA_CH_IER_TIE_POS,
289062306a36Sopenharmony_ci				DMA_CH_IER_TIE_LEN, 0);
289162306a36Sopenharmony_ci		break;
289262306a36Sopenharmony_ci	case XLGMAC_INT_DMA_CH_SR_TPS:
289362306a36Sopenharmony_ci		dma_ch_ier = XLGMAC_SET_REG_BITS(
289462306a36Sopenharmony_ci				dma_ch_ier, DMA_CH_IER_TXSE_POS,
289562306a36Sopenharmony_ci				DMA_CH_IER_TXSE_LEN, 0);
289662306a36Sopenharmony_ci		break;
289762306a36Sopenharmony_ci	case XLGMAC_INT_DMA_CH_SR_TBU:
289862306a36Sopenharmony_ci		dma_ch_ier = XLGMAC_SET_REG_BITS(
289962306a36Sopenharmony_ci				dma_ch_ier, DMA_CH_IER_TBUE_POS,
290062306a36Sopenharmony_ci				DMA_CH_IER_TBUE_LEN, 0);
290162306a36Sopenharmony_ci		break;
290262306a36Sopenharmony_ci	case XLGMAC_INT_DMA_CH_SR_RI:
290362306a36Sopenharmony_ci		dma_ch_ier = XLGMAC_SET_REG_BITS(
290462306a36Sopenharmony_ci				dma_ch_ier, DMA_CH_IER_RIE_POS,
290562306a36Sopenharmony_ci				DMA_CH_IER_RIE_LEN, 0);
290662306a36Sopenharmony_ci		break;
290762306a36Sopenharmony_ci	case XLGMAC_INT_DMA_CH_SR_RBU:
290862306a36Sopenharmony_ci		dma_ch_ier = XLGMAC_SET_REG_BITS(
290962306a36Sopenharmony_ci				dma_ch_ier, DMA_CH_IER_RBUE_POS,
291062306a36Sopenharmony_ci				DMA_CH_IER_RBUE_LEN, 0);
291162306a36Sopenharmony_ci		break;
291262306a36Sopenharmony_ci	case XLGMAC_INT_DMA_CH_SR_RPS:
291362306a36Sopenharmony_ci		dma_ch_ier = XLGMAC_SET_REG_BITS(
291462306a36Sopenharmony_ci				dma_ch_ier, DMA_CH_IER_RSE_POS,
291562306a36Sopenharmony_ci				DMA_CH_IER_RSE_LEN, 0);
291662306a36Sopenharmony_ci		break;
291762306a36Sopenharmony_ci	case XLGMAC_INT_DMA_CH_SR_TI_RI:
291862306a36Sopenharmony_ci		dma_ch_ier = XLGMAC_SET_REG_BITS(
291962306a36Sopenharmony_ci				dma_ch_ier, DMA_CH_IER_TIE_POS,
292062306a36Sopenharmony_ci				DMA_CH_IER_TIE_LEN, 0);
292162306a36Sopenharmony_ci		dma_ch_ier = XLGMAC_SET_REG_BITS(
292262306a36Sopenharmony_ci				dma_ch_ier, DMA_CH_IER_RIE_POS,
292362306a36Sopenharmony_ci				DMA_CH_IER_RIE_LEN, 0);
292462306a36Sopenharmony_ci		break;
292562306a36Sopenharmony_ci	case XLGMAC_INT_DMA_CH_SR_FBE:
292662306a36Sopenharmony_ci		dma_ch_ier = XLGMAC_SET_REG_BITS(
292762306a36Sopenharmony_ci				dma_ch_ier, DMA_CH_IER_FBEE_POS,
292862306a36Sopenharmony_ci				DMA_CH_IER_FBEE_LEN, 0);
292962306a36Sopenharmony_ci		break;
293062306a36Sopenharmony_ci	case XLGMAC_INT_DMA_ALL:
293162306a36Sopenharmony_ci		channel->saved_ier = dma_ch_ier & XLGMAC_DMA_INTERRUPT_MASK;
293262306a36Sopenharmony_ci		dma_ch_ier &= ~XLGMAC_DMA_INTERRUPT_MASK;
293362306a36Sopenharmony_ci		break;
293462306a36Sopenharmony_ci	default:
293562306a36Sopenharmony_ci		return -1;
293662306a36Sopenharmony_ci	}
293762306a36Sopenharmony_ci
293862306a36Sopenharmony_ci	writel(dma_ch_ier, XLGMAC_DMA_REG(channel, DMA_CH_IER));
293962306a36Sopenharmony_ci
294062306a36Sopenharmony_ci	return 0;
294162306a36Sopenharmony_ci}
294262306a36Sopenharmony_ci
294362306a36Sopenharmony_cistatic int xlgmac_flush_tx_queues(struct xlgmac_pdata *pdata)
294462306a36Sopenharmony_ci{
294562306a36Sopenharmony_ci	unsigned int i, count;
294662306a36Sopenharmony_ci	u32 regval;
294762306a36Sopenharmony_ci
294862306a36Sopenharmony_ci	for (i = 0; i < pdata->tx_q_count; i++) {
294962306a36Sopenharmony_ci		regval = readl(XLGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR));
295062306a36Sopenharmony_ci		regval = XLGMAC_SET_REG_BITS(regval, MTL_Q_TQOMR_FTQ_POS,
295162306a36Sopenharmony_ci					     MTL_Q_TQOMR_FTQ_LEN, 1);
295262306a36Sopenharmony_ci		writel(regval, XLGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR));
295362306a36Sopenharmony_ci	}
295462306a36Sopenharmony_ci
295562306a36Sopenharmony_ci	/* Poll Until Poll Condition */
295662306a36Sopenharmony_ci	for (i = 0; i < pdata->tx_q_count; i++) {
295762306a36Sopenharmony_ci		count = 2000;
295862306a36Sopenharmony_ci		regval = readl(XLGMAC_MTL_REG(pdata, i, MTL_Q_TQOMR));
295962306a36Sopenharmony_ci		regval = XLGMAC_GET_REG_BITS(regval, MTL_Q_TQOMR_FTQ_POS,
296062306a36Sopenharmony_ci					     MTL_Q_TQOMR_FTQ_LEN);
296162306a36Sopenharmony_ci		while (--count && regval)
296262306a36Sopenharmony_ci			usleep_range(500, 600);
296362306a36Sopenharmony_ci
296462306a36Sopenharmony_ci		if (!count)
296562306a36Sopenharmony_ci			return -EBUSY;
296662306a36Sopenharmony_ci	}
296762306a36Sopenharmony_ci
296862306a36Sopenharmony_ci	return 0;
296962306a36Sopenharmony_ci}
297062306a36Sopenharmony_ci
297162306a36Sopenharmony_cistatic void xlgmac_config_dma_bus(struct xlgmac_pdata *pdata)
297262306a36Sopenharmony_ci{
297362306a36Sopenharmony_ci	u32 regval;
297462306a36Sopenharmony_ci
297562306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + DMA_SBMR);
297662306a36Sopenharmony_ci	/* Set enhanced addressing mode */
297762306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, DMA_SBMR_EAME_POS,
297862306a36Sopenharmony_ci				     DMA_SBMR_EAME_LEN, 1);
297962306a36Sopenharmony_ci	/* Set the System Bus mode */
298062306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, DMA_SBMR_UNDEF_POS,
298162306a36Sopenharmony_ci				     DMA_SBMR_UNDEF_LEN, 1);
298262306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, DMA_SBMR_BLEN_256_POS,
298362306a36Sopenharmony_ci				     DMA_SBMR_BLEN_256_LEN, 1);
298462306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + DMA_SBMR);
298562306a36Sopenharmony_ci}
298662306a36Sopenharmony_ci
298762306a36Sopenharmony_cistatic int xlgmac_hw_init(struct xlgmac_pdata *pdata)
298862306a36Sopenharmony_ci{
298962306a36Sopenharmony_ci	struct xlgmac_desc_ops *desc_ops = &pdata->desc_ops;
299062306a36Sopenharmony_ci	int ret;
299162306a36Sopenharmony_ci
299262306a36Sopenharmony_ci	/* Flush Tx queues */
299362306a36Sopenharmony_ci	ret = xlgmac_flush_tx_queues(pdata);
299462306a36Sopenharmony_ci	if (ret)
299562306a36Sopenharmony_ci		return ret;
299662306a36Sopenharmony_ci
299762306a36Sopenharmony_ci	/* Initialize DMA related features */
299862306a36Sopenharmony_ci	xlgmac_config_dma_bus(pdata);
299962306a36Sopenharmony_ci	xlgmac_config_osp_mode(pdata);
300062306a36Sopenharmony_ci	xlgmac_config_pblx8(pdata);
300162306a36Sopenharmony_ci	xlgmac_config_tx_pbl_val(pdata);
300262306a36Sopenharmony_ci	xlgmac_config_rx_pbl_val(pdata);
300362306a36Sopenharmony_ci	xlgmac_config_rx_coalesce(pdata);
300462306a36Sopenharmony_ci	xlgmac_config_tx_coalesce(pdata);
300562306a36Sopenharmony_ci	xlgmac_config_rx_buffer_size(pdata);
300662306a36Sopenharmony_ci	xlgmac_config_tso_mode(pdata);
300762306a36Sopenharmony_ci	xlgmac_config_sph_mode(pdata);
300862306a36Sopenharmony_ci	xlgmac_config_rss(pdata);
300962306a36Sopenharmony_ci	desc_ops->tx_desc_init(pdata);
301062306a36Sopenharmony_ci	desc_ops->rx_desc_init(pdata);
301162306a36Sopenharmony_ci	xlgmac_enable_dma_interrupts(pdata);
301262306a36Sopenharmony_ci
301362306a36Sopenharmony_ci	/* Initialize MTL related features */
301462306a36Sopenharmony_ci	xlgmac_config_mtl_mode(pdata);
301562306a36Sopenharmony_ci	xlgmac_config_queue_mapping(pdata);
301662306a36Sopenharmony_ci	xlgmac_config_tsf_mode(pdata, pdata->tx_sf_mode);
301762306a36Sopenharmony_ci	xlgmac_config_rsf_mode(pdata, pdata->rx_sf_mode);
301862306a36Sopenharmony_ci	xlgmac_config_tx_threshold(pdata, pdata->tx_threshold);
301962306a36Sopenharmony_ci	xlgmac_config_rx_threshold(pdata, pdata->rx_threshold);
302062306a36Sopenharmony_ci	xlgmac_config_tx_fifo_size(pdata);
302162306a36Sopenharmony_ci	xlgmac_config_rx_fifo_size(pdata);
302262306a36Sopenharmony_ci	xlgmac_config_flow_control_threshold(pdata);
302362306a36Sopenharmony_ci	xlgmac_config_rx_fep_enable(pdata);
302462306a36Sopenharmony_ci	xlgmac_config_rx_fup_enable(pdata);
302562306a36Sopenharmony_ci	xlgmac_enable_mtl_interrupts(pdata);
302662306a36Sopenharmony_ci
302762306a36Sopenharmony_ci	/* Initialize MAC related features */
302862306a36Sopenharmony_ci	xlgmac_config_mac_address(pdata);
302962306a36Sopenharmony_ci	xlgmac_config_rx_mode(pdata);
303062306a36Sopenharmony_ci	xlgmac_config_jumbo_enable(pdata);
303162306a36Sopenharmony_ci	xlgmac_config_flow_control(pdata);
303262306a36Sopenharmony_ci	xlgmac_config_mac_speed(pdata);
303362306a36Sopenharmony_ci	xlgmac_config_checksum_offload(pdata);
303462306a36Sopenharmony_ci	xlgmac_config_vlan_support(pdata);
303562306a36Sopenharmony_ci	xlgmac_config_mmc(pdata);
303662306a36Sopenharmony_ci	xlgmac_enable_mac_interrupts(pdata);
303762306a36Sopenharmony_ci
303862306a36Sopenharmony_ci	return 0;
303962306a36Sopenharmony_ci}
304062306a36Sopenharmony_ci
304162306a36Sopenharmony_cistatic int xlgmac_hw_exit(struct xlgmac_pdata *pdata)
304262306a36Sopenharmony_ci{
304362306a36Sopenharmony_ci	unsigned int count = 2000;
304462306a36Sopenharmony_ci	u32 regval;
304562306a36Sopenharmony_ci
304662306a36Sopenharmony_ci	/* Issue a software reset */
304762306a36Sopenharmony_ci	regval = readl(pdata->mac_regs + DMA_MR);
304862306a36Sopenharmony_ci	regval = XLGMAC_SET_REG_BITS(regval, DMA_MR_SWR_POS,
304962306a36Sopenharmony_ci				     DMA_MR_SWR_LEN, 1);
305062306a36Sopenharmony_ci	writel(regval, pdata->mac_regs + DMA_MR);
305162306a36Sopenharmony_ci	usleep_range(10, 15);
305262306a36Sopenharmony_ci
305362306a36Sopenharmony_ci	/* Poll Until Poll Condition */
305462306a36Sopenharmony_ci	while (--count &&
305562306a36Sopenharmony_ci	       XLGMAC_GET_REG_BITS(readl(pdata->mac_regs + DMA_MR),
305662306a36Sopenharmony_ci				   DMA_MR_SWR_POS, DMA_MR_SWR_LEN))
305762306a36Sopenharmony_ci		usleep_range(500, 600);
305862306a36Sopenharmony_ci
305962306a36Sopenharmony_ci	if (!count)
306062306a36Sopenharmony_ci		return -EBUSY;
306162306a36Sopenharmony_ci
306262306a36Sopenharmony_ci	return 0;
306362306a36Sopenharmony_ci}
306462306a36Sopenharmony_ci
306562306a36Sopenharmony_civoid xlgmac_init_hw_ops(struct xlgmac_hw_ops *hw_ops)
306662306a36Sopenharmony_ci{
306762306a36Sopenharmony_ci	hw_ops->init = xlgmac_hw_init;
306862306a36Sopenharmony_ci	hw_ops->exit = xlgmac_hw_exit;
306962306a36Sopenharmony_ci
307062306a36Sopenharmony_ci	hw_ops->tx_complete = xlgmac_tx_complete;
307162306a36Sopenharmony_ci
307262306a36Sopenharmony_ci	hw_ops->enable_tx = xlgmac_enable_tx;
307362306a36Sopenharmony_ci	hw_ops->disable_tx = xlgmac_disable_tx;
307462306a36Sopenharmony_ci	hw_ops->enable_rx = xlgmac_enable_rx;
307562306a36Sopenharmony_ci	hw_ops->disable_rx = xlgmac_disable_rx;
307662306a36Sopenharmony_ci
307762306a36Sopenharmony_ci	hw_ops->dev_xmit = xlgmac_dev_xmit;
307862306a36Sopenharmony_ci	hw_ops->dev_read = xlgmac_dev_read;
307962306a36Sopenharmony_ci	hw_ops->enable_int = xlgmac_enable_int;
308062306a36Sopenharmony_ci	hw_ops->disable_int = xlgmac_disable_int;
308162306a36Sopenharmony_ci
308262306a36Sopenharmony_ci	hw_ops->set_mac_address = xlgmac_set_mac_address;
308362306a36Sopenharmony_ci	hw_ops->config_rx_mode = xlgmac_config_rx_mode;
308462306a36Sopenharmony_ci	hw_ops->enable_rx_csum = xlgmac_enable_rx_csum;
308562306a36Sopenharmony_ci	hw_ops->disable_rx_csum = xlgmac_disable_rx_csum;
308662306a36Sopenharmony_ci
308762306a36Sopenharmony_ci	/* For MII speed configuration */
308862306a36Sopenharmony_ci	hw_ops->set_xlgmii_25000_speed = xlgmac_set_xlgmii_25000_speed;
308962306a36Sopenharmony_ci	hw_ops->set_xlgmii_40000_speed = xlgmac_set_xlgmii_40000_speed;
309062306a36Sopenharmony_ci	hw_ops->set_xlgmii_50000_speed = xlgmac_set_xlgmii_50000_speed;
309162306a36Sopenharmony_ci	hw_ops->set_xlgmii_100000_speed = xlgmac_set_xlgmii_100000_speed;
309262306a36Sopenharmony_ci
309362306a36Sopenharmony_ci	/* For descriptor related operation */
309462306a36Sopenharmony_ci	hw_ops->tx_desc_init = xlgmac_tx_desc_init;
309562306a36Sopenharmony_ci	hw_ops->rx_desc_init = xlgmac_rx_desc_init;
309662306a36Sopenharmony_ci	hw_ops->tx_desc_reset = xlgmac_tx_desc_reset;
309762306a36Sopenharmony_ci	hw_ops->rx_desc_reset = xlgmac_rx_desc_reset;
309862306a36Sopenharmony_ci	hw_ops->is_last_desc = xlgmac_is_last_desc;
309962306a36Sopenharmony_ci	hw_ops->is_context_desc = xlgmac_is_context_desc;
310062306a36Sopenharmony_ci	hw_ops->tx_start_xmit = xlgmac_tx_start_xmit;
310162306a36Sopenharmony_ci
310262306a36Sopenharmony_ci	/* For Flow Control */
310362306a36Sopenharmony_ci	hw_ops->config_tx_flow_control = xlgmac_config_tx_flow_control;
310462306a36Sopenharmony_ci	hw_ops->config_rx_flow_control = xlgmac_config_rx_flow_control;
310562306a36Sopenharmony_ci
310662306a36Sopenharmony_ci	/* For Vlan related config */
310762306a36Sopenharmony_ci	hw_ops->enable_rx_vlan_stripping = xlgmac_enable_rx_vlan_stripping;
310862306a36Sopenharmony_ci	hw_ops->disable_rx_vlan_stripping = xlgmac_disable_rx_vlan_stripping;
310962306a36Sopenharmony_ci	hw_ops->enable_rx_vlan_filtering = xlgmac_enable_rx_vlan_filtering;
311062306a36Sopenharmony_ci	hw_ops->disable_rx_vlan_filtering = xlgmac_disable_rx_vlan_filtering;
311162306a36Sopenharmony_ci	hw_ops->update_vlan_hash_table = xlgmac_update_vlan_hash_table;
311262306a36Sopenharmony_ci
311362306a36Sopenharmony_ci	/* For RX coalescing */
311462306a36Sopenharmony_ci	hw_ops->config_rx_coalesce = xlgmac_config_rx_coalesce;
311562306a36Sopenharmony_ci	hw_ops->config_tx_coalesce = xlgmac_config_tx_coalesce;
311662306a36Sopenharmony_ci	hw_ops->usec_to_riwt = xlgmac_usec_to_riwt;
311762306a36Sopenharmony_ci	hw_ops->riwt_to_usec = xlgmac_riwt_to_usec;
311862306a36Sopenharmony_ci
311962306a36Sopenharmony_ci	/* For RX and TX threshold config */
312062306a36Sopenharmony_ci	hw_ops->config_rx_threshold = xlgmac_config_rx_threshold;
312162306a36Sopenharmony_ci	hw_ops->config_tx_threshold = xlgmac_config_tx_threshold;
312262306a36Sopenharmony_ci
312362306a36Sopenharmony_ci	/* For RX and TX Store and Forward Mode config */
312462306a36Sopenharmony_ci	hw_ops->config_rsf_mode = xlgmac_config_rsf_mode;
312562306a36Sopenharmony_ci	hw_ops->config_tsf_mode = xlgmac_config_tsf_mode;
312662306a36Sopenharmony_ci
312762306a36Sopenharmony_ci	/* For TX DMA Operating on Second Frame config */
312862306a36Sopenharmony_ci	hw_ops->config_osp_mode = xlgmac_config_osp_mode;
312962306a36Sopenharmony_ci
313062306a36Sopenharmony_ci	/* For RX and TX PBL config */
313162306a36Sopenharmony_ci	hw_ops->config_rx_pbl_val = xlgmac_config_rx_pbl_val;
313262306a36Sopenharmony_ci	hw_ops->get_rx_pbl_val = xlgmac_get_rx_pbl_val;
313362306a36Sopenharmony_ci	hw_ops->config_tx_pbl_val = xlgmac_config_tx_pbl_val;
313462306a36Sopenharmony_ci	hw_ops->get_tx_pbl_val = xlgmac_get_tx_pbl_val;
313562306a36Sopenharmony_ci	hw_ops->config_pblx8 = xlgmac_config_pblx8;
313662306a36Sopenharmony_ci
313762306a36Sopenharmony_ci	/* For MMC statistics support */
313862306a36Sopenharmony_ci	hw_ops->tx_mmc_int = xlgmac_tx_mmc_int;
313962306a36Sopenharmony_ci	hw_ops->rx_mmc_int = xlgmac_rx_mmc_int;
314062306a36Sopenharmony_ci	hw_ops->read_mmc_stats = xlgmac_read_mmc_stats;
314162306a36Sopenharmony_ci
314262306a36Sopenharmony_ci	/* For Receive Side Scaling */
314362306a36Sopenharmony_ci	hw_ops->enable_rss = xlgmac_enable_rss;
314462306a36Sopenharmony_ci	hw_ops->disable_rss = xlgmac_disable_rss;
314562306a36Sopenharmony_ci	hw_ops->set_rss_hash_key = xlgmac_set_rss_hash_key;
314662306a36Sopenharmony_ci	hw_ops->set_rss_lookup_table = xlgmac_set_rss_lookup_table;
314762306a36Sopenharmony_ci}
3148