18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * r8169.c: RealTek 8169/8168/8101 ethernet driver.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2002 ShuChen <shuchen@realtek.com.tw>
68c2ecf20Sopenharmony_ci * Copyright (c) 2003 - 2007 Francois Romieu <romieu@fr.zoreil.com>
78c2ecf20Sopenharmony_ci * Copyright (c) a lot of people too. Please respect their work.
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * See MAINTAINERS file for support contact information.
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <linux/module.h>
138c2ecf20Sopenharmony_ci#include <linux/pci.h>
148c2ecf20Sopenharmony_ci#include <linux/netdevice.h>
158c2ecf20Sopenharmony_ci#include <linux/etherdevice.h>
168c2ecf20Sopenharmony_ci#include <linux/clk.h>
178c2ecf20Sopenharmony_ci#include <linux/delay.h>
188c2ecf20Sopenharmony_ci#include <linux/ethtool.h>
198c2ecf20Sopenharmony_ci#include <linux/phy.h>
208c2ecf20Sopenharmony_ci#include <linux/if_vlan.h>
218c2ecf20Sopenharmony_ci#include <linux/in.h>
228c2ecf20Sopenharmony_ci#include <linux/io.h>
238c2ecf20Sopenharmony_ci#include <linux/ip.h>
248c2ecf20Sopenharmony_ci#include <linux/tcp.h>
258c2ecf20Sopenharmony_ci#include <linux/interrupt.h>
268c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h>
278c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h>
288c2ecf20Sopenharmony_ci#include <linux/bitfield.h>
298c2ecf20Sopenharmony_ci#include <linux/prefetch.h>
308c2ecf20Sopenharmony_ci#include <linux/ipv6.h>
318c2ecf20Sopenharmony_ci#include <net/ip6_checksum.h>
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#include "r8169.h"
348c2ecf20Sopenharmony_ci#include "r8169_firmware.h"
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#define MODULENAME "r8169"
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#define FIRMWARE_8168D_1	"rtl_nic/rtl8168d-1.fw"
398c2ecf20Sopenharmony_ci#define FIRMWARE_8168D_2	"rtl_nic/rtl8168d-2.fw"
408c2ecf20Sopenharmony_ci#define FIRMWARE_8168E_1	"rtl_nic/rtl8168e-1.fw"
418c2ecf20Sopenharmony_ci#define FIRMWARE_8168E_2	"rtl_nic/rtl8168e-2.fw"
428c2ecf20Sopenharmony_ci#define FIRMWARE_8168E_3	"rtl_nic/rtl8168e-3.fw"
438c2ecf20Sopenharmony_ci#define FIRMWARE_8168F_1	"rtl_nic/rtl8168f-1.fw"
448c2ecf20Sopenharmony_ci#define FIRMWARE_8168F_2	"rtl_nic/rtl8168f-2.fw"
458c2ecf20Sopenharmony_ci#define FIRMWARE_8105E_1	"rtl_nic/rtl8105e-1.fw"
468c2ecf20Sopenharmony_ci#define FIRMWARE_8402_1		"rtl_nic/rtl8402-1.fw"
478c2ecf20Sopenharmony_ci#define FIRMWARE_8411_1		"rtl_nic/rtl8411-1.fw"
488c2ecf20Sopenharmony_ci#define FIRMWARE_8411_2		"rtl_nic/rtl8411-2.fw"
498c2ecf20Sopenharmony_ci#define FIRMWARE_8106E_1	"rtl_nic/rtl8106e-1.fw"
508c2ecf20Sopenharmony_ci#define FIRMWARE_8106E_2	"rtl_nic/rtl8106e-2.fw"
518c2ecf20Sopenharmony_ci#define FIRMWARE_8168G_2	"rtl_nic/rtl8168g-2.fw"
528c2ecf20Sopenharmony_ci#define FIRMWARE_8168G_3	"rtl_nic/rtl8168g-3.fw"
538c2ecf20Sopenharmony_ci#define FIRMWARE_8168H_1	"rtl_nic/rtl8168h-1.fw"
548c2ecf20Sopenharmony_ci#define FIRMWARE_8168H_2	"rtl_nic/rtl8168h-2.fw"
558c2ecf20Sopenharmony_ci#define FIRMWARE_8168FP_3	"rtl_nic/rtl8168fp-3.fw"
568c2ecf20Sopenharmony_ci#define FIRMWARE_8107E_1	"rtl_nic/rtl8107e-1.fw"
578c2ecf20Sopenharmony_ci#define FIRMWARE_8107E_2	"rtl_nic/rtl8107e-2.fw"
588c2ecf20Sopenharmony_ci#define FIRMWARE_8125A_3	"rtl_nic/rtl8125a-3.fw"
598c2ecf20Sopenharmony_ci#define FIRMWARE_8125B_2	"rtl_nic/rtl8125b-2.fw"
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast).
628c2ecf20Sopenharmony_ci   The RTL chips use a 64 element hash table based on the Ethernet CRC. */
638c2ecf20Sopenharmony_ci#define	MC_FILTER_LIMIT	32
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci#define TX_DMA_BURST	7	/* Maximum PCI burst, '7' is unlimited */
668c2ecf20Sopenharmony_ci#define InterFrameGap	0x03	/* 3 means InterFrameGap = the shortest one */
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci#define R8169_REGS_SIZE		256
698c2ecf20Sopenharmony_ci#define R8169_RX_BUF_SIZE	(SZ_16K - 1)
708c2ecf20Sopenharmony_ci#define NUM_TX_DESC	64	/* Number of Tx descriptor registers */
718c2ecf20Sopenharmony_ci#define NUM_RX_DESC	256U	/* Number of Rx descriptor registers */
728c2ecf20Sopenharmony_ci#define R8169_TX_RING_BYTES	(NUM_TX_DESC * sizeof(struct TxDesc))
738c2ecf20Sopenharmony_ci#define R8169_RX_RING_BYTES	(NUM_RX_DESC * sizeof(struct RxDesc))
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci#define OCP_STD_PHY_BASE	0xa400
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci#define RTL_CFG_NO_GBIT	1
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci/* write/read MMIO register */
808c2ecf20Sopenharmony_ci#define RTL_W8(tp, reg, val8)	writeb((val8), tp->mmio_addr + (reg))
818c2ecf20Sopenharmony_ci#define RTL_W16(tp, reg, val16)	writew((val16), tp->mmio_addr + (reg))
828c2ecf20Sopenharmony_ci#define RTL_W32(tp, reg, val32)	writel((val32), tp->mmio_addr + (reg))
838c2ecf20Sopenharmony_ci#define RTL_R8(tp, reg)		readb(tp->mmio_addr + (reg))
848c2ecf20Sopenharmony_ci#define RTL_R16(tp, reg)		readw(tp->mmio_addr + (reg))
858c2ecf20Sopenharmony_ci#define RTL_R32(tp, reg)		readl(tp->mmio_addr + (reg))
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci#define JUMBO_4K	(4 * SZ_1K - VLAN_ETH_HLEN - ETH_FCS_LEN)
888c2ecf20Sopenharmony_ci#define JUMBO_6K	(6 * SZ_1K - VLAN_ETH_HLEN - ETH_FCS_LEN)
898c2ecf20Sopenharmony_ci#define JUMBO_7K	(7 * SZ_1K - VLAN_ETH_HLEN - ETH_FCS_LEN)
908c2ecf20Sopenharmony_ci#define JUMBO_9K	(9 * SZ_1K - VLAN_ETH_HLEN - ETH_FCS_LEN)
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_cistatic const struct {
938c2ecf20Sopenharmony_ci	const char *name;
948c2ecf20Sopenharmony_ci	const char *fw_name;
958c2ecf20Sopenharmony_ci} rtl_chip_infos[] = {
968c2ecf20Sopenharmony_ci	/* PCI devices. */
978c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_02] = {"RTL8169s"				},
988c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_03] = {"RTL8110s"				},
998c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_04] = {"RTL8169sb/8110sb"			},
1008c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_05] = {"RTL8169sc/8110sc"			},
1018c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_06] = {"RTL8169sc/8110sc"			},
1028c2ecf20Sopenharmony_ci	/* PCI-E devices. */
1038c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_07] = {"RTL8102e"				},
1048c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_08] = {"RTL8102e"				},
1058c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_09] = {"RTL8102e/RTL8103e"			},
1068c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_10] = {"RTL8101e"				},
1078c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_11] = {"RTL8168b/8111b"			},
1088c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_12] = {"RTL8168b/8111b"			},
1098c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_13] = {"RTL8101e/RTL8100e"			},
1108c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_14] = {"RTL8401"				},
1118c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_16] = {"RTL8101e"				},
1128c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_17] = {"RTL8168b/8111b"			},
1138c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_18] = {"RTL8168cp/8111cp"			},
1148c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_19] = {"RTL8168c/8111c"			},
1158c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_20] = {"RTL8168c/8111c"			},
1168c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_21] = {"RTL8168c/8111c"			},
1178c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_22] = {"RTL8168c/8111c"			},
1188c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_23] = {"RTL8168cp/8111cp"			},
1198c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_24] = {"RTL8168cp/8111cp"			},
1208c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_25] = {"RTL8168d/8111d",	FIRMWARE_8168D_1},
1218c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_26] = {"RTL8168d/8111d",	FIRMWARE_8168D_2},
1228c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_27] = {"RTL8168dp/8111dp"			},
1238c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_28] = {"RTL8168dp/8111dp"			},
1248c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_29] = {"RTL8105e",		FIRMWARE_8105E_1},
1258c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_30] = {"RTL8105e",		FIRMWARE_8105E_1},
1268c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_31] = {"RTL8168dp/8111dp"			},
1278c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_32] = {"RTL8168e/8111e",	FIRMWARE_8168E_1},
1288c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_33] = {"RTL8168e/8111e",	FIRMWARE_8168E_2},
1298c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_34] = {"RTL8168evl/8111evl",	FIRMWARE_8168E_3},
1308c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_35] = {"RTL8168f/8111f",	FIRMWARE_8168F_1},
1318c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_36] = {"RTL8168f/8111f",	FIRMWARE_8168F_2},
1328c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_37] = {"RTL8402",		FIRMWARE_8402_1 },
1338c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_38] = {"RTL8411",		FIRMWARE_8411_1 },
1348c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_39] = {"RTL8106e",		FIRMWARE_8106E_1},
1358c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_40] = {"RTL8168g/8111g",	FIRMWARE_8168G_2},
1368c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_41] = {"RTL8168g/8111g"			},
1378c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_42] = {"RTL8168gu/8111gu",	FIRMWARE_8168G_3},
1388c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_43] = {"RTL8106eus",		FIRMWARE_8106E_2},
1398c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_44] = {"RTL8411b",		FIRMWARE_8411_2 },
1408c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_45] = {"RTL8168h/8111h",	FIRMWARE_8168H_1},
1418c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_46] = {"RTL8168h/8111h",	FIRMWARE_8168H_2},
1428c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_47] = {"RTL8107e",		FIRMWARE_8107E_1},
1438c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_48] = {"RTL8107e",		FIRMWARE_8107E_2},
1448c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_49] = {"RTL8168ep/8111ep"			},
1458c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_50] = {"RTL8168ep/8111ep"			},
1468c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_51] = {"RTL8168ep/8111ep"			},
1478c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_52] = {"RTL8168fp/RTL8117",  FIRMWARE_8168FP_3},
1488c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_60] = {"RTL8125A"				},
1498c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_61] = {"RTL8125A",		FIRMWARE_8125A_3},
1508c2ecf20Sopenharmony_ci	/* reserve 62 for CFG_METHOD_4 in the vendor driver */
1518c2ecf20Sopenharmony_ci	[RTL_GIGA_MAC_VER_63] = {"RTL8125B",		FIRMWARE_8125B_2},
1528c2ecf20Sopenharmony_ci};
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_cistatic const struct pci_device_id rtl8169_pci_tbl[] = {
1558c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(REALTEK,	0x2502) },
1568c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(REALTEK,	0x2600) },
1578c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(REALTEK,	0x8129) },
1588c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(REALTEK,	0x8136), RTL_CFG_NO_GBIT },
1598c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(REALTEK,	0x8161) },
1608c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(REALTEK,	0x8162) },
1618c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(REALTEK,	0x8167) },
1628c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(REALTEK,	0x8168) },
1638c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(NCUBE,	0x8168) },
1648c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(REALTEK,	0x8169) },
1658c2ecf20Sopenharmony_ci	{ PCI_VENDOR_ID_DLINK,	0x4300,
1668c2ecf20Sopenharmony_ci		PCI_VENDOR_ID_DLINK, 0x4b10, 0, 0 },
1678c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(DLINK,	0x4300) },
1688c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(DLINK,	0x4302) },
1698c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(AT,	0xc107) },
1708c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(USR,	0x0116) },
1718c2ecf20Sopenharmony_ci	{ PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0024 },
1728c2ecf20Sopenharmony_ci	{ 0x0001, 0x8168, PCI_ANY_ID, 0x2410 },
1738c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(REALTEK,	0x8125) },
1748c2ecf20Sopenharmony_ci	{ PCI_VDEVICE(REALTEK,	0x3000) },
1758c2ecf20Sopenharmony_ci	{}
1768c2ecf20Sopenharmony_ci};
1778c2ecf20Sopenharmony_ci
1788c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl);
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_cienum rtl_registers {
1818c2ecf20Sopenharmony_ci	MAC0		= 0,	/* Ethernet hardware address. */
1828c2ecf20Sopenharmony_ci	MAC4		= 4,
1838c2ecf20Sopenharmony_ci	MAR0		= 8,	/* Multicast filter. */
1848c2ecf20Sopenharmony_ci	CounterAddrLow		= 0x10,
1858c2ecf20Sopenharmony_ci	CounterAddrHigh		= 0x14,
1868c2ecf20Sopenharmony_ci	TxDescStartAddrLow	= 0x20,
1878c2ecf20Sopenharmony_ci	TxDescStartAddrHigh	= 0x24,
1888c2ecf20Sopenharmony_ci	TxHDescStartAddrLow	= 0x28,
1898c2ecf20Sopenharmony_ci	TxHDescStartAddrHigh	= 0x2c,
1908c2ecf20Sopenharmony_ci	FLASH		= 0x30,
1918c2ecf20Sopenharmony_ci	ERSR		= 0x36,
1928c2ecf20Sopenharmony_ci	ChipCmd		= 0x37,
1938c2ecf20Sopenharmony_ci	TxPoll		= 0x38,
1948c2ecf20Sopenharmony_ci	IntrMask	= 0x3c,
1958c2ecf20Sopenharmony_ci	IntrStatus	= 0x3e,
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	TxConfig	= 0x40,
1988c2ecf20Sopenharmony_ci#define	TXCFG_AUTO_FIFO			(1 << 7)	/* 8111e-vl */
1998c2ecf20Sopenharmony_ci#define	TXCFG_EMPTY			(1 << 11)	/* 8111e-vl */
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	RxConfig	= 0x44,
2028c2ecf20Sopenharmony_ci#define	RX128_INT_EN			(1 << 15)	/* 8111c and later */
2038c2ecf20Sopenharmony_ci#define	RX_MULTI_EN			(1 << 14)	/* 8111c only */
2048c2ecf20Sopenharmony_ci#define	RXCFG_FIFO_SHIFT		13
2058c2ecf20Sopenharmony_ci					/* No threshold before first PCI xfer */
2068c2ecf20Sopenharmony_ci#define	RX_FIFO_THRESH			(7 << RXCFG_FIFO_SHIFT)
2078c2ecf20Sopenharmony_ci#define	RX_EARLY_OFF			(1 << 11)
2088c2ecf20Sopenharmony_ci#define	RX_PAUSE_SLOT_ON		(1 << 11)	/* 8125b and later */
2098c2ecf20Sopenharmony_ci#define	RXCFG_DMA_SHIFT			8
2108c2ecf20Sopenharmony_ci					/* Unlimited maximum PCI burst. */
2118c2ecf20Sopenharmony_ci#define	RX_DMA_BURST			(7 << RXCFG_DMA_SHIFT)
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	Cfg9346		= 0x50,
2148c2ecf20Sopenharmony_ci	Config0		= 0x51,
2158c2ecf20Sopenharmony_ci	Config1		= 0x52,
2168c2ecf20Sopenharmony_ci	Config2		= 0x53,
2178c2ecf20Sopenharmony_ci#define PME_SIGNAL			(1 << 5)	/* 8168c and later */
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci	Config3		= 0x54,
2208c2ecf20Sopenharmony_ci	Config4		= 0x55,
2218c2ecf20Sopenharmony_ci	Config5		= 0x56,
2228c2ecf20Sopenharmony_ci	PHYAR		= 0x60,
2238c2ecf20Sopenharmony_ci	PHYstatus	= 0x6c,
2248c2ecf20Sopenharmony_ci	RxMaxSize	= 0xda,
2258c2ecf20Sopenharmony_ci	CPlusCmd	= 0xe0,
2268c2ecf20Sopenharmony_ci	IntrMitigate	= 0xe2,
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci#define RTL_COALESCE_TX_USECS	GENMASK(15, 12)
2298c2ecf20Sopenharmony_ci#define RTL_COALESCE_TX_FRAMES	GENMASK(11, 8)
2308c2ecf20Sopenharmony_ci#define RTL_COALESCE_RX_USECS	GENMASK(7, 4)
2318c2ecf20Sopenharmony_ci#define RTL_COALESCE_RX_FRAMES	GENMASK(3, 0)
2328c2ecf20Sopenharmony_ci
2338c2ecf20Sopenharmony_ci#define RTL_COALESCE_T_MAX	0x0fU
2348c2ecf20Sopenharmony_ci#define RTL_COALESCE_FRAME_MAX	(RTL_COALESCE_T_MAX * 4)
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci	RxDescAddrLow	= 0xe4,
2378c2ecf20Sopenharmony_ci	RxDescAddrHigh	= 0xe8,
2388c2ecf20Sopenharmony_ci	EarlyTxThres	= 0xec,	/* 8169. Unit of 32 bytes. */
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci#define NoEarlyTx	0x3f	/* Max value : no early transmit. */
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	MaxTxPacketSize	= 0xec,	/* 8101/8168. Unit of 128 bytes. */
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci#define TxPacketMax	(8064 >> 7)
2458c2ecf20Sopenharmony_ci#define EarlySize	0x27
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_ci	FuncEvent	= 0xf0,
2488c2ecf20Sopenharmony_ci	FuncEventMask	= 0xf4,
2498c2ecf20Sopenharmony_ci	FuncPresetState	= 0xf8,
2508c2ecf20Sopenharmony_ci	IBCR0           = 0xf8,
2518c2ecf20Sopenharmony_ci	IBCR2           = 0xf9,
2528c2ecf20Sopenharmony_ci	IBIMR0          = 0xfa,
2538c2ecf20Sopenharmony_ci	IBISR0          = 0xfb,
2548c2ecf20Sopenharmony_ci	FuncForceEvent	= 0xfc,
2558c2ecf20Sopenharmony_ci};
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_cienum rtl8168_8101_registers {
2588c2ecf20Sopenharmony_ci	CSIDR			= 0x64,
2598c2ecf20Sopenharmony_ci	CSIAR			= 0x68,
2608c2ecf20Sopenharmony_ci#define	CSIAR_FLAG			0x80000000
2618c2ecf20Sopenharmony_ci#define	CSIAR_WRITE_CMD			0x80000000
2628c2ecf20Sopenharmony_ci#define	CSIAR_BYTE_ENABLE		0x0000f000
2638c2ecf20Sopenharmony_ci#define	CSIAR_ADDR_MASK			0x00000fff
2648c2ecf20Sopenharmony_ci	PMCH			= 0x6f,
2658c2ecf20Sopenharmony_ci	EPHYAR			= 0x80,
2668c2ecf20Sopenharmony_ci#define	EPHYAR_FLAG			0x80000000
2678c2ecf20Sopenharmony_ci#define	EPHYAR_WRITE_CMD		0x80000000
2688c2ecf20Sopenharmony_ci#define	EPHYAR_REG_MASK			0x1f
2698c2ecf20Sopenharmony_ci#define	EPHYAR_REG_SHIFT		16
2708c2ecf20Sopenharmony_ci#define	EPHYAR_DATA_MASK		0xffff
2718c2ecf20Sopenharmony_ci	DLLPR			= 0xd0,
2728c2ecf20Sopenharmony_ci#define	PFM_EN				(1 << 6)
2738c2ecf20Sopenharmony_ci#define	TX_10M_PS_EN			(1 << 7)
2748c2ecf20Sopenharmony_ci	DBG_REG			= 0xd1,
2758c2ecf20Sopenharmony_ci#define	FIX_NAK_1			(1 << 4)
2768c2ecf20Sopenharmony_ci#define	FIX_NAK_2			(1 << 3)
2778c2ecf20Sopenharmony_ci	TWSI			= 0xd2,
2788c2ecf20Sopenharmony_ci	MCU			= 0xd3,
2798c2ecf20Sopenharmony_ci#define	NOW_IS_OOB			(1 << 7)
2808c2ecf20Sopenharmony_ci#define	TX_EMPTY			(1 << 5)
2818c2ecf20Sopenharmony_ci#define	RX_EMPTY			(1 << 4)
2828c2ecf20Sopenharmony_ci#define	RXTX_EMPTY			(TX_EMPTY | RX_EMPTY)
2838c2ecf20Sopenharmony_ci#define	EN_NDP				(1 << 3)
2848c2ecf20Sopenharmony_ci#define	EN_OOB_RESET			(1 << 2)
2858c2ecf20Sopenharmony_ci#define	LINK_LIST_RDY			(1 << 1)
2868c2ecf20Sopenharmony_ci	EFUSEAR			= 0xdc,
2878c2ecf20Sopenharmony_ci#define	EFUSEAR_FLAG			0x80000000
2888c2ecf20Sopenharmony_ci#define	EFUSEAR_WRITE_CMD		0x80000000
2898c2ecf20Sopenharmony_ci#define	EFUSEAR_READ_CMD		0x00000000
2908c2ecf20Sopenharmony_ci#define	EFUSEAR_REG_MASK		0x03ff
2918c2ecf20Sopenharmony_ci#define	EFUSEAR_REG_SHIFT		8
2928c2ecf20Sopenharmony_ci#define	EFUSEAR_DATA_MASK		0xff
2938c2ecf20Sopenharmony_ci	MISC_1			= 0xf2,
2948c2ecf20Sopenharmony_ci#define	PFM_D3COLD_EN			(1 << 6)
2958c2ecf20Sopenharmony_ci};
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_cienum rtl8168_registers {
2988c2ecf20Sopenharmony_ci	LED_FREQ		= 0x1a,
2998c2ecf20Sopenharmony_ci	EEE_LED			= 0x1b,
3008c2ecf20Sopenharmony_ci	ERIDR			= 0x70,
3018c2ecf20Sopenharmony_ci	ERIAR			= 0x74,
3028c2ecf20Sopenharmony_ci#define ERIAR_FLAG			0x80000000
3038c2ecf20Sopenharmony_ci#define ERIAR_WRITE_CMD			0x80000000
3048c2ecf20Sopenharmony_ci#define ERIAR_READ_CMD			0x00000000
3058c2ecf20Sopenharmony_ci#define ERIAR_ADDR_BYTE_ALIGN		4
3068c2ecf20Sopenharmony_ci#define ERIAR_TYPE_SHIFT		16
3078c2ecf20Sopenharmony_ci#define ERIAR_EXGMAC			(0x00 << ERIAR_TYPE_SHIFT)
3088c2ecf20Sopenharmony_ci#define ERIAR_MSIX			(0x01 << ERIAR_TYPE_SHIFT)
3098c2ecf20Sopenharmony_ci#define ERIAR_ASF			(0x02 << ERIAR_TYPE_SHIFT)
3108c2ecf20Sopenharmony_ci#define ERIAR_OOB			(0x02 << ERIAR_TYPE_SHIFT)
3118c2ecf20Sopenharmony_ci#define ERIAR_MASK_SHIFT		12
3128c2ecf20Sopenharmony_ci#define ERIAR_MASK_0001			(0x1 << ERIAR_MASK_SHIFT)
3138c2ecf20Sopenharmony_ci#define ERIAR_MASK_0011			(0x3 << ERIAR_MASK_SHIFT)
3148c2ecf20Sopenharmony_ci#define ERIAR_MASK_0100			(0x4 << ERIAR_MASK_SHIFT)
3158c2ecf20Sopenharmony_ci#define ERIAR_MASK_0101			(0x5 << ERIAR_MASK_SHIFT)
3168c2ecf20Sopenharmony_ci#define ERIAR_MASK_1111			(0xf << ERIAR_MASK_SHIFT)
3178c2ecf20Sopenharmony_ci	EPHY_RXER_NUM		= 0x7c,
3188c2ecf20Sopenharmony_ci	OCPDR			= 0xb0,	/* OCP GPHY access */
3198c2ecf20Sopenharmony_ci#define OCPDR_WRITE_CMD			0x80000000
3208c2ecf20Sopenharmony_ci#define OCPDR_READ_CMD			0x00000000
3218c2ecf20Sopenharmony_ci#define OCPDR_REG_MASK			0x7f
3228c2ecf20Sopenharmony_ci#define OCPDR_GPHY_REG_SHIFT		16
3238c2ecf20Sopenharmony_ci#define OCPDR_DATA_MASK			0xffff
3248c2ecf20Sopenharmony_ci	OCPAR			= 0xb4,
3258c2ecf20Sopenharmony_ci#define OCPAR_FLAG			0x80000000
3268c2ecf20Sopenharmony_ci#define OCPAR_GPHY_WRITE_CMD		0x8000f060
3278c2ecf20Sopenharmony_ci#define OCPAR_GPHY_READ_CMD		0x0000f060
3288c2ecf20Sopenharmony_ci	GPHY_OCP		= 0xb8,
3298c2ecf20Sopenharmony_ci	RDSAR1			= 0xd0,	/* 8168c only. Undocumented on 8168dp */
3308c2ecf20Sopenharmony_ci	MISC			= 0xf0,	/* 8168e only. */
3318c2ecf20Sopenharmony_ci#define TXPLA_RST			(1 << 29)
3328c2ecf20Sopenharmony_ci#define DISABLE_LAN_EN			(1 << 23) /* Enable GPIO pin */
3338c2ecf20Sopenharmony_ci#define PWM_EN				(1 << 22)
3348c2ecf20Sopenharmony_ci#define RXDV_GATED_EN			(1 << 19)
3358c2ecf20Sopenharmony_ci#define EARLY_TALLY_EN			(1 << 16)
3368c2ecf20Sopenharmony_ci};
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_cienum rtl8125_registers {
3398c2ecf20Sopenharmony_ci	IntrMask_8125		= 0x38,
3408c2ecf20Sopenharmony_ci	IntrStatus_8125		= 0x3c,
3418c2ecf20Sopenharmony_ci	TxPoll_8125		= 0x90,
3428c2ecf20Sopenharmony_ci	MAC0_BKP		= 0x19e0,
3438c2ecf20Sopenharmony_ci	EEE_TXIDLE_TIMER_8125	= 0x6048,
3448c2ecf20Sopenharmony_ci};
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci#define RX_VLAN_INNER_8125	BIT(22)
3478c2ecf20Sopenharmony_ci#define RX_VLAN_OUTER_8125	BIT(23)
3488c2ecf20Sopenharmony_ci#define RX_VLAN_8125		(RX_VLAN_INNER_8125 | RX_VLAN_OUTER_8125)
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci#define RX_FETCH_DFLT_8125	(8 << 27)
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_cienum rtl_register_content {
3538c2ecf20Sopenharmony_ci	/* InterruptStatusBits */
3548c2ecf20Sopenharmony_ci	SYSErr		= 0x8000,
3558c2ecf20Sopenharmony_ci	PCSTimeout	= 0x4000,
3568c2ecf20Sopenharmony_ci	SWInt		= 0x0100,
3578c2ecf20Sopenharmony_ci	TxDescUnavail	= 0x0080,
3588c2ecf20Sopenharmony_ci	RxFIFOOver	= 0x0040,
3598c2ecf20Sopenharmony_ci	LinkChg		= 0x0020,
3608c2ecf20Sopenharmony_ci	RxOverflow	= 0x0010,
3618c2ecf20Sopenharmony_ci	TxErr		= 0x0008,
3628c2ecf20Sopenharmony_ci	TxOK		= 0x0004,
3638c2ecf20Sopenharmony_ci	RxErr		= 0x0002,
3648c2ecf20Sopenharmony_ci	RxOK		= 0x0001,
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci	/* RxStatusDesc */
3678c2ecf20Sopenharmony_ci	RxRWT	= (1 << 22),
3688c2ecf20Sopenharmony_ci	RxRES	= (1 << 21),
3698c2ecf20Sopenharmony_ci	RxRUNT	= (1 << 20),
3708c2ecf20Sopenharmony_ci	RxCRC	= (1 << 19),
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	/* ChipCmdBits */
3738c2ecf20Sopenharmony_ci	StopReq		= 0x80,
3748c2ecf20Sopenharmony_ci	CmdReset	= 0x10,
3758c2ecf20Sopenharmony_ci	CmdRxEnb	= 0x08,
3768c2ecf20Sopenharmony_ci	CmdTxEnb	= 0x04,
3778c2ecf20Sopenharmony_ci	RxBufEmpty	= 0x01,
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci	/* TXPoll register p.5 */
3808c2ecf20Sopenharmony_ci	HPQ		= 0x80,		/* Poll cmd on the high prio queue */
3818c2ecf20Sopenharmony_ci	NPQ		= 0x40,		/* Poll cmd on the low prio queue */
3828c2ecf20Sopenharmony_ci	FSWInt		= 0x01,		/* Forced software interrupt */
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_ci	/* Cfg9346Bits */
3858c2ecf20Sopenharmony_ci	Cfg9346_Lock	= 0x00,
3868c2ecf20Sopenharmony_ci	Cfg9346_Unlock	= 0xc0,
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci	/* rx_mode_bits */
3898c2ecf20Sopenharmony_ci	AcceptErr	= 0x20,
3908c2ecf20Sopenharmony_ci	AcceptRunt	= 0x10,
3918c2ecf20Sopenharmony_ci#define RX_CONFIG_ACCEPT_ERR_MASK	0x30
3928c2ecf20Sopenharmony_ci	AcceptBroadcast	= 0x08,
3938c2ecf20Sopenharmony_ci	AcceptMulticast	= 0x04,
3948c2ecf20Sopenharmony_ci	AcceptMyPhys	= 0x02,
3958c2ecf20Sopenharmony_ci	AcceptAllPhys	= 0x01,
3968c2ecf20Sopenharmony_ci#define RX_CONFIG_ACCEPT_OK_MASK	0x0f
3978c2ecf20Sopenharmony_ci#define RX_CONFIG_ACCEPT_MASK		0x3f
3988c2ecf20Sopenharmony_ci
3998c2ecf20Sopenharmony_ci	/* TxConfigBits */
4008c2ecf20Sopenharmony_ci	TxInterFrameGapShift = 24,
4018c2ecf20Sopenharmony_ci	TxDMAShift = 8,	/* DMA burst value (0-7) is shift this many bits */
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci	/* Config1 register p.24 */
4048c2ecf20Sopenharmony_ci	LEDS1		= (1 << 7),
4058c2ecf20Sopenharmony_ci	LEDS0		= (1 << 6),
4068c2ecf20Sopenharmony_ci	Speed_down	= (1 << 4),
4078c2ecf20Sopenharmony_ci	MEMMAP		= (1 << 3),
4088c2ecf20Sopenharmony_ci	IOMAP		= (1 << 2),
4098c2ecf20Sopenharmony_ci	VPD		= (1 << 1),
4108c2ecf20Sopenharmony_ci	PMEnable	= (1 << 0),	/* Power Management Enable */
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_ci	/* Config2 register p. 25 */
4138c2ecf20Sopenharmony_ci	ClkReqEn	= (1 << 7),	/* Clock Request Enable */
4148c2ecf20Sopenharmony_ci	MSIEnable	= (1 << 5),	/* 8169 only. Reserved in the 8168. */
4158c2ecf20Sopenharmony_ci	PCI_Clock_66MHz = 0x01,
4168c2ecf20Sopenharmony_ci	PCI_Clock_33MHz = 0x00,
4178c2ecf20Sopenharmony_ci
4188c2ecf20Sopenharmony_ci	/* Config3 register p.25 */
4198c2ecf20Sopenharmony_ci	MagicPacket	= (1 << 5),	/* Wake up when receives a Magic Packet */
4208c2ecf20Sopenharmony_ci	LinkUp		= (1 << 4),	/* Wake up when the cable connection is re-established */
4218c2ecf20Sopenharmony_ci	Jumbo_En0	= (1 << 2),	/* 8168 only. Reserved in the 8168b */
4228c2ecf20Sopenharmony_ci	Rdy_to_L23	= (1 << 1),	/* L23 Enable */
4238c2ecf20Sopenharmony_ci	Beacon_en	= (1 << 0),	/* 8168 only. Reserved in the 8168b */
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci	/* Config4 register */
4268c2ecf20Sopenharmony_ci	Jumbo_En1	= (1 << 1),	/* 8168 only. Reserved in the 8168b */
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	/* Config5 register p.27 */
4298c2ecf20Sopenharmony_ci	BWF		= (1 << 6),	/* Accept Broadcast wakeup frame */
4308c2ecf20Sopenharmony_ci	MWF		= (1 << 5),	/* Accept Multicast wakeup frame */
4318c2ecf20Sopenharmony_ci	UWF		= (1 << 4),	/* Accept Unicast wakeup frame */
4328c2ecf20Sopenharmony_ci	Spi_en		= (1 << 3),
4338c2ecf20Sopenharmony_ci	LanWake		= (1 << 1),	/* LanWake enable/disable */
4348c2ecf20Sopenharmony_ci	PMEStatus	= (1 << 0),	/* PME status can be reset by PCI RST# */
4358c2ecf20Sopenharmony_ci	ASPM_en		= (1 << 0),	/* ASPM enable */
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	/* CPlusCmd p.31 */
4388c2ecf20Sopenharmony_ci	EnableBist	= (1 << 15),	// 8168 8101
4398c2ecf20Sopenharmony_ci	Mac_dbgo_oe	= (1 << 14),	// 8168 8101
4408c2ecf20Sopenharmony_ci	EnAnaPLL	= (1 << 14),	// 8169
4418c2ecf20Sopenharmony_ci	Normal_mode	= (1 << 13),	// unused
4428c2ecf20Sopenharmony_ci	Force_half_dup	= (1 << 12),	// 8168 8101
4438c2ecf20Sopenharmony_ci	Force_rxflow_en	= (1 << 11),	// 8168 8101
4448c2ecf20Sopenharmony_ci	Force_txflow_en	= (1 << 10),	// 8168 8101
4458c2ecf20Sopenharmony_ci	Cxpl_dbg_sel	= (1 << 9),	// 8168 8101
4468c2ecf20Sopenharmony_ci	ASF		= (1 << 8),	// 8168 8101
4478c2ecf20Sopenharmony_ci	PktCntrDisable	= (1 << 7),	// 8168 8101
4488c2ecf20Sopenharmony_ci	Mac_dbgo_sel	= 0x001c,	// 8168
4498c2ecf20Sopenharmony_ci	RxVlan		= (1 << 6),
4508c2ecf20Sopenharmony_ci	RxChkSum	= (1 << 5),
4518c2ecf20Sopenharmony_ci	PCIDAC		= (1 << 4),
4528c2ecf20Sopenharmony_ci	PCIMulRW	= (1 << 3),
4538c2ecf20Sopenharmony_ci#define INTT_MASK	GENMASK(1, 0)
4548c2ecf20Sopenharmony_ci#define CPCMD_MASK	(Normal_mode | RxVlan | RxChkSum | INTT_MASK)
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	/* rtl8169_PHYstatus */
4578c2ecf20Sopenharmony_ci	TBI_Enable	= 0x80,
4588c2ecf20Sopenharmony_ci	TxFlowCtrl	= 0x40,
4598c2ecf20Sopenharmony_ci	RxFlowCtrl	= 0x20,
4608c2ecf20Sopenharmony_ci	_1000bpsF	= 0x10,
4618c2ecf20Sopenharmony_ci	_100bps		= 0x08,
4628c2ecf20Sopenharmony_ci	_10bps		= 0x04,
4638c2ecf20Sopenharmony_ci	LinkStatus	= 0x02,
4648c2ecf20Sopenharmony_ci	FullDup		= 0x01,
4658c2ecf20Sopenharmony_ci
4668c2ecf20Sopenharmony_ci	/* ResetCounterCommand */
4678c2ecf20Sopenharmony_ci	CounterReset	= 0x1,
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	/* DumpCounterCommand */
4708c2ecf20Sopenharmony_ci	CounterDump	= 0x8,
4718c2ecf20Sopenharmony_ci
4728c2ecf20Sopenharmony_ci	/* magic enable v2 */
4738c2ecf20Sopenharmony_ci	MagicPacket_v2	= (1 << 16),	/* Wake up when receives a Magic Packet */
4748c2ecf20Sopenharmony_ci};
4758c2ecf20Sopenharmony_ci
4768c2ecf20Sopenharmony_cienum rtl_desc_bit {
4778c2ecf20Sopenharmony_ci	/* First doubleword. */
4788c2ecf20Sopenharmony_ci	DescOwn		= (1 << 31), /* Descriptor is owned by NIC */
4798c2ecf20Sopenharmony_ci	RingEnd		= (1 << 30), /* End of descriptor ring */
4808c2ecf20Sopenharmony_ci	FirstFrag	= (1 << 29), /* First segment of a packet */
4818c2ecf20Sopenharmony_ci	LastFrag	= (1 << 28), /* Final segment of a packet */
4828c2ecf20Sopenharmony_ci};
4838c2ecf20Sopenharmony_ci
4848c2ecf20Sopenharmony_ci/* Generic case. */
4858c2ecf20Sopenharmony_cienum rtl_tx_desc_bit {
4868c2ecf20Sopenharmony_ci	/* First doubleword. */
4878c2ecf20Sopenharmony_ci	TD_LSO		= (1 << 27),		/* Large Send Offload */
4888c2ecf20Sopenharmony_ci#define TD_MSS_MAX			0x07ffu	/* MSS value */
4898c2ecf20Sopenharmony_ci
4908c2ecf20Sopenharmony_ci	/* Second doubleword. */
4918c2ecf20Sopenharmony_ci	TxVlanTag	= (1 << 17),		/* Add VLAN tag */
4928c2ecf20Sopenharmony_ci};
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci/* 8169, 8168b and 810x except 8102e. */
4958c2ecf20Sopenharmony_cienum rtl_tx_desc_bit_0 {
4968c2ecf20Sopenharmony_ci	/* First doubleword. */
4978c2ecf20Sopenharmony_ci#define TD0_MSS_SHIFT			16	/* MSS position (11 bits) */
4988c2ecf20Sopenharmony_ci	TD0_TCP_CS	= (1 << 16),		/* Calculate TCP/IP checksum */
4998c2ecf20Sopenharmony_ci	TD0_UDP_CS	= (1 << 17),		/* Calculate UDP/IP checksum */
5008c2ecf20Sopenharmony_ci	TD0_IP_CS	= (1 << 18),		/* Calculate IP checksum */
5018c2ecf20Sopenharmony_ci};
5028c2ecf20Sopenharmony_ci
5038c2ecf20Sopenharmony_ci/* 8102e, 8168c and beyond. */
5048c2ecf20Sopenharmony_cienum rtl_tx_desc_bit_1 {
5058c2ecf20Sopenharmony_ci	/* First doubleword. */
5068c2ecf20Sopenharmony_ci	TD1_GTSENV4	= (1 << 26),		/* Giant Send for IPv4 */
5078c2ecf20Sopenharmony_ci	TD1_GTSENV6	= (1 << 25),		/* Giant Send for IPv6 */
5088c2ecf20Sopenharmony_ci#define GTTCPHO_SHIFT			18
5098c2ecf20Sopenharmony_ci#define GTTCPHO_MAX			0x7f
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	/* Second doubleword. */
5128c2ecf20Sopenharmony_ci#define TCPHO_SHIFT			18
5138c2ecf20Sopenharmony_ci#define TCPHO_MAX			0x3ff
5148c2ecf20Sopenharmony_ci#define TD1_MSS_SHIFT			18	/* MSS position (11 bits) */
5158c2ecf20Sopenharmony_ci	TD1_IPv6_CS	= (1 << 28),		/* Calculate IPv6 checksum */
5168c2ecf20Sopenharmony_ci	TD1_IPv4_CS	= (1 << 29),		/* Calculate IPv4 checksum */
5178c2ecf20Sopenharmony_ci	TD1_TCP_CS	= (1 << 30),		/* Calculate TCP/IP checksum */
5188c2ecf20Sopenharmony_ci	TD1_UDP_CS	= (1 << 31),		/* Calculate UDP/IP checksum */
5198c2ecf20Sopenharmony_ci};
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_cienum rtl_rx_desc_bit {
5228c2ecf20Sopenharmony_ci	/* Rx private */
5238c2ecf20Sopenharmony_ci	PID1		= (1 << 18), /* Protocol ID bit 1/2 */
5248c2ecf20Sopenharmony_ci	PID0		= (1 << 17), /* Protocol ID bit 0/2 */
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci#define RxProtoUDP	(PID1)
5278c2ecf20Sopenharmony_ci#define RxProtoTCP	(PID0)
5288c2ecf20Sopenharmony_ci#define RxProtoIP	(PID1 | PID0)
5298c2ecf20Sopenharmony_ci#define RxProtoMask	RxProtoIP
5308c2ecf20Sopenharmony_ci
5318c2ecf20Sopenharmony_ci	IPFail		= (1 << 16), /* IP checksum failed */
5328c2ecf20Sopenharmony_ci	UDPFail		= (1 << 15), /* UDP/IP checksum failed */
5338c2ecf20Sopenharmony_ci	TCPFail		= (1 << 14), /* TCP/IP checksum failed */
5348c2ecf20Sopenharmony_ci	RxVlanTag	= (1 << 16), /* VLAN tag available */
5358c2ecf20Sopenharmony_ci};
5368c2ecf20Sopenharmony_ci
5378c2ecf20Sopenharmony_ci#define RTL_GSO_MAX_SIZE_V1	32000
5388c2ecf20Sopenharmony_ci#define RTL_GSO_MAX_SEGS_V1	24
5398c2ecf20Sopenharmony_ci#define RTL_GSO_MAX_SIZE_V2	64000
5408c2ecf20Sopenharmony_ci#define RTL_GSO_MAX_SEGS_V2	64
5418c2ecf20Sopenharmony_ci
5428c2ecf20Sopenharmony_cistruct TxDesc {
5438c2ecf20Sopenharmony_ci	__le32 opts1;
5448c2ecf20Sopenharmony_ci	__le32 opts2;
5458c2ecf20Sopenharmony_ci	__le64 addr;
5468c2ecf20Sopenharmony_ci};
5478c2ecf20Sopenharmony_ci
5488c2ecf20Sopenharmony_cistruct RxDesc {
5498c2ecf20Sopenharmony_ci	__le32 opts1;
5508c2ecf20Sopenharmony_ci	__le32 opts2;
5518c2ecf20Sopenharmony_ci	__le64 addr;
5528c2ecf20Sopenharmony_ci};
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_cistruct ring_info {
5558c2ecf20Sopenharmony_ci	struct sk_buff	*skb;
5568c2ecf20Sopenharmony_ci	u32		len;
5578c2ecf20Sopenharmony_ci};
5588c2ecf20Sopenharmony_ci
5598c2ecf20Sopenharmony_cistruct rtl8169_counters {
5608c2ecf20Sopenharmony_ci	__le64	tx_packets;
5618c2ecf20Sopenharmony_ci	__le64	rx_packets;
5628c2ecf20Sopenharmony_ci	__le64	tx_errors;
5638c2ecf20Sopenharmony_ci	__le32	rx_errors;
5648c2ecf20Sopenharmony_ci	__le16	rx_missed;
5658c2ecf20Sopenharmony_ci	__le16	align_errors;
5668c2ecf20Sopenharmony_ci	__le32	tx_one_collision;
5678c2ecf20Sopenharmony_ci	__le32	tx_multi_collision;
5688c2ecf20Sopenharmony_ci	__le64	rx_unicast;
5698c2ecf20Sopenharmony_ci	__le64	rx_broadcast;
5708c2ecf20Sopenharmony_ci	__le32	rx_multicast;
5718c2ecf20Sopenharmony_ci	__le16	tx_aborted;
5728c2ecf20Sopenharmony_ci	__le16	tx_underun;
5738c2ecf20Sopenharmony_ci};
5748c2ecf20Sopenharmony_ci
5758c2ecf20Sopenharmony_cistruct rtl8169_tc_offsets {
5768c2ecf20Sopenharmony_ci	bool	inited;
5778c2ecf20Sopenharmony_ci	__le64	tx_errors;
5788c2ecf20Sopenharmony_ci	__le32	tx_multi_collision;
5798c2ecf20Sopenharmony_ci	__le16	tx_aborted;
5808c2ecf20Sopenharmony_ci	__le16	rx_missed;
5818c2ecf20Sopenharmony_ci};
5828c2ecf20Sopenharmony_ci
5838c2ecf20Sopenharmony_cienum rtl_flag {
5848c2ecf20Sopenharmony_ci	RTL_FLAG_TASK_ENABLED = 0,
5858c2ecf20Sopenharmony_ci	RTL_FLAG_TASK_RESET_PENDING,
5868c2ecf20Sopenharmony_ci	RTL_FLAG_TASK_RESET_NO_QUEUE_WAKE,
5878c2ecf20Sopenharmony_ci	RTL_FLAG_TASK_TX_TIMEOUT,
5888c2ecf20Sopenharmony_ci	RTL_FLAG_MAX
5898c2ecf20Sopenharmony_ci};
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_cistruct rtl8169_stats {
5928c2ecf20Sopenharmony_ci	u64			packets;
5938c2ecf20Sopenharmony_ci	u64			bytes;
5948c2ecf20Sopenharmony_ci	struct u64_stats_sync	syncp;
5958c2ecf20Sopenharmony_ci};
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_cistruct rtl8169_private {
5988c2ecf20Sopenharmony_ci	void __iomem *mmio_addr;	/* memory map physical address */
5998c2ecf20Sopenharmony_ci	struct pci_dev *pci_dev;
6008c2ecf20Sopenharmony_ci	struct net_device *dev;
6018c2ecf20Sopenharmony_ci	struct phy_device *phydev;
6028c2ecf20Sopenharmony_ci	struct napi_struct napi;
6038c2ecf20Sopenharmony_ci	enum mac_version mac_version;
6048c2ecf20Sopenharmony_ci	u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */
6058c2ecf20Sopenharmony_ci	u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */
6068c2ecf20Sopenharmony_ci	u32 dirty_tx;
6078c2ecf20Sopenharmony_ci	struct rtl8169_stats rx_stats;
6088c2ecf20Sopenharmony_ci	struct rtl8169_stats tx_stats;
6098c2ecf20Sopenharmony_ci	struct TxDesc *TxDescArray;	/* 256-aligned Tx descriptor ring */
6108c2ecf20Sopenharmony_ci	struct RxDesc *RxDescArray;	/* 256-aligned Rx descriptor ring */
6118c2ecf20Sopenharmony_ci	dma_addr_t TxPhyAddr;
6128c2ecf20Sopenharmony_ci	dma_addr_t RxPhyAddr;
6138c2ecf20Sopenharmony_ci	struct page *Rx_databuff[NUM_RX_DESC];	/* Rx data buffers */
6148c2ecf20Sopenharmony_ci	struct ring_info tx_skb[NUM_TX_DESC];	/* Tx data buffers */
6158c2ecf20Sopenharmony_ci	u16 cp_cmd;
6168c2ecf20Sopenharmony_ci	u32 irq_mask;
6178c2ecf20Sopenharmony_ci	struct clk *clk;
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	struct {
6208c2ecf20Sopenharmony_ci		DECLARE_BITMAP(flags, RTL_FLAG_MAX);
6218c2ecf20Sopenharmony_ci		struct work_struct work;
6228c2ecf20Sopenharmony_ci	} wk;
6238c2ecf20Sopenharmony_ci
6248c2ecf20Sopenharmony_ci	unsigned supports_gmii:1;
6258c2ecf20Sopenharmony_ci	unsigned aspm_manageable:1;
6268c2ecf20Sopenharmony_ci	dma_addr_t counters_phys_addr;
6278c2ecf20Sopenharmony_ci	struct rtl8169_counters *counters;
6288c2ecf20Sopenharmony_ci	struct rtl8169_tc_offsets tc_offset;
6298c2ecf20Sopenharmony_ci	u32 saved_wolopts;
6308c2ecf20Sopenharmony_ci	int eee_adv;
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ci	const char *fw_name;
6338c2ecf20Sopenharmony_ci	struct rtl_fw *rtl_fw;
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci	u32 ocp_base;
6368c2ecf20Sopenharmony_ci};
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_citypedef void (*rtl_generic_fct)(struct rtl8169_private *tp);
6398c2ecf20Sopenharmony_ci
6408c2ecf20Sopenharmony_ciMODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
6418c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver");
6428c2ecf20Sopenharmony_ciMODULE_SOFTDEP("pre: realtek");
6438c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
6448c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FIRMWARE_8168D_1);
6458c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FIRMWARE_8168D_2);
6468c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FIRMWARE_8168E_1);
6478c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FIRMWARE_8168E_2);
6488c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FIRMWARE_8168E_3);
6498c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FIRMWARE_8105E_1);
6508c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FIRMWARE_8168F_1);
6518c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FIRMWARE_8168F_2);
6528c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FIRMWARE_8402_1);
6538c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FIRMWARE_8411_1);
6548c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FIRMWARE_8411_2);
6558c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FIRMWARE_8106E_1);
6568c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FIRMWARE_8106E_2);
6578c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FIRMWARE_8168G_2);
6588c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FIRMWARE_8168G_3);
6598c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FIRMWARE_8168H_1);
6608c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FIRMWARE_8168H_2);
6618c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FIRMWARE_8168FP_3);
6628c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FIRMWARE_8107E_1);
6638c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FIRMWARE_8107E_2);
6648c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FIRMWARE_8125A_3);
6658c2ecf20Sopenharmony_ciMODULE_FIRMWARE(FIRMWARE_8125B_2);
6668c2ecf20Sopenharmony_ci
6678c2ecf20Sopenharmony_cistatic inline struct device *tp_to_dev(struct rtl8169_private *tp)
6688c2ecf20Sopenharmony_ci{
6698c2ecf20Sopenharmony_ci	return &tp->pci_dev->dev;
6708c2ecf20Sopenharmony_ci}
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_cistatic void rtl_lock_config_regs(struct rtl8169_private *tp)
6738c2ecf20Sopenharmony_ci{
6748c2ecf20Sopenharmony_ci	RTL_W8(tp, Cfg9346, Cfg9346_Lock);
6758c2ecf20Sopenharmony_ci}
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_cistatic void rtl_unlock_config_regs(struct rtl8169_private *tp)
6788c2ecf20Sopenharmony_ci{
6798c2ecf20Sopenharmony_ci	RTL_W8(tp, Cfg9346, Cfg9346_Unlock);
6808c2ecf20Sopenharmony_ci}
6818c2ecf20Sopenharmony_ci
6828c2ecf20Sopenharmony_cistatic void rtl_pci_commit(struct rtl8169_private *tp)
6838c2ecf20Sopenharmony_ci{
6848c2ecf20Sopenharmony_ci	/* Read an arbitrary register to commit a preceding PCI write */
6858c2ecf20Sopenharmony_ci	RTL_R8(tp, ChipCmd);
6868c2ecf20Sopenharmony_ci}
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_cistatic bool rtl_is_8125(struct rtl8169_private *tp)
6898c2ecf20Sopenharmony_ci{
6908c2ecf20Sopenharmony_ci	return tp->mac_version >= RTL_GIGA_MAC_VER_60;
6918c2ecf20Sopenharmony_ci}
6928c2ecf20Sopenharmony_ci
6938c2ecf20Sopenharmony_cistatic bool rtl_is_8168evl_up(struct rtl8169_private *tp)
6948c2ecf20Sopenharmony_ci{
6958c2ecf20Sopenharmony_ci	return tp->mac_version >= RTL_GIGA_MAC_VER_34 &&
6968c2ecf20Sopenharmony_ci	       tp->mac_version != RTL_GIGA_MAC_VER_39 &&
6978c2ecf20Sopenharmony_ci	       tp->mac_version <= RTL_GIGA_MAC_VER_52;
6988c2ecf20Sopenharmony_ci}
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_cistatic bool rtl_supports_eee(struct rtl8169_private *tp)
7018c2ecf20Sopenharmony_ci{
7028c2ecf20Sopenharmony_ci	return tp->mac_version >= RTL_GIGA_MAC_VER_34 &&
7038c2ecf20Sopenharmony_ci	       tp->mac_version != RTL_GIGA_MAC_VER_37 &&
7048c2ecf20Sopenharmony_ci	       tp->mac_version != RTL_GIGA_MAC_VER_39;
7058c2ecf20Sopenharmony_ci}
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_cistatic void rtl_get_priv_stats(struct rtl8169_stats *stats,
7088c2ecf20Sopenharmony_ci			       u64 *pkts, u64 *bytes)
7098c2ecf20Sopenharmony_ci{
7108c2ecf20Sopenharmony_ci	unsigned int start;
7118c2ecf20Sopenharmony_ci
7128c2ecf20Sopenharmony_ci	do {
7138c2ecf20Sopenharmony_ci		start = u64_stats_fetch_begin_irq(&stats->syncp);
7148c2ecf20Sopenharmony_ci		*pkts = stats->packets;
7158c2ecf20Sopenharmony_ci		*bytes = stats->bytes;
7168c2ecf20Sopenharmony_ci	} while (u64_stats_fetch_retry_irq(&stats->syncp, start));
7178c2ecf20Sopenharmony_ci}
7188c2ecf20Sopenharmony_ci
7198c2ecf20Sopenharmony_cistatic void rtl_inc_priv_stats(struct rtl8169_stats *stats,
7208c2ecf20Sopenharmony_ci			       u64 pkts, u64 bytes)
7218c2ecf20Sopenharmony_ci{
7228c2ecf20Sopenharmony_ci	u64_stats_update_begin(&stats->syncp);
7238c2ecf20Sopenharmony_ci	stats->packets += pkts;
7248c2ecf20Sopenharmony_ci	stats->bytes += bytes;
7258c2ecf20Sopenharmony_ci	u64_stats_update_end(&stats->syncp);
7268c2ecf20Sopenharmony_ci}
7278c2ecf20Sopenharmony_ci
7288c2ecf20Sopenharmony_cistatic void rtl_read_mac_from_reg(struct rtl8169_private *tp, u8 *mac, int reg)
7298c2ecf20Sopenharmony_ci{
7308c2ecf20Sopenharmony_ci	int i;
7318c2ecf20Sopenharmony_ci
7328c2ecf20Sopenharmony_ci	for (i = 0; i < ETH_ALEN; i++)
7338c2ecf20Sopenharmony_ci		mac[i] = RTL_R8(tp, reg + i);
7348c2ecf20Sopenharmony_ci}
7358c2ecf20Sopenharmony_ci
7368c2ecf20Sopenharmony_cistruct rtl_cond {
7378c2ecf20Sopenharmony_ci	bool (*check)(struct rtl8169_private *);
7388c2ecf20Sopenharmony_ci	const char *msg;
7398c2ecf20Sopenharmony_ci};
7408c2ecf20Sopenharmony_ci
7418c2ecf20Sopenharmony_cistatic bool rtl_loop_wait(struct rtl8169_private *tp, const struct rtl_cond *c,
7428c2ecf20Sopenharmony_ci			  unsigned long usecs, int n, bool high)
7438c2ecf20Sopenharmony_ci{
7448c2ecf20Sopenharmony_ci	int i;
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_ci	for (i = 0; i < n; i++) {
7478c2ecf20Sopenharmony_ci		if (c->check(tp) == high)
7488c2ecf20Sopenharmony_ci			return true;
7498c2ecf20Sopenharmony_ci		fsleep(usecs);
7508c2ecf20Sopenharmony_ci	}
7518c2ecf20Sopenharmony_ci
7528c2ecf20Sopenharmony_ci	if (net_ratelimit())
7538c2ecf20Sopenharmony_ci		netdev_err(tp->dev, "%s == %d (loop: %d, delay: %lu).\n",
7548c2ecf20Sopenharmony_ci			   c->msg, !high, n, usecs);
7558c2ecf20Sopenharmony_ci	return false;
7568c2ecf20Sopenharmony_ci}
7578c2ecf20Sopenharmony_ci
7588c2ecf20Sopenharmony_cistatic bool rtl_loop_wait_high(struct rtl8169_private *tp,
7598c2ecf20Sopenharmony_ci			       const struct rtl_cond *c,
7608c2ecf20Sopenharmony_ci			       unsigned long d, int n)
7618c2ecf20Sopenharmony_ci{
7628c2ecf20Sopenharmony_ci	return rtl_loop_wait(tp, c, d, n, true);
7638c2ecf20Sopenharmony_ci}
7648c2ecf20Sopenharmony_ci
7658c2ecf20Sopenharmony_cistatic bool rtl_loop_wait_low(struct rtl8169_private *tp,
7668c2ecf20Sopenharmony_ci			      const struct rtl_cond *c,
7678c2ecf20Sopenharmony_ci			      unsigned long d, int n)
7688c2ecf20Sopenharmony_ci{
7698c2ecf20Sopenharmony_ci	return rtl_loop_wait(tp, c, d, n, false);
7708c2ecf20Sopenharmony_ci}
7718c2ecf20Sopenharmony_ci
7728c2ecf20Sopenharmony_ci#define DECLARE_RTL_COND(name)				\
7738c2ecf20Sopenharmony_cistatic bool name ## _check(struct rtl8169_private *);	\
7748c2ecf20Sopenharmony_ci							\
7758c2ecf20Sopenharmony_cistatic const struct rtl_cond name = {			\
7768c2ecf20Sopenharmony_ci	.check	= name ## _check,			\
7778c2ecf20Sopenharmony_ci	.msg	= #name					\
7788c2ecf20Sopenharmony_ci};							\
7798c2ecf20Sopenharmony_ci							\
7808c2ecf20Sopenharmony_cistatic bool name ## _check(struct rtl8169_private *tp)
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_cistatic bool rtl_ocp_reg_failure(struct rtl8169_private *tp, u32 reg)
7838c2ecf20Sopenharmony_ci{
7848c2ecf20Sopenharmony_ci	if (reg & 0xffff0001) {
7858c2ecf20Sopenharmony_ci		if (net_ratelimit())
7868c2ecf20Sopenharmony_ci			netdev_err(tp->dev, "Invalid ocp reg %x!\n", reg);
7878c2ecf20Sopenharmony_ci		return true;
7888c2ecf20Sopenharmony_ci	}
7898c2ecf20Sopenharmony_ci	return false;
7908c2ecf20Sopenharmony_ci}
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ciDECLARE_RTL_COND(rtl_ocp_gphy_cond)
7938c2ecf20Sopenharmony_ci{
7948c2ecf20Sopenharmony_ci	return RTL_R32(tp, GPHY_OCP) & OCPAR_FLAG;
7958c2ecf20Sopenharmony_ci}
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_cistatic void r8168_phy_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
7988c2ecf20Sopenharmony_ci{
7998c2ecf20Sopenharmony_ci	if (rtl_ocp_reg_failure(tp, reg))
8008c2ecf20Sopenharmony_ci		return;
8018c2ecf20Sopenharmony_ci
8028c2ecf20Sopenharmony_ci	RTL_W32(tp, GPHY_OCP, OCPAR_FLAG | (reg << 15) | data);
8038c2ecf20Sopenharmony_ci
8048c2ecf20Sopenharmony_ci	rtl_loop_wait_low(tp, &rtl_ocp_gphy_cond, 25, 10);
8058c2ecf20Sopenharmony_ci}
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_cistatic int r8168_phy_ocp_read(struct rtl8169_private *tp, u32 reg)
8088c2ecf20Sopenharmony_ci{
8098c2ecf20Sopenharmony_ci	if (rtl_ocp_reg_failure(tp, reg))
8108c2ecf20Sopenharmony_ci		return 0;
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_ci	RTL_W32(tp, GPHY_OCP, reg << 15);
8138c2ecf20Sopenharmony_ci
8148c2ecf20Sopenharmony_ci	return rtl_loop_wait_high(tp, &rtl_ocp_gphy_cond, 25, 10) ?
8158c2ecf20Sopenharmony_ci		(RTL_R32(tp, GPHY_OCP) & 0xffff) : -ETIMEDOUT;
8168c2ecf20Sopenharmony_ci}
8178c2ecf20Sopenharmony_ci
8188c2ecf20Sopenharmony_cistatic void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data)
8198c2ecf20Sopenharmony_ci{
8208c2ecf20Sopenharmony_ci	if (rtl_ocp_reg_failure(tp, reg))
8218c2ecf20Sopenharmony_ci		return;
8228c2ecf20Sopenharmony_ci
8238c2ecf20Sopenharmony_ci	RTL_W32(tp, OCPDR, OCPAR_FLAG | (reg << 15) | data);
8248c2ecf20Sopenharmony_ci}
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_cistatic u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg)
8278c2ecf20Sopenharmony_ci{
8288c2ecf20Sopenharmony_ci	if (rtl_ocp_reg_failure(tp, reg))
8298c2ecf20Sopenharmony_ci		return 0;
8308c2ecf20Sopenharmony_ci
8318c2ecf20Sopenharmony_ci	RTL_W32(tp, OCPDR, reg << 15);
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci	return RTL_R32(tp, OCPDR);
8348c2ecf20Sopenharmony_ci}
8358c2ecf20Sopenharmony_ci
8368c2ecf20Sopenharmony_cistatic void r8168_mac_ocp_modify(struct rtl8169_private *tp, u32 reg, u16 mask,
8378c2ecf20Sopenharmony_ci				 u16 set)
8388c2ecf20Sopenharmony_ci{
8398c2ecf20Sopenharmony_ci	u16 data = r8168_mac_ocp_read(tp, reg);
8408c2ecf20Sopenharmony_ci
8418c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, reg, (data & ~mask) | set);
8428c2ecf20Sopenharmony_ci}
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_cistatic void r8168g_mdio_write(struct rtl8169_private *tp, int reg, int value)
8458c2ecf20Sopenharmony_ci{
8468c2ecf20Sopenharmony_ci	if (reg == 0x1f) {
8478c2ecf20Sopenharmony_ci		tp->ocp_base = value ? value << 4 : OCP_STD_PHY_BASE;
8488c2ecf20Sopenharmony_ci		return;
8498c2ecf20Sopenharmony_ci	}
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci	if (tp->ocp_base != OCP_STD_PHY_BASE)
8528c2ecf20Sopenharmony_ci		reg -= 0x10;
8538c2ecf20Sopenharmony_ci
8548c2ecf20Sopenharmony_ci	r8168_phy_ocp_write(tp, tp->ocp_base + reg * 2, value);
8558c2ecf20Sopenharmony_ci}
8568c2ecf20Sopenharmony_ci
8578c2ecf20Sopenharmony_cistatic int r8168g_mdio_read(struct rtl8169_private *tp, int reg)
8588c2ecf20Sopenharmony_ci{
8598c2ecf20Sopenharmony_ci	if (reg == 0x1f)
8608c2ecf20Sopenharmony_ci		return tp->ocp_base == OCP_STD_PHY_BASE ? 0 : tp->ocp_base >> 4;
8618c2ecf20Sopenharmony_ci
8628c2ecf20Sopenharmony_ci	if (tp->ocp_base != OCP_STD_PHY_BASE)
8638c2ecf20Sopenharmony_ci		reg -= 0x10;
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_ci	return r8168_phy_ocp_read(tp, tp->ocp_base + reg * 2);
8668c2ecf20Sopenharmony_ci}
8678c2ecf20Sopenharmony_ci
8688c2ecf20Sopenharmony_cistatic void mac_mcu_write(struct rtl8169_private *tp, int reg, int value)
8698c2ecf20Sopenharmony_ci{
8708c2ecf20Sopenharmony_ci	if (reg == 0x1f) {
8718c2ecf20Sopenharmony_ci		tp->ocp_base = value << 4;
8728c2ecf20Sopenharmony_ci		return;
8738c2ecf20Sopenharmony_ci	}
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, tp->ocp_base + reg, value);
8768c2ecf20Sopenharmony_ci}
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_cistatic int mac_mcu_read(struct rtl8169_private *tp, int reg)
8798c2ecf20Sopenharmony_ci{
8808c2ecf20Sopenharmony_ci	return r8168_mac_ocp_read(tp, tp->ocp_base + reg);
8818c2ecf20Sopenharmony_ci}
8828c2ecf20Sopenharmony_ci
8838c2ecf20Sopenharmony_ciDECLARE_RTL_COND(rtl_phyar_cond)
8848c2ecf20Sopenharmony_ci{
8858c2ecf20Sopenharmony_ci	return RTL_R32(tp, PHYAR) & 0x80000000;
8868c2ecf20Sopenharmony_ci}
8878c2ecf20Sopenharmony_ci
8888c2ecf20Sopenharmony_cistatic void r8169_mdio_write(struct rtl8169_private *tp, int reg, int value)
8898c2ecf20Sopenharmony_ci{
8908c2ecf20Sopenharmony_ci	RTL_W32(tp, PHYAR, 0x80000000 | (reg & 0x1f) << 16 | (value & 0xffff));
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_ci	rtl_loop_wait_low(tp, &rtl_phyar_cond, 25, 20);
8938c2ecf20Sopenharmony_ci	/*
8948c2ecf20Sopenharmony_ci	 * According to hardware specs a 20us delay is required after write
8958c2ecf20Sopenharmony_ci	 * complete indication, but before sending next command.
8968c2ecf20Sopenharmony_ci	 */
8978c2ecf20Sopenharmony_ci	udelay(20);
8988c2ecf20Sopenharmony_ci}
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_cistatic int r8169_mdio_read(struct rtl8169_private *tp, int reg)
9018c2ecf20Sopenharmony_ci{
9028c2ecf20Sopenharmony_ci	int value;
9038c2ecf20Sopenharmony_ci
9048c2ecf20Sopenharmony_ci	RTL_W32(tp, PHYAR, 0x0 | (reg & 0x1f) << 16);
9058c2ecf20Sopenharmony_ci
9068c2ecf20Sopenharmony_ci	value = rtl_loop_wait_high(tp, &rtl_phyar_cond, 25, 20) ?
9078c2ecf20Sopenharmony_ci		RTL_R32(tp, PHYAR) & 0xffff : -ETIMEDOUT;
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_ci	/*
9108c2ecf20Sopenharmony_ci	 * According to hardware specs a 20us delay is required after read
9118c2ecf20Sopenharmony_ci	 * complete indication, but before sending next command.
9128c2ecf20Sopenharmony_ci	 */
9138c2ecf20Sopenharmony_ci	udelay(20);
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_ci	return value;
9168c2ecf20Sopenharmony_ci}
9178c2ecf20Sopenharmony_ci
9188c2ecf20Sopenharmony_ciDECLARE_RTL_COND(rtl_ocpar_cond)
9198c2ecf20Sopenharmony_ci{
9208c2ecf20Sopenharmony_ci	return RTL_R32(tp, OCPAR) & OCPAR_FLAG;
9218c2ecf20Sopenharmony_ci}
9228c2ecf20Sopenharmony_ci
9238c2ecf20Sopenharmony_cistatic void r8168dp_1_mdio_access(struct rtl8169_private *tp, int reg, u32 data)
9248c2ecf20Sopenharmony_ci{
9258c2ecf20Sopenharmony_ci	RTL_W32(tp, OCPDR, data | ((reg & OCPDR_REG_MASK) << OCPDR_GPHY_REG_SHIFT));
9268c2ecf20Sopenharmony_ci	RTL_W32(tp, OCPAR, OCPAR_GPHY_WRITE_CMD);
9278c2ecf20Sopenharmony_ci	RTL_W32(tp, EPHY_RXER_NUM, 0);
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_ci	rtl_loop_wait_low(tp, &rtl_ocpar_cond, 1000, 100);
9308c2ecf20Sopenharmony_ci}
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_cistatic void r8168dp_1_mdio_write(struct rtl8169_private *tp, int reg, int value)
9338c2ecf20Sopenharmony_ci{
9348c2ecf20Sopenharmony_ci	r8168dp_1_mdio_access(tp, reg,
9358c2ecf20Sopenharmony_ci			      OCPDR_WRITE_CMD | (value & OCPDR_DATA_MASK));
9368c2ecf20Sopenharmony_ci}
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_cistatic int r8168dp_1_mdio_read(struct rtl8169_private *tp, int reg)
9398c2ecf20Sopenharmony_ci{
9408c2ecf20Sopenharmony_ci	r8168dp_1_mdio_access(tp, reg, OCPDR_READ_CMD);
9418c2ecf20Sopenharmony_ci
9428c2ecf20Sopenharmony_ci	mdelay(1);
9438c2ecf20Sopenharmony_ci	RTL_W32(tp, OCPAR, OCPAR_GPHY_READ_CMD);
9448c2ecf20Sopenharmony_ci	RTL_W32(tp, EPHY_RXER_NUM, 0);
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_ci	return rtl_loop_wait_high(tp, &rtl_ocpar_cond, 1000, 100) ?
9478c2ecf20Sopenharmony_ci		RTL_R32(tp, OCPDR) & OCPDR_DATA_MASK : -ETIMEDOUT;
9488c2ecf20Sopenharmony_ci}
9498c2ecf20Sopenharmony_ci
9508c2ecf20Sopenharmony_ci#define R8168DP_1_MDIO_ACCESS_BIT	0x00020000
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_cistatic void r8168dp_2_mdio_start(struct rtl8169_private *tp)
9538c2ecf20Sopenharmony_ci{
9548c2ecf20Sopenharmony_ci	RTL_W32(tp, 0xd0, RTL_R32(tp, 0xd0) & ~R8168DP_1_MDIO_ACCESS_BIT);
9558c2ecf20Sopenharmony_ci}
9568c2ecf20Sopenharmony_ci
9578c2ecf20Sopenharmony_cistatic void r8168dp_2_mdio_stop(struct rtl8169_private *tp)
9588c2ecf20Sopenharmony_ci{
9598c2ecf20Sopenharmony_ci	RTL_W32(tp, 0xd0, RTL_R32(tp, 0xd0) | R8168DP_1_MDIO_ACCESS_BIT);
9608c2ecf20Sopenharmony_ci}
9618c2ecf20Sopenharmony_ci
9628c2ecf20Sopenharmony_cistatic void r8168dp_2_mdio_write(struct rtl8169_private *tp, int reg, int value)
9638c2ecf20Sopenharmony_ci{
9648c2ecf20Sopenharmony_ci	r8168dp_2_mdio_start(tp);
9658c2ecf20Sopenharmony_ci
9668c2ecf20Sopenharmony_ci	r8169_mdio_write(tp, reg, value);
9678c2ecf20Sopenharmony_ci
9688c2ecf20Sopenharmony_ci	r8168dp_2_mdio_stop(tp);
9698c2ecf20Sopenharmony_ci}
9708c2ecf20Sopenharmony_ci
9718c2ecf20Sopenharmony_cistatic int r8168dp_2_mdio_read(struct rtl8169_private *tp, int reg)
9728c2ecf20Sopenharmony_ci{
9738c2ecf20Sopenharmony_ci	int value;
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_ci	/* Work around issue with chip reporting wrong PHY ID */
9768c2ecf20Sopenharmony_ci	if (reg == MII_PHYSID2)
9778c2ecf20Sopenharmony_ci		return 0xc912;
9788c2ecf20Sopenharmony_ci
9798c2ecf20Sopenharmony_ci	r8168dp_2_mdio_start(tp);
9808c2ecf20Sopenharmony_ci
9818c2ecf20Sopenharmony_ci	value = r8169_mdio_read(tp, reg);
9828c2ecf20Sopenharmony_ci
9838c2ecf20Sopenharmony_ci	r8168dp_2_mdio_stop(tp);
9848c2ecf20Sopenharmony_ci
9858c2ecf20Sopenharmony_ci	return value;
9868c2ecf20Sopenharmony_ci}
9878c2ecf20Sopenharmony_ci
9888c2ecf20Sopenharmony_cistatic void rtl_writephy(struct rtl8169_private *tp, int location, int val)
9898c2ecf20Sopenharmony_ci{
9908c2ecf20Sopenharmony_ci	switch (tp->mac_version) {
9918c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_27:
9928c2ecf20Sopenharmony_ci		r8168dp_1_mdio_write(tp, location, val);
9938c2ecf20Sopenharmony_ci		break;
9948c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_28:
9958c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_31:
9968c2ecf20Sopenharmony_ci		r8168dp_2_mdio_write(tp, location, val);
9978c2ecf20Sopenharmony_ci		break;
9988c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_63:
9998c2ecf20Sopenharmony_ci		r8168g_mdio_write(tp, location, val);
10008c2ecf20Sopenharmony_ci		break;
10018c2ecf20Sopenharmony_ci	default:
10028c2ecf20Sopenharmony_ci		r8169_mdio_write(tp, location, val);
10038c2ecf20Sopenharmony_ci		break;
10048c2ecf20Sopenharmony_ci	}
10058c2ecf20Sopenharmony_ci}
10068c2ecf20Sopenharmony_ci
10078c2ecf20Sopenharmony_cistatic int rtl_readphy(struct rtl8169_private *tp, int location)
10088c2ecf20Sopenharmony_ci{
10098c2ecf20Sopenharmony_ci	switch (tp->mac_version) {
10108c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_27:
10118c2ecf20Sopenharmony_ci		return r8168dp_1_mdio_read(tp, location);
10128c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_28:
10138c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_31:
10148c2ecf20Sopenharmony_ci		return r8168dp_2_mdio_read(tp, location);
10158c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_63:
10168c2ecf20Sopenharmony_ci		return r8168g_mdio_read(tp, location);
10178c2ecf20Sopenharmony_ci	default:
10188c2ecf20Sopenharmony_ci		return r8169_mdio_read(tp, location);
10198c2ecf20Sopenharmony_ci	}
10208c2ecf20Sopenharmony_ci}
10218c2ecf20Sopenharmony_ci
10228c2ecf20Sopenharmony_ciDECLARE_RTL_COND(rtl_ephyar_cond)
10238c2ecf20Sopenharmony_ci{
10248c2ecf20Sopenharmony_ci	return RTL_R32(tp, EPHYAR) & EPHYAR_FLAG;
10258c2ecf20Sopenharmony_ci}
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_cistatic void rtl_ephy_write(struct rtl8169_private *tp, int reg_addr, int value)
10288c2ecf20Sopenharmony_ci{
10298c2ecf20Sopenharmony_ci	RTL_W32(tp, EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) |
10308c2ecf20Sopenharmony_ci		(reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
10318c2ecf20Sopenharmony_ci
10328c2ecf20Sopenharmony_ci	rtl_loop_wait_low(tp, &rtl_ephyar_cond, 10, 100);
10338c2ecf20Sopenharmony_ci
10348c2ecf20Sopenharmony_ci	udelay(10);
10358c2ecf20Sopenharmony_ci}
10368c2ecf20Sopenharmony_ci
10378c2ecf20Sopenharmony_cistatic u16 rtl_ephy_read(struct rtl8169_private *tp, int reg_addr)
10388c2ecf20Sopenharmony_ci{
10398c2ecf20Sopenharmony_ci	RTL_W32(tp, EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT);
10408c2ecf20Sopenharmony_ci
10418c2ecf20Sopenharmony_ci	return rtl_loop_wait_high(tp, &rtl_ephyar_cond, 10, 100) ?
10428c2ecf20Sopenharmony_ci		RTL_R32(tp, EPHYAR) & EPHYAR_DATA_MASK : ~0;
10438c2ecf20Sopenharmony_ci}
10448c2ecf20Sopenharmony_ci
10458c2ecf20Sopenharmony_cistatic void r8168fp_adjust_ocp_cmd(struct rtl8169_private *tp, u32 *cmd, int type)
10468c2ecf20Sopenharmony_ci{
10478c2ecf20Sopenharmony_ci	/* based on RTL8168FP_OOBMAC_BASE in vendor driver */
10488c2ecf20Sopenharmony_ci	if (tp->mac_version == RTL_GIGA_MAC_VER_52 && type == ERIAR_OOB)
10498c2ecf20Sopenharmony_ci		*cmd |= 0xf70 << 18;
10508c2ecf20Sopenharmony_ci}
10518c2ecf20Sopenharmony_ci
10528c2ecf20Sopenharmony_ciDECLARE_RTL_COND(rtl_eriar_cond)
10538c2ecf20Sopenharmony_ci{
10548c2ecf20Sopenharmony_ci	return RTL_R32(tp, ERIAR) & ERIAR_FLAG;
10558c2ecf20Sopenharmony_ci}
10568c2ecf20Sopenharmony_ci
10578c2ecf20Sopenharmony_cistatic void _rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask,
10588c2ecf20Sopenharmony_ci			   u32 val, int type)
10598c2ecf20Sopenharmony_ci{
10608c2ecf20Sopenharmony_ci	u32 cmd = ERIAR_WRITE_CMD | type | mask | addr;
10618c2ecf20Sopenharmony_ci
10628c2ecf20Sopenharmony_ci	BUG_ON((addr & 3) || (mask == 0));
10638c2ecf20Sopenharmony_ci	RTL_W32(tp, ERIDR, val);
10648c2ecf20Sopenharmony_ci	r8168fp_adjust_ocp_cmd(tp, &cmd, type);
10658c2ecf20Sopenharmony_ci	RTL_W32(tp, ERIAR, cmd);
10668c2ecf20Sopenharmony_ci
10678c2ecf20Sopenharmony_ci	rtl_loop_wait_low(tp, &rtl_eriar_cond, 100, 100);
10688c2ecf20Sopenharmony_ci}
10698c2ecf20Sopenharmony_ci
10708c2ecf20Sopenharmony_cistatic void rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask,
10718c2ecf20Sopenharmony_ci			  u32 val)
10728c2ecf20Sopenharmony_ci{
10738c2ecf20Sopenharmony_ci	_rtl_eri_write(tp, addr, mask, val, ERIAR_EXGMAC);
10748c2ecf20Sopenharmony_ci}
10758c2ecf20Sopenharmony_ci
10768c2ecf20Sopenharmony_cistatic u32 _rtl_eri_read(struct rtl8169_private *tp, int addr, int type)
10778c2ecf20Sopenharmony_ci{
10788c2ecf20Sopenharmony_ci	u32 cmd = ERIAR_READ_CMD | type | ERIAR_MASK_1111 | addr;
10798c2ecf20Sopenharmony_ci
10808c2ecf20Sopenharmony_ci	r8168fp_adjust_ocp_cmd(tp, &cmd, type);
10818c2ecf20Sopenharmony_ci	RTL_W32(tp, ERIAR, cmd);
10828c2ecf20Sopenharmony_ci
10838c2ecf20Sopenharmony_ci	return rtl_loop_wait_high(tp, &rtl_eriar_cond, 100, 100) ?
10848c2ecf20Sopenharmony_ci		RTL_R32(tp, ERIDR) : ~0;
10858c2ecf20Sopenharmony_ci}
10868c2ecf20Sopenharmony_ci
10878c2ecf20Sopenharmony_cistatic u32 rtl_eri_read(struct rtl8169_private *tp, int addr)
10888c2ecf20Sopenharmony_ci{
10898c2ecf20Sopenharmony_ci	return _rtl_eri_read(tp, addr, ERIAR_EXGMAC);
10908c2ecf20Sopenharmony_ci}
10918c2ecf20Sopenharmony_ci
10928c2ecf20Sopenharmony_cistatic void rtl_w0w1_eri(struct rtl8169_private *tp, int addr, u32 p, u32 m)
10938c2ecf20Sopenharmony_ci{
10948c2ecf20Sopenharmony_ci	u32 val = rtl_eri_read(tp, addr);
10958c2ecf20Sopenharmony_ci
10968c2ecf20Sopenharmony_ci	rtl_eri_write(tp, addr, ERIAR_MASK_1111, (val & ~m) | p);
10978c2ecf20Sopenharmony_ci}
10988c2ecf20Sopenharmony_ci
10998c2ecf20Sopenharmony_cistatic void rtl_eri_set_bits(struct rtl8169_private *tp, int addr, u32 p)
11008c2ecf20Sopenharmony_ci{
11018c2ecf20Sopenharmony_ci	rtl_w0w1_eri(tp, addr, p, 0);
11028c2ecf20Sopenharmony_ci}
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_cistatic void rtl_eri_clear_bits(struct rtl8169_private *tp, int addr, u32 m)
11058c2ecf20Sopenharmony_ci{
11068c2ecf20Sopenharmony_ci	rtl_w0w1_eri(tp, addr, 0, m);
11078c2ecf20Sopenharmony_ci}
11088c2ecf20Sopenharmony_ci
11098c2ecf20Sopenharmony_cistatic u32 r8168dp_ocp_read(struct rtl8169_private *tp, u16 reg)
11108c2ecf20Sopenharmony_ci{
11118c2ecf20Sopenharmony_ci	RTL_W32(tp, OCPAR, 0x0fu << 12 | (reg & 0x0fff));
11128c2ecf20Sopenharmony_ci	return rtl_loop_wait_high(tp, &rtl_ocpar_cond, 100, 20) ?
11138c2ecf20Sopenharmony_ci		RTL_R32(tp, OCPDR) : ~0;
11148c2ecf20Sopenharmony_ci}
11158c2ecf20Sopenharmony_ci
11168c2ecf20Sopenharmony_cistatic u32 r8168ep_ocp_read(struct rtl8169_private *tp, u16 reg)
11178c2ecf20Sopenharmony_ci{
11188c2ecf20Sopenharmony_ci	return _rtl_eri_read(tp, reg, ERIAR_OOB);
11198c2ecf20Sopenharmony_ci}
11208c2ecf20Sopenharmony_ci
11218c2ecf20Sopenharmony_cistatic void r8168dp_ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg,
11228c2ecf20Sopenharmony_ci			      u32 data)
11238c2ecf20Sopenharmony_ci{
11248c2ecf20Sopenharmony_ci	RTL_W32(tp, OCPDR, data);
11258c2ecf20Sopenharmony_ci	RTL_W32(tp, OCPAR, OCPAR_FLAG | ((u32)mask & 0x0f) << 12 | (reg & 0x0fff));
11268c2ecf20Sopenharmony_ci	rtl_loop_wait_low(tp, &rtl_ocpar_cond, 100, 20);
11278c2ecf20Sopenharmony_ci}
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_cistatic void r8168ep_ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg,
11308c2ecf20Sopenharmony_ci			      u32 data)
11318c2ecf20Sopenharmony_ci{
11328c2ecf20Sopenharmony_ci	_rtl_eri_write(tp, reg, ((u32)mask & 0x0f) << ERIAR_MASK_SHIFT,
11338c2ecf20Sopenharmony_ci		       data, ERIAR_OOB);
11348c2ecf20Sopenharmony_ci}
11358c2ecf20Sopenharmony_ci
11368c2ecf20Sopenharmony_cistatic void r8168dp_oob_notify(struct rtl8169_private *tp, u8 cmd)
11378c2ecf20Sopenharmony_ci{
11388c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xe8, ERIAR_MASK_0001, cmd);
11398c2ecf20Sopenharmony_ci
11408c2ecf20Sopenharmony_ci	r8168dp_ocp_write(tp, 0x1, 0x30, 0x00000001);
11418c2ecf20Sopenharmony_ci}
11428c2ecf20Sopenharmony_ci
11438c2ecf20Sopenharmony_ci#define OOB_CMD_RESET		0x00
11448c2ecf20Sopenharmony_ci#define OOB_CMD_DRIVER_START	0x05
11458c2ecf20Sopenharmony_ci#define OOB_CMD_DRIVER_STOP	0x06
11468c2ecf20Sopenharmony_ci
11478c2ecf20Sopenharmony_cistatic u16 rtl8168_get_ocp_reg(struct rtl8169_private *tp)
11488c2ecf20Sopenharmony_ci{
11498c2ecf20Sopenharmony_ci	return (tp->mac_version == RTL_GIGA_MAC_VER_31) ? 0xb8 : 0x10;
11508c2ecf20Sopenharmony_ci}
11518c2ecf20Sopenharmony_ci
11528c2ecf20Sopenharmony_ciDECLARE_RTL_COND(rtl_dp_ocp_read_cond)
11538c2ecf20Sopenharmony_ci{
11548c2ecf20Sopenharmony_ci	u16 reg;
11558c2ecf20Sopenharmony_ci
11568c2ecf20Sopenharmony_ci	reg = rtl8168_get_ocp_reg(tp);
11578c2ecf20Sopenharmony_ci
11588c2ecf20Sopenharmony_ci	return r8168dp_ocp_read(tp, reg) & 0x00000800;
11598c2ecf20Sopenharmony_ci}
11608c2ecf20Sopenharmony_ci
11618c2ecf20Sopenharmony_ciDECLARE_RTL_COND(rtl_ep_ocp_read_cond)
11628c2ecf20Sopenharmony_ci{
11638c2ecf20Sopenharmony_ci	return r8168ep_ocp_read(tp, 0x124) & 0x00000001;
11648c2ecf20Sopenharmony_ci}
11658c2ecf20Sopenharmony_ci
11668c2ecf20Sopenharmony_ciDECLARE_RTL_COND(rtl_ocp_tx_cond)
11678c2ecf20Sopenharmony_ci{
11688c2ecf20Sopenharmony_ci	return RTL_R8(tp, IBISR0) & 0x20;
11698c2ecf20Sopenharmony_ci}
11708c2ecf20Sopenharmony_ci
11718c2ecf20Sopenharmony_cistatic void rtl8168ep_stop_cmac(struct rtl8169_private *tp)
11728c2ecf20Sopenharmony_ci{
11738c2ecf20Sopenharmony_ci	RTL_W8(tp, IBCR2, RTL_R8(tp, IBCR2) & ~0x01);
11748c2ecf20Sopenharmony_ci	rtl_loop_wait_high(tp, &rtl_ocp_tx_cond, 50000, 2000);
11758c2ecf20Sopenharmony_ci	RTL_W8(tp, IBISR0, RTL_R8(tp, IBISR0) | 0x20);
11768c2ecf20Sopenharmony_ci	RTL_W8(tp, IBCR0, RTL_R8(tp, IBCR0) & ~0x01);
11778c2ecf20Sopenharmony_ci}
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_cistatic void rtl8168dp_driver_start(struct rtl8169_private *tp)
11808c2ecf20Sopenharmony_ci{
11818c2ecf20Sopenharmony_ci	r8168dp_oob_notify(tp, OOB_CMD_DRIVER_START);
11828c2ecf20Sopenharmony_ci	rtl_loop_wait_high(tp, &rtl_dp_ocp_read_cond, 10000, 10);
11838c2ecf20Sopenharmony_ci}
11848c2ecf20Sopenharmony_ci
11858c2ecf20Sopenharmony_cistatic void rtl8168ep_driver_start(struct rtl8169_private *tp)
11868c2ecf20Sopenharmony_ci{
11878c2ecf20Sopenharmony_ci	r8168ep_ocp_write(tp, 0x01, 0x180, OOB_CMD_DRIVER_START);
11888c2ecf20Sopenharmony_ci	r8168ep_ocp_write(tp, 0x01, 0x30, r8168ep_ocp_read(tp, 0x30) | 0x01);
11898c2ecf20Sopenharmony_ci	rtl_loop_wait_high(tp, &rtl_ep_ocp_read_cond, 10000, 10);
11908c2ecf20Sopenharmony_ci}
11918c2ecf20Sopenharmony_ci
11928c2ecf20Sopenharmony_cistatic void rtl8168_driver_start(struct rtl8169_private *tp)
11938c2ecf20Sopenharmony_ci{
11948c2ecf20Sopenharmony_ci	switch (tp->mac_version) {
11958c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_27:
11968c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_28:
11978c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_31:
11988c2ecf20Sopenharmony_ci		rtl8168dp_driver_start(tp);
11998c2ecf20Sopenharmony_ci		break;
12008c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_49 ... RTL_GIGA_MAC_VER_52:
12018c2ecf20Sopenharmony_ci		rtl8168ep_driver_start(tp);
12028c2ecf20Sopenharmony_ci		break;
12038c2ecf20Sopenharmony_ci	default:
12048c2ecf20Sopenharmony_ci		BUG();
12058c2ecf20Sopenharmony_ci		break;
12068c2ecf20Sopenharmony_ci	}
12078c2ecf20Sopenharmony_ci}
12088c2ecf20Sopenharmony_ci
12098c2ecf20Sopenharmony_cistatic void rtl8168dp_driver_stop(struct rtl8169_private *tp)
12108c2ecf20Sopenharmony_ci{
12118c2ecf20Sopenharmony_ci	r8168dp_oob_notify(tp, OOB_CMD_DRIVER_STOP);
12128c2ecf20Sopenharmony_ci	rtl_loop_wait_low(tp, &rtl_dp_ocp_read_cond, 10000, 10);
12138c2ecf20Sopenharmony_ci}
12148c2ecf20Sopenharmony_ci
12158c2ecf20Sopenharmony_cistatic void rtl8168ep_driver_stop(struct rtl8169_private *tp)
12168c2ecf20Sopenharmony_ci{
12178c2ecf20Sopenharmony_ci	rtl8168ep_stop_cmac(tp);
12188c2ecf20Sopenharmony_ci	r8168ep_ocp_write(tp, 0x01, 0x180, OOB_CMD_DRIVER_STOP);
12198c2ecf20Sopenharmony_ci	r8168ep_ocp_write(tp, 0x01, 0x30, r8168ep_ocp_read(tp, 0x30) | 0x01);
12208c2ecf20Sopenharmony_ci	rtl_loop_wait_low(tp, &rtl_ep_ocp_read_cond, 10000, 10);
12218c2ecf20Sopenharmony_ci}
12228c2ecf20Sopenharmony_ci
12238c2ecf20Sopenharmony_cistatic void rtl8168_driver_stop(struct rtl8169_private *tp)
12248c2ecf20Sopenharmony_ci{
12258c2ecf20Sopenharmony_ci	switch (tp->mac_version) {
12268c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_27:
12278c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_28:
12288c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_31:
12298c2ecf20Sopenharmony_ci		rtl8168dp_driver_stop(tp);
12308c2ecf20Sopenharmony_ci		break;
12318c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_49 ... RTL_GIGA_MAC_VER_52:
12328c2ecf20Sopenharmony_ci		rtl8168ep_driver_stop(tp);
12338c2ecf20Sopenharmony_ci		break;
12348c2ecf20Sopenharmony_ci	default:
12358c2ecf20Sopenharmony_ci		BUG();
12368c2ecf20Sopenharmony_ci		break;
12378c2ecf20Sopenharmony_ci	}
12388c2ecf20Sopenharmony_ci}
12398c2ecf20Sopenharmony_ci
12408c2ecf20Sopenharmony_cistatic bool r8168dp_check_dash(struct rtl8169_private *tp)
12418c2ecf20Sopenharmony_ci{
12428c2ecf20Sopenharmony_ci	u16 reg = rtl8168_get_ocp_reg(tp);
12438c2ecf20Sopenharmony_ci
12448c2ecf20Sopenharmony_ci	return !!(r8168dp_ocp_read(tp, reg) & 0x00008000);
12458c2ecf20Sopenharmony_ci}
12468c2ecf20Sopenharmony_ci
12478c2ecf20Sopenharmony_cistatic bool r8168ep_check_dash(struct rtl8169_private *tp)
12488c2ecf20Sopenharmony_ci{
12498c2ecf20Sopenharmony_ci	return r8168ep_ocp_read(tp, 0x128) & 0x00000001;
12508c2ecf20Sopenharmony_ci}
12518c2ecf20Sopenharmony_ci
12528c2ecf20Sopenharmony_cistatic bool r8168_check_dash(struct rtl8169_private *tp)
12538c2ecf20Sopenharmony_ci{
12548c2ecf20Sopenharmony_ci	switch (tp->mac_version) {
12558c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_27:
12568c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_28:
12578c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_31:
12588c2ecf20Sopenharmony_ci		return r8168dp_check_dash(tp);
12598c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_49 ... RTL_GIGA_MAC_VER_52:
12608c2ecf20Sopenharmony_ci		return r8168ep_check_dash(tp);
12618c2ecf20Sopenharmony_ci	default:
12628c2ecf20Sopenharmony_ci		return false;
12638c2ecf20Sopenharmony_ci	}
12648c2ecf20Sopenharmony_ci}
12658c2ecf20Sopenharmony_ci
12668c2ecf20Sopenharmony_cistatic void rtl_reset_packet_filter(struct rtl8169_private *tp)
12678c2ecf20Sopenharmony_ci{
12688c2ecf20Sopenharmony_ci	rtl_eri_clear_bits(tp, 0xdc, BIT(0));
12698c2ecf20Sopenharmony_ci	rtl_eri_set_bits(tp, 0xdc, BIT(0));
12708c2ecf20Sopenharmony_ci}
12718c2ecf20Sopenharmony_ci
12728c2ecf20Sopenharmony_ciDECLARE_RTL_COND(rtl_efusear_cond)
12738c2ecf20Sopenharmony_ci{
12748c2ecf20Sopenharmony_ci	return RTL_R32(tp, EFUSEAR) & EFUSEAR_FLAG;
12758c2ecf20Sopenharmony_ci}
12768c2ecf20Sopenharmony_ci
12778c2ecf20Sopenharmony_ciu8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr)
12788c2ecf20Sopenharmony_ci{
12798c2ecf20Sopenharmony_ci	RTL_W32(tp, EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT);
12808c2ecf20Sopenharmony_ci
12818c2ecf20Sopenharmony_ci	return rtl_loop_wait_high(tp, &rtl_efusear_cond, 100, 300) ?
12828c2ecf20Sopenharmony_ci		RTL_R32(tp, EFUSEAR) & EFUSEAR_DATA_MASK : ~0;
12838c2ecf20Sopenharmony_ci}
12848c2ecf20Sopenharmony_ci
12858c2ecf20Sopenharmony_cistatic u32 rtl_get_events(struct rtl8169_private *tp)
12868c2ecf20Sopenharmony_ci{
12878c2ecf20Sopenharmony_ci	if (rtl_is_8125(tp))
12888c2ecf20Sopenharmony_ci		return RTL_R32(tp, IntrStatus_8125);
12898c2ecf20Sopenharmony_ci	else
12908c2ecf20Sopenharmony_ci		return RTL_R16(tp, IntrStatus);
12918c2ecf20Sopenharmony_ci}
12928c2ecf20Sopenharmony_ci
12938c2ecf20Sopenharmony_cistatic void rtl_ack_events(struct rtl8169_private *tp, u32 bits)
12948c2ecf20Sopenharmony_ci{
12958c2ecf20Sopenharmony_ci	if (rtl_is_8125(tp))
12968c2ecf20Sopenharmony_ci		RTL_W32(tp, IntrStatus_8125, bits);
12978c2ecf20Sopenharmony_ci	else
12988c2ecf20Sopenharmony_ci		RTL_W16(tp, IntrStatus, bits);
12998c2ecf20Sopenharmony_ci}
13008c2ecf20Sopenharmony_ci
13018c2ecf20Sopenharmony_cistatic void rtl_irq_disable(struct rtl8169_private *tp)
13028c2ecf20Sopenharmony_ci{
13038c2ecf20Sopenharmony_ci	if (rtl_is_8125(tp))
13048c2ecf20Sopenharmony_ci		RTL_W32(tp, IntrMask_8125, 0);
13058c2ecf20Sopenharmony_ci	else
13068c2ecf20Sopenharmony_ci		RTL_W16(tp, IntrMask, 0);
13078c2ecf20Sopenharmony_ci}
13088c2ecf20Sopenharmony_ci
13098c2ecf20Sopenharmony_cistatic void rtl_irq_enable(struct rtl8169_private *tp)
13108c2ecf20Sopenharmony_ci{
13118c2ecf20Sopenharmony_ci	if (rtl_is_8125(tp))
13128c2ecf20Sopenharmony_ci		RTL_W32(tp, IntrMask_8125, tp->irq_mask);
13138c2ecf20Sopenharmony_ci	else
13148c2ecf20Sopenharmony_ci		RTL_W16(tp, IntrMask, tp->irq_mask);
13158c2ecf20Sopenharmony_ci}
13168c2ecf20Sopenharmony_ci
13178c2ecf20Sopenharmony_cistatic void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp)
13188c2ecf20Sopenharmony_ci{
13198c2ecf20Sopenharmony_ci	rtl_irq_disable(tp);
13208c2ecf20Sopenharmony_ci	rtl_ack_events(tp, 0xffffffff);
13218c2ecf20Sopenharmony_ci	rtl_pci_commit(tp);
13228c2ecf20Sopenharmony_ci}
13238c2ecf20Sopenharmony_ci
13248c2ecf20Sopenharmony_cistatic void rtl_link_chg_patch(struct rtl8169_private *tp)
13258c2ecf20Sopenharmony_ci{
13268c2ecf20Sopenharmony_ci	struct phy_device *phydev = tp->phydev;
13278c2ecf20Sopenharmony_ci
13288c2ecf20Sopenharmony_ci	if (tp->mac_version == RTL_GIGA_MAC_VER_34 ||
13298c2ecf20Sopenharmony_ci	    tp->mac_version == RTL_GIGA_MAC_VER_38) {
13308c2ecf20Sopenharmony_ci		if (phydev->speed == SPEED_1000) {
13318c2ecf20Sopenharmony_ci			rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011);
13328c2ecf20Sopenharmony_ci			rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005);
13338c2ecf20Sopenharmony_ci		} else if (phydev->speed == SPEED_100) {
13348c2ecf20Sopenharmony_ci			rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f);
13358c2ecf20Sopenharmony_ci			rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005);
13368c2ecf20Sopenharmony_ci		} else {
13378c2ecf20Sopenharmony_ci			rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f);
13388c2ecf20Sopenharmony_ci			rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f);
13398c2ecf20Sopenharmony_ci		}
13408c2ecf20Sopenharmony_ci		rtl_reset_packet_filter(tp);
13418c2ecf20Sopenharmony_ci	} else if (tp->mac_version == RTL_GIGA_MAC_VER_35 ||
13428c2ecf20Sopenharmony_ci		   tp->mac_version == RTL_GIGA_MAC_VER_36) {
13438c2ecf20Sopenharmony_ci		if (phydev->speed == SPEED_1000) {
13448c2ecf20Sopenharmony_ci			rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011);
13458c2ecf20Sopenharmony_ci			rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005);
13468c2ecf20Sopenharmony_ci		} else {
13478c2ecf20Sopenharmony_ci			rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f);
13488c2ecf20Sopenharmony_ci			rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f);
13498c2ecf20Sopenharmony_ci		}
13508c2ecf20Sopenharmony_ci	} else if (tp->mac_version == RTL_GIGA_MAC_VER_37) {
13518c2ecf20Sopenharmony_ci		if (phydev->speed == SPEED_10) {
13528c2ecf20Sopenharmony_ci			rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x4d02);
13538c2ecf20Sopenharmony_ci			rtl_eri_write(tp, 0x1dc, ERIAR_MASK_0011, 0x0060a);
13548c2ecf20Sopenharmony_ci		} else {
13558c2ecf20Sopenharmony_ci			rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000);
13568c2ecf20Sopenharmony_ci		}
13578c2ecf20Sopenharmony_ci	}
13588c2ecf20Sopenharmony_ci}
13598c2ecf20Sopenharmony_ci
13608c2ecf20Sopenharmony_ci#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)
13618c2ecf20Sopenharmony_ci
13628c2ecf20Sopenharmony_cistatic void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
13638c2ecf20Sopenharmony_ci{
13648c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = netdev_priv(dev);
13658c2ecf20Sopenharmony_ci
13668c2ecf20Sopenharmony_ci	wol->supported = WAKE_ANY;
13678c2ecf20Sopenharmony_ci	wol->wolopts = tp->saved_wolopts;
13688c2ecf20Sopenharmony_ci}
13698c2ecf20Sopenharmony_ci
13708c2ecf20Sopenharmony_cistatic void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
13718c2ecf20Sopenharmony_ci{
13728c2ecf20Sopenharmony_ci	static const struct {
13738c2ecf20Sopenharmony_ci		u32 opt;
13748c2ecf20Sopenharmony_ci		u16 reg;
13758c2ecf20Sopenharmony_ci		u8  mask;
13768c2ecf20Sopenharmony_ci	} cfg[] = {
13778c2ecf20Sopenharmony_ci		{ WAKE_PHY,   Config3, LinkUp },
13788c2ecf20Sopenharmony_ci		{ WAKE_UCAST, Config5, UWF },
13798c2ecf20Sopenharmony_ci		{ WAKE_BCAST, Config5, BWF },
13808c2ecf20Sopenharmony_ci		{ WAKE_MCAST, Config5, MWF },
13818c2ecf20Sopenharmony_ci		{ WAKE_ANY,   Config5, LanWake },
13828c2ecf20Sopenharmony_ci		{ WAKE_MAGIC, Config3, MagicPacket }
13838c2ecf20Sopenharmony_ci	};
13848c2ecf20Sopenharmony_ci	unsigned int i, tmp = ARRAY_SIZE(cfg);
13858c2ecf20Sopenharmony_ci	u8 options;
13868c2ecf20Sopenharmony_ci
13878c2ecf20Sopenharmony_ci	rtl_unlock_config_regs(tp);
13888c2ecf20Sopenharmony_ci
13898c2ecf20Sopenharmony_ci	if (rtl_is_8168evl_up(tp)) {
13908c2ecf20Sopenharmony_ci		tmp--;
13918c2ecf20Sopenharmony_ci		if (wolopts & WAKE_MAGIC)
13928c2ecf20Sopenharmony_ci			rtl_eri_set_bits(tp, 0x0dc, MagicPacket_v2);
13938c2ecf20Sopenharmony_ci		else
13948c2ecf20Sopenharmony_ci			rtl_eri_clear_bits(tp, 0x0dc, MagicPacket_v2);
13958c2ecf20Sopenharmony_ci	} else if (rtl_is_8125(tp)) {
13968c2ecf20Sopenharmony_ci		tmp--;
13978c2ecf20Sopenharmony_ci		if (wolopts & WAKE_MAGIC)
13988c2ecf20Sopenharmony_ci			r8168_mac_ocp_modify(tp, 0xc0b6, 0, BIT(0));
13998c2ecf20Sopenharmony_ci		else
14008c2ecf20Sopenharmony_ci			r8168_mac_ocp_modify(tp, 0xc0b6, BIT(0), 0);
14018c2ecf20Sopenharmony_ci	}
14028c2ecf20Sopenharmony_ci
14038c2ecf20Sopenharmony_ci	for (i = 0; i < tmp; i++) {
14048c2ecf20Sopenharmony_ci		options = RTL_R8(tp, cfg[i].reg) & ~cfg[i].mask;
14058c2ecf20Sopenharmony_ci		if (wolopts & cfg[i].opt)
14068c2ecf20Sopenharmony_ci			options |= cfg[i].mask;
14078c2ecf20Sopenharmony_ci		RTL_W8(tp, cfg[i].reg, options);
14088c2ecf20Sopenharmony_ci	}
14098c2ecf20Sopenharmony_ci
14108c2ecf20Sopenharmony_ci	switch (tp->mac_version) {
14118c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06:
14128c2ecf20Sopenharmony_ci		options = RTL_R8(tp, Config1) & ~PMEnable;
14138c2ecf20Sopenharmony_ci		if (wolopts)
14148c2ecf20Sopenharmony_ci			options |= PMEnable;
14158c2ecf20Sopenharmony_ci		RTL_W8(tp, Config1, options);
14168c2ecf20Sopenharmony_ci		break;
14178c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_34:
14188c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_37:
14198c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_63:
14208c2ecf20Sopenharmony_ci		options = RTL_R8(tp, Config2) & ~PME_SIGNAL;
14218c2ecf20Sopenharmony_ci		if (wolopts)
14228c2ecf20Sopenharmony_ci			options |= PME_SIGNAL;
14238c2ecf20Sopenharmony_ci		RTL_W8(tp, Config2, options);
14248c2ecf20Sopenharmony_ci		break;
14258c2ecf20Sopenharmony_ci	default:
14268c2ecf20Sopenharmony_ci		break;
14278c2ecf20Sopenharmony_ci	}
14288c2ecf20Sopenharmony_ci
14298c2ecf20Sopenharmony_ci	rtl_lock_config_regs(tp);
14308c2ecf20Sopenharmony_ci
14318c2ecf20Sopenharmony_ci	device_set_wakeup_enable(tp_to_dev(tp), wolopts);
14328c2ecf20Sopenharmony_ci	tp->dev->wol_enabled = wolopts ? 1 : 0;
14338c2ecf20Sopenharmony_ci}
14348c2ecf20Sopenharmony_ci
14358c2ecf20Sopenharmony_cistatic int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
14368c2ecf20Sopenharmony_ci{
14378c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = netdev_priv(dev);
14388c2ecf20Sopenharmony_ci
14398c2ecf20Sopenharmony_ci	if (wol->wolopts & ~WAKE_ANY)
14408c2ecf20Sopenharmony_ci		return -EINVAL;
14418c2ecf20Sopenharmony_ci
14428c2ecf20Sopenharmony_ci	tp->saved_wolopts = wol->wolopts;
14438c2ecf20Sopenharmony_ci	__rtl8169_set_wol(tp, tp->saved_wolopts);
14448c2ecf20Sopenharmony_ci
14458c2ecf20Sopenharmony_ci	return 0;
14468c2ecf20Sopenharmony_ci}
14478c2ecf20Sopenharmony_ci
14488c2ecf20Sopenharmony_cistatic void rtl8169_get_drvinfo(struct net_device *dev,
14498c2ecf20Sopenharmony_ci				struct ethtool_drvinfo *info)
14508c2ecf20Sopenharmony_ci{
14518c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = netdev_priv(dev);
14528c2ecf20Sopenharmony_ci	struct rtl_fw *rtl_fw = tp->rtl_fw;
14538c2ecf20Sopenharmony_ci
14548c2ecf20Sopenharmony_ci	strlcpy(info->driver, MODULENAME, sizeof(info->driver));
14558c2ecf20Sopenharmony_ci	strlcpy(info->bus_info, pci_name(tp->pci_dev), sizeof(info->bus_info));
14568c2ecf20Sopenharmony_ci	BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version));
14578c2ecf20Sopenharmony_ci	if (rtl_fw)
14588c2ecf20Sopenharmony_ci		strlcpy(info->fw_version, rtl_fw->version,
14598c2ecf20Sopenharmony_ci			sizeof(info->fw_version));
14608c2ecf20Sopenharmony_ci}
14618c2ecf20Sopenharmony_ci
14628c2ecf20Sopenharmony_cistatic int rtl8169_get_regs_len(struct net_device *dev)
14638c2ecf20Sopenharmony_ci{
14648c2ecf20Sopenharmony_ci	return R8169_REGS_SIZE;
14658c2ecf20Sopenharmony_ci}
14668c2ecf20Sopenharmony_ci
14678c2ecf20Sopenharmony_cistatic netdev_features_t rtl8169_fix_features(struct net_device *dev,
14688c2ecf20Sopenharmony_ci	netdev_features_t features)
14698c2ecf20Sopenharmony_ci{
14708c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = netdev_priv(dev);
14718c2ecf20Sopenharmony_ci
14728c2ecf20Sopenharmony_ci	if (dev->mtu > TD_MSS_MAX)
14738c2ecf20Sopenharmony_ci		features &= ~NETIF_F_ALL_TSO;
14748c2ecf20Sopenharmony_ci
14758c2ecf20Sopenharmony_ci	if (dev->mtu > ETH_DATA_LEN &&
14768c2ecf20Sopenharmony_ci	    tp->mac_version > RTL_GIGA_MAC_VER_06)
14778c2ecf20Sopenharmony_ci		features &= ~(NETIF_F_CSUM_MASK | NETIF_F_ALL_TSO);
14788c2ecf20Sopenharmony_ci
14798c2ecf20Sopenharmony_ci	return features;
14808c2ecf20Sopenharmony_ci}
14818c2ecf20Sopenharmony_ci
14828c2ecf20Sopenharmony_cistatic void rtl_set_rx_config_features(struct rtl8169_private *tp,
14838c2ecf20Sopenharmony_ci				       netdev_features_t features)
14848c2ecf20Sopenharmony_ci{
14858c2ecf20Sopenharmony_ci	u32 rx_config = RTL_R32(tp, RxConfig);
14868c2ecf20Sopenharmony_ci
14878c2ecf20Sopenharmony_ci	if (features & NETIF_F_RXALL)
14888c2ecf20Sopenharmony_ci		rx_config |= RX_CONFIG_ACCEPT_ERR_MASK;
14898c2ecf20Sopenharmony_ci	else
14908c2ecf20Sopenharmony_ci		rx_config &= ~RX_CONFIG_ACCEPT_ERR_MASK;
14918c2ecf20Sopenharmony_ci
14928c2ecf20Sopenharmony_ci	if (rtl_is_8125(tp)) {
14938c2ecf20Sopenharmony_ci		if (features & NETIF_F_HW_VLAN_CTAG_RX)
14948c2ecf20Sopenharmony_ci			rx_config |= RX_VLAN_8125;
14958c2ecf20Sopenharmony_ci		else
14968c2ecf20Sopenharmony_ci			rx_config &= ~RX_VLAN_8125;
14978c2ecf20Sopenharmony_ci	}
14988c2ecf20Sopenharmony_ci
14998c2ecf20Sopenharmony_ci	RTL_W32(tp, RxConfig, rx_config);
15008c2ecf20Sopenharmony_ci}
15018c2ecf20Sopenharmony_ci
15028c2ecf20Sopenharmony_cistatic int rtl8169_set_features(struct net_device *dev,
15038c2ecf20Sopenharmony_ci				netdev_features_t features)
15048c2ecf20Sopenharmony_ci{
15058c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = netdev_priv(dev);
15068c2ecf20Sopenharmony_ci
15078c2ecf20Sopenharmony_ci	rtl_set_rx_config_features(tp, features);
15088c2ecf20Sopenharmony_ci
15098c2ecf20Sopenharmony_ci	if (features & NETIF_F_RXCSUM)
15108c2ecf20Sopenharmony_ci		tp->cp_cmd |= RxChkSum;
15118c2ecf20Sopenharmony_ci	else
15128c2ecf20Sopenharmony_ci		tp->cp_cmd &= ~RxChkSum;
15138c2ecf20Sopenharmony_ci
15148c2ecf20Sopenharmony_ci	if (!rtl_is_8125(tp)) {
15158c2ecf20Sopenharmony_ci		if (features & NETIF_F_HW_VLAN_CTAG_RX)
15168c2ecf20Sopenharmony_ci			tp->cp_cmd |= RxVlan;
15178c2ecf20Sopenharmony_ci		else
15188c2ecf20Sopenharmony_ci			tp->cp_cmd &= ~RxVlan;
15198c2ecf20Sopenharmony_ci	}
15208c2ecf20Sopenharmony_ci
15218c2ecf20Sopenharmony_ci	RTL_W16(tp, CPlusCmd, tp->cp_cmd);
15228c2ecf20Sopenharmony_ci	rtl_pci_commit(tp);
15238c2ecf20Sopenharmony_ci
15248c2ecf20Sopenharmony_ci	return 0;
15258c2ecf20Sopenharmony_ci}
15268c2ecf20Sopenharmony_ci
15278c2ecf20Sopenharmony_cistatic inline u32 rtl8169_tx_vlan_tag(struct sk_buff *skb)
15288c2ecf20Sopenharmony_ci{
15298c2ecf20Sopenharmony_ci	return (skb_vlan_tag_present(skb)) ?
15308c2ecf20Sopenharmony_ci		TxVlanTag | swab16(skb_vlan_tag_get(skb)) : 0x00;
15318c2ecf20Sopenharmony_ci}
15328c2ecf20Sopenharmony_ci
15338c2ecf20Sopenharmony_cistatic void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb)
15348c2ecf20Sopenharmony_ci{
15358c2ecf20Sopenharmony_ci	u32 opts2 = le32_to_cpu(desc->opts2);
15368c2ecf20Sopenharmony_ci
15378c2ecf20Sopenharmony_ci	if (opts2 & RxVlanTag)
15388c2ecf20Sopenharmony_ci		__vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), swab16(opts2 & 0xffff));
15398c2ecf20Sopenharmony_ci}
15408c2ecf20Sopenharmony_ci
15418c2ecf20Sopenharmony_cistatic void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs,
15428c2ecf20Sopenharmony_ci			     void *p)
15438c2ecf20Sopenharmony_ci{
15448c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = netdev_priv(dev);
15458c2ecf20Sopenharmony_ci	u32 __iomem *data = tp->mmio_addr;
15468c2ecf20Sopenharmony_ci	u32 *dw = p;
15478c2ecf20Sopenharmony_ci	int i;
15488c2ecf20Sopenharmony_ci
15498c2ecf20Sopenharmony_ci	for (i = 0; i < R8169_REGS_SIZE; i += 4)
15508c2ecf20Sopenharmony_ci		memcpy_fromio(dw++, data++, 4);
15518c2ecf20Sopenharmony_ci}
15528c2ecf20Sopenharmony_ci
15538c2ecf20Sopenharmony_cistatic const char rtl8169_gstrings[][ETH_GSTRING_LEN] = {
15548c2ecf20Sopenharmony_ci	"tx_packets",
15558c2ecf20Sopenharmony_ci	"rx_packets",
15568c2ecf20Sopenharmony_ci	"tx_errors",
15578c2ecf20Sopenharmony_ci	"rx_errors",
15588c2ecf20Sopenharmony_ci	"rx_missed",
15598c2ecf20Sopenharmony_ci	"align_errors",
15608c2ecf20Sopenharmony_ci	"tx_single_collisions",
15618c2ecf20Sopenharmony_ci	"tx_multi_collisions",
15628c2ecf20Sopenharmony_ci	"unicast",
15638c2ecf20Sopenharmony_ci	"broadcast",
15648c2ecf20Sopenharmony_ci	"multicast",
15658c2ecf20Sopenharmony_ci	"tx_aborted",
15668c2ecf20Sopenharmony_ci	"tx_underrun",
15678c2ecf20Sopenharmony_ci};
15688c2ecf20Sopenharmony_ci
15698c2ecf20Sopenharmony_cistatic int rtl8169_get_sset_count(struct net_device *dev, int sset)
15708c2ecf20Sopenharmony_ci{
15718c2ecf20Sopenharmony_ci	switch (sset) {
15728c2ecf20Sopenharmony_ci	case ETH_SS_STATS:
15738c2ecf20Sopenharmony_ci		return ARRAY_SIZE(rtl8169_gstrings);
15748c2ecf20Sopenharmony_ci	default:
15758c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
15768c2ecf20Sopenharmony_ci	}
15778c2ecf20Sopenharmony_ci}
15788c2ecf20Sopenharmony_ci
15798c2ecf20Sopenharmony_ciDECLARE_RTL_COND(rtl_counters_cond)
15808c2ecf20Sopenharmony_ci{
15818c2ecf20Sopenharmony_ci	return RTL_R32(tp, CounterAddrLow) & (CounterReset | CounterDump);
15828c2ecf20Sopenharmony_ci}
15838c2ecf20Sopenharmony_ci
15848c2ecf20Sopenharmony_cistatic void rtl8169_do_counters(struct rtl8169_private *tp, u32 counter_cmd)
15858c2ecf20Sopenharmony_ci{
15868c2ecf20Sopenharmony_ci	dma_addr_t paddr = tp->counters_phys_addr;
15878c2ecf20Sopenharmony_ci	u32 cmd;
15888c2ecf20Sopenharmony_ci
15898c2ecf20Sopenharmony_ci	RTL_W32(tp, CounterAddrHigh, (u64)paddr >> 32);
15908c2ecf20Sopenharmony_ci	rtl_pci_commit(tp);
15918c2ecf20Sopenharmony_ci	cmd = (u64)paddr & DMA_BIT_MASK(32);
15928c2ecf20Sopenharmony_ci	RTL_W32(tp, CounterAddrLow, cmd);
15938c2ecf20Sopenharmony_ci	RTL_W32(tp, CounterAddrLow, cmd | counter_cmd);
15948c2ecf20Sopenharmony_ci
15958c2ecf20Sopenharmony_ci	rtl_loop_wait_low(tp, &rtl_counters_cond, 10, 1000);
15968c2ecf20Sopenharmony_ci}
15978c2ecf20Sopenharmony_ci
15988c2ecf20Sopenharmony_cistatic void rtl8169_reset_counters(struct rtl8169_private *tp)
15998c2ecf20Sopenharmony_ci{
16008c2ecf20Sopenharmony_ci	/*
16018c2ecf20Sopenharmony_ci	 * Versions prior to RTL_GIGA_MAC_VER_19 don't support resetting the
16028c2ecf20Sopenharmony_ci	 * tally counters.
16038c2ecf20Sopenharmony_ci	 */
16048c2ecf20Sopenharmony_ci	if (tp->mac_version >= RTL_GIGA_MAC_VER_19)
16058c2ecf20Sopenharmony_ci		rtl8169_do_counters(tp, CounterReset);
16068c2ecf20Sopenharmony_ci}
16078c2ecf20Sopenharmony_ci
16088c2ecf20Sopenharmony_cistatic void rtl8169_update_counters(struct rtl8169_private *tp)
16098c2ecf20Sopenharmony_ci{
16108c2ecf20Sopenharmony_ci	u8 val = RTL_R8(tp, ChipCmd);
16118c2ecf20Sopenharmony_ci
16128c2ecf20Sopenharmony_ci	/*
16138c2ecf20Sopenharmony_ci	 * Some chips are unable to dump tally counters when the receiver
16148c2ecf20Sopenharmony_ci	 * is disabled. If 0xff chip may be in a PCI power-save state.
16158c2ecf20Sopenharmony_ci	 */
16168c2ecf20Sopenharmony_ci	if (val & CmdRxEnb && val != 0xff)
16178c2ecf20Sopenharmony_ci		rtl8169_do_counters(tp, CounterDump);
16188c2ecf20Sopenharmony_ci}
16198c2ecf20Sopenharmony_ci
16208c2ecf20Sopenharmony_cistatic void rtl8169_init_counter_offsets(struct rtl8169_private *tp)
16218c2ecf20Sopenharmony_ci{
16228c2ecf20Sopenharmony_ci	struct rtl8169_counters *counters = tp->counters;
16238c2ecf20Sopenharmony_ci
16248c2ecf20Sopenharmony_ci	/*
16258c2ecf20Sopenharmony_ci	 * rtl8169_init_counter_offsets is called from rtl_open.  On chip
16268c2ecf20Sopenharmony_ci	 * versions prior to RTL_GIGA_MAC_VER_19 the tally counters are only
16278c2ecf20Sopenharmony_ci	 * reset by a power cycle, while the counter values collected by the
16288c2ecf20Sopenharmony_ci	 * driver are reset at every driver unload/load cycle.
16298c2ecf20Sopenharmony_ci	 *
16308c2ecf20Sopenharmony_ci	 * To make sure the HW values returned by @get_stats64 match the SW
16318c2ecf20Sopenharmony_ci	 * values, we collect the initial values at first open(*) and use them
16328c2ecf20Sopenharmony_ci	 * as offsets to normalize the values returned by @get_stats64.
16338c2ecf20Sopenharmony_ci	 *
16348c2ecf20Sopenharmony_ci	 * (*) We can't call rtl8169_init_counter_offsets from rtl_init_one
16358c2ecf20Sopenharmony_ci	 * for the reason stated in rtl8169_update_counters; CmdRxEnb is only
16368c2ecf20Sopenharmony_ci	 * set at open time by rtl_hw_start.
16378c2ecf20Sopenharmony_ci	 */
16388c2ecf20Sopenharmony_ci
16398c2ecf20Sopenharmony_ci	if (tp->tc_offset.inited)
16408c2ecf20Sopenharmony_ci		return;
16418c2ecf20Sopenharmony_ci
16428c2ecf20Sopenharmony_ci	rtl8169_reset_counters(tp);
16438c2ecf20Sopenharmony_ci	rtl8169_update_counters(tp);
16448c2ecf20Sopenharmony_ci
16458c2ecf20Sopenharmony_ci	tp->tc_offset.tx_errors = counters->tx_errors;
16468c2ecf20Sopenharmony_ci	tp->tc_offset.tx_multi_collision = counters->tx_multi_collision;
16478c2ecf20Sopenharmony_ci	tp->tc_offset.tx_aborted = counters->tx_aborted;
16488c2ecf20Sopenharmony_ci	tp->tc_offset.rx_missed = counters->rx_missed;
16498c2ecf20Sopenharmony_ci	tp->tc_offset.inited = true;
16508c2ecf20Sopenharmony_ci}
16518c2ecf20Sopenharmony_ci
16528c2ecf20Sopenharmony_cistatic void rtl8169_get_ethtool_stats(struct net_device *dev,
16538c2ecf20Sopenharmony_ci				      struct ethtool_stats *stats, u64 *data)
16548c2ecf20Sopenharmony_ci{
16558c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = netdev_priv(dev);
16568c2ecf20Sopenharmony_ci	struct rtl8169_counters *counters;
16578c2ecf20Sopenharmony_ci
16588c2ecf20Sopenharmony_ci	counters = tp->counters;
16598c2ecf20Sopenharmony_ci	rtl8169_update_counters(tp);
16608c2ecf20Sopenharmony_ci
16618c2ecf20Sopenharmony_ci	data[0] = le64_to_cpu(counters->tx_packets);
16628c2ecf20Sopenharmony_ci	data[1] = le64_to_cpu(counters->rx_packets);
16638c2ecf20Sopenharmony_ci	data[2] = le64_to_cpu(counters->tx_errors);
16648c2ecf20Sopenharmony_ci	data[3] = le32_to_cpu(counters->rx_errors);
16658c2ecf20Sopenharmony_ci	data[4] = le16_to_cpu(counters->rx_missed);
16668c2ecf20Sopenharmony_ci	data[5] = le16_to_cpu(counters->align_errors);
16678c2ecf20Sopenharmony_ci	data[6] = le32_to_cpu(counters->tx_one_collision);
16688c2ecf20Sopenharmony_ci	data[7] = le32_to_cpu(counters->tx_multi_collision);
16698c2ecf20Sopenharmony_ci	data[8] = le64_to_cpu(counters->rx_unicast);
16708c2ecf20Sopenharmony_ci	data[9] = le64_to_cpu(counters->rx_broadcast);
16718c2ecf20Sopenharmony_ci	data[10] = le32_to_cpu(counters->rx_multicast);
16728c2ecf20Sopenharmony_ci	data[11] = le16_to_cpu(counters->tx_aborted);
16738c2ecf20Sopenharmony_ci	data[12] = le16_to_cpu(counters->tx_underun);
16748c2ecf20Sopenharmony_ci}
16758c2ecf20Sopenharmony_ci
16768c2ecf20Sopenharmony_cistatic void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data)
16778c2ecf20Sopenharmony_ci{
16788c2ecf20Sopenharmony_ci	switch(stringset) {
16798c2ecf20Sopenharmony_ci	case ETH_SS_STATS:
16808c2ecf20Sopenharmony_ci		memcpy(data, rtl8169_gstrings, sizeof(rtl8169_gstrings));
16818c2ecf20Sopenharmony_ci		break;
16828c2ecf20Sopenharmony_ci	}
16838c2ecf20Sopenharmony_ci}
16848c2ecf20Sopenharmony_ci
16858c2ecf20Sopenharmony_ci/*
16868c2ecf20Sopenharmony_ci * Interrupt coalescing
16878c2ecf20Sopenharmony_ci *
16888c2ecf20Sopenharmony_ci * > 1 - the availability of the IntrMitigate (0xe2) register through the
16898c2ecf20Sopenharmony_ci * >     8169, 8168 and 810x line of chipsets
16908c2ecf20Sopenharmony_ci *
16918c2ecf20Sopenharmony_ci * 8169, 8168, and 8136(810x) serial chipsets support it.
16928c2ecf20Sopenharmony_ci *
16938c2ecf20Sopenharmony_ci * > 2 - the Tx timer unit at gigabit speed
16948c2ecf20Sopenharmony_ci *
16958c2ecf20Sopenharmony_ci * The unit of the timer depends on both the speed and the setting of CPlusCmd
16968c2ecf20Sopenharmony_ci * (0xe0) bit 1 and bit 0.
16978c2ecf20Sopenharmony_ci *
16988c2ecf20Sopenharmony_ci * For 8169
16998c2ecf20Sopenharmony_ci * bit[1:0] \ speed        1000M           100M            10M
17008c2ecf20Sopenharmony_ci * 0 0                     320ns           2.56us          40.96us
17018c2ecf20Sopenharmony_ci * 0 1                     2.56us          20.48us         327.7us
17028c2ecf20Sopenharmony_ci * 1 0                     5.12us          40.96us         655.4us
17038c2ecf20Sopenharmony_ci * 1 1                     10.24us         81.92us         1.31ms
17048c2ecf20Sopenharmony_ci *
17058c2ecf20Sopenharmony_ci * For the other
17068c2ecf20Sopenharmony_ci * bit[1:0] \ speed        1000M           100M            10M
17078c2ecf20Sopenharmony_ci * 0 0                     5us             2.56us          40.96us
17088c2ecf20Sopenharmony_ci * 0 1                     40us            20.48us         327.7us
17098c2ecf20Sopenharmony_ci * 1 0                     80us            40.96us         655.4us
17108c2ecf20Sopenharmony_ci * 1 1                     160us           81.92us         1.31ms
17118c2ecf20Sopenharmony_ci */
17128c2ecf20Sopenharmony_ci
17138c2ecf20Sopenharmony_ci/* rx/tx scale factors for all CPlusCmd[0:1] cases */
17148c2ecf20Sopenharmony_cistruct rtl_coalesce_info {
17158c2ecf20Sopenharmony_ci	u32 speed;
17168c2ecf20Sopenharmony_ci	u32 scale_nsecs[4];
17178c2ecf20Sopenharmony_ci};
17188c2ecf20Sopenharmony_ci
17198c2ecf20Sopenharmony_ci/* produce array with base delay *1, *8, *8*2, *8*2*2 */
17208c2ecf20Sopenharmony_ci#define COALESCE_DELAY(d) { (d), 8 * (d), 16 * (d), 32 * (d) }
17218c2ecf20Sopenharmony_ci
17228c2ecf20Sopenharmony_cistatic const struct rtl_coalesce_info rtl_coalesce_info_8169[] = {
17238c2ecf20Sopenharmony_ci	{ SPEED_1000,	COALESCE_DELAY(320) },
17248c2ecf20Sopenharmony_ci	{ SPEED_100,	COALESCE_DELAY(2560) },
17258c2ecf20Sopenharmony_ci	{ SPEED_10,	COALESCE_DELAY(40960) },
17268c2ecf20Sopenharmony_ci	{ 0 },
17278c2ecf20Sopenharmony_ci};
17288c2ecf20Sopenharmony_ci
17298c2ecf20Sopenharmony_cistatic const struct rtl_coalesce_info rtl_coalesce_info_8168_8136[] = {
17308c2ecf20Sopenharmony_ci	{ SPEED_1000,	COALESCE_DELAY(5000) },
17318c2ecf20Sopenharmony_ci	{ SPEED_100,	COALESCE_DELAY(2560) },
17328c2ecf20Sopenharmony_ci	{ SPEED_10,	COALESCE_DELAY(40960) },
17338c2ecf20Sopenharmony_ci	{ 0 },
17348c2ecf20Sopenharmony_ci};
17358c2ecf20Sopenharmony_ci#undef COALESCE_DELAY
17368c2ecf20Sopenharmony_ci
17378c2ecf20Sopenharmony_ci/* get rx/tx scale vector corresponding to current speed */
17388c2ecf20Sopenharmony_cistatic const struct rtl_coalesce_info *
17398c2ecf20Sopenharmony_cirtl_coalesce_info(struct rtl8169_private *tp)
17408c2ecf20Sopenharmony_ci{
17418c2ecf20Sopenharmony_ci	const struct rtl_coalesce_info *ci;
17428c2ecf20Sopenharmony_ci
17438c2ecf20Sopenharmony_ci	if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
17448c2ecf20Sopenharmony_ci		ci = rtl_coalesce_info_8169;
17458c2ecf20Sopenharmony_ci	else
17468c2ecf20Sopenharmony_ci		ci = rtl_coalesce_info_8168_8136;
17478c2ecf20Sopenharmony_ci
17488c2ecf20Sopenharmony_ci	/* if speed is unknown assume highest one */
17498c2ecf20Sopenharmony_ci	if (tp->phydev->speed == SPEED_UNKNOWN)
17508c2ecf20Sopenharmony_ci		return ci;
17518c2ecf20Sopenharmony_ci
17528c2ecf20Sopenharmony_ci	for (; ci->speed; ci++) {
17538c2ecf20Sopenharmony_ci		if (tp->phydev->speed == ci->speed)
17548c2ecf20Sopenharmony_ci			return ci;
17558c2ecf20Sopenharmony_ci	}
17568c2ecf20Sopenharmony_ci
17578c2ecf20Sopenharmony_ci	return ERR_PTR(-ELNRNG);
17588c2ecf20Sopenharmony_ci}
17598c2ecf20Sopenharmony_ci
17608c2ecf20Sopenharmony_cistatic int rtl_get_coalesce(struct net_device *dev, struct ethtool_coalesce *ec)
17618c2ecf20Sopenharmony_ci{
17628c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = netdev_priv(dev);
17638c2ecf20Sopenharmony_ci	const struct rtl_coalesce_info *ci;
17648c2ecf20Sopenharmony_ci	u32 scale, c_us, c_fr;
17658c2ecf20Sopenharmony_ci	u16 intrmit;
17668c2ecf20Sopenharmony_ci
17678c2ecf20Sopenharmony_ci	if (rtl_is_8125(tp))
17688c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
17698c2ecf20Sopenharmony_ci
17708c2ecf20Sopenharmony_ci	memset(ec, 0, sizeof(*ec));
17718c2ecf20Sopenharmony_ci
17728c2ecf20Sopenharmony_ci	/* get rx/tx scale corresponding to current speed and CPlusCmd[0:1] */
17738c2ecf20Sopenharmony_ci	ci = rtl_coalesce_info(tp);
17748c2ecf20Sopenharmony_ci	if (IS_ERR(ci))
17758c2ecf20Sopenharmony_ci		return PTR_ERR(ci);
17768c2ecf20Sopenharmony_ci
17778c2ecf20Sopenharmony_ci	scale = ci->scale_nsecs[tp->cp_cmd & INTT_MASK];
17788c2ecf20Sopenharmony_ci
17798c2ecf20Sopenharmony_ci	intrmit = RTL_R16(tp, IntrMitigate);
17808c2ecf20Sopenharmony_ci
17818c2ecf20Sopenharmony_ci	c_us = FIELD_GET(RTL_COALESCE_TX_USECS, intrmit);
17828c2ecf20Sopenharmony_ci	ec->tx_coalesce_usecs = DIV_ROUND_UP(c_us * scale, 1000);
17838c2ecf20Sopenharmony_ci
17848c2ecf20Sopenharmony_ci	c_fr = FIELD_GET(RTL_COALESCE_TX_FRAMES, intrmit);
17858c2ecf20Sopenharmony_ci	/* ethtool_coalesce states usecs and max_frames must not both be 0 */
17868c2ecf20Sopenharmony_ci	ec->tx_max_coalesced_frames = (c_us || c_fr) ? c_fr * 4 : 1;
17878c2ecf20Sopenharmony_ci
17888c2ecf20Sopenharmony_ci	c_us = FIELD_GET(RTL_COALESCE_RX_USECS, intrmit);
17898c2ecf20Sopenharmony_ci	ec->rx_coalesce_usecs = DIV_ROUND_UP(c_us * scale, 1000);
17908c2ecf20Sopenharmony_ci
17918c2ecf20Sopenharmony_ci	c_fr = FIELD_GET(RTL_COALESCE_RX_FRAMES, intrmit);
17928c2ecf20Sopenharmony_ci	ec->rx_max_coalesced_frames = (c_us || c_fr) ? c_fr * 4 : 1;
17938c2ecf20Sopenharmony_ci
17948c2ecf20Sopenharmony_ci	return 0;
17958c2ecf20Sopenharmony_ci}
17968c2ecf20Sopenharmony_ci
17978c2ecf20Sopenharmony_ci/* choose appropriate scale factor and CPlusCmd[0:1] for (speed, usec) */
17988c2ecf20Sopenharmony_cistatic int rtl_coalesce_choose_scale(struct rtl8169_private *tp, u32 usec,
17998c2ecf20Sopenharmony_ci				     u16 *cp01)
18008c2ecf20Sopenharmony_ci{
18018c2ecf20Sopenharmony_ci	const struct rtl_coalesce_info *ci;
18028c2ecf20Sopenharmony_ci	u16 i;
18038c2ecf20Sopenharmony_ci
18048c2ecf20Sopenharmony_ci	ci = rtl_coalesce_info(tp);
18058c2ecf20Sopenharmony_ci	if (IS_ERR(ci))
18068c2ecf20Sopenharmony_ci		return PTR_ERR(ci);
18078c2ecf20Sopenharmony_ci
18088c2ecf20Sopenharmony_ci	for (i = 0; i < 4; i++) {
18098c2ecf20Sopenharmony_ci		if (usec <= ci->scale_nsecs[i] * RTL_COALESCE_T_MAX / 1000U) {
18108c2ecf20Sopenharmony_ci			*cp01 = i;
18118c2ecf20Sopenharmony_ci			return ci->scale_nsecs[i];
18128c2ecf20Sopenharmony_ci		}
18138c2ecf20Sopenharmony_ci	}
18148c2ecf20Sopenharmony_ci
18158c2ecf20Sopenharmony_ci	return -ERANGE;
18168c2ecf20Sopenharmony_ci}
18178c2ecf20Sopenharmony_ci
18188c2ecf20Sopenharmony_cistatic int rtl_set_coalesce(struct net_device *dev, struct ethtool_coalesce *ec)
18198c2ecf20Sopenharmony_ci{
18208c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = netdev_priv(dev);
18218c2ecf20Sopenharmony_ci	u32 tx_fr = ec->tx_max_coalesced_frames;
18228c2ecf20Sopenharmony_ci	u32 rx_fr = ec->rx_max_coalesced_frames;
18238c2ecf20Sopenharmony_ci	u32 coal_usec_max, units;
18248c2ecf20Sopenharmony_ci	u16 w = 0, cp01 = 0;
18258c2ecf20Sopenharmony_ci	int scale;
18268c2ecf20Sopenharmony_ci
18278c2ecf20Sopenharmony_ci	if (rtl_is_8125(tp))
18288c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
18298c2ecf20Sopenharmony_ci
18308c2ecf20Sopenharmony_ci	if (rx_fr > RTL_COALESCE_FRAME_MAX || tx_fr > RTL_COALESCE_FRAME_MAX)
18318c2ecf20Sopenharmony_ci		return -ERANGE;
18328c2ecf20Sopenharmony_ci
18338c2ecf20Sopenharmony_ci	coal_usec_max = max(ec->rx_coalesce_usecs, ec->tx_coalesce_usecs);
18348c2ecf20Sopenharmony_ci	scale = rtl_coalesce_choose_scale(tp, coal_usec_max, &cp01);
18358c2ecf20Sopenharmony_ci	if (scale < 0)
18368c2ecf20Sopenharmony_ci		return scale;
18378c2ecf20Sopenharmony_ci
18388c2ecf20Sopenharmony_ci	/* Accept max_frames=1 we returned in rtl_get_coalesce. Accept it
18398c2ecf20Sopenharmony_ci	 * not only when usecs=0 because of e.g. the following scenario:
18408c2ecf20Sopenharmony_ci	 *
18418c2ecf20Sopenharmony_ci	 * - both rx_usecs=0 & rx_frames=0 in hardware (no delay on RX)
18428c2ecf20Sopenharmony_ci	 * - rtl_get_coalesce returns rx_usecs=0, rx_frames=1
18438c2ecf20Sopenharmony_ci	 * - then user does `ethtool -C eth0 rx-usecs 100`
18448c2ecf20Sopenharmony_ci	 *
18458c2ecf20Sopenharmony_ci	 * Since ethtool sends to kernel whole ethtool_coalesce settings,
18468c2ecf20Sopenharmony_ci	 * if we want to ignore rx_frames then it has to be set to 0.
18478c2ecf20Sopenharmony_ci	 */
18488c2ecf20Sopenharmony_ci	if (rx_fr == 1)
18498c2ecf20Sopenharmony_ci		rx_fr = 0;
18508c2ecf20Sopenharmony_ci	if (tx_fr == 1)
18518c2ecf20Sopenharmony_ci		tx_fr = 0;
18528c2ecf20Sopenharmony_ci
18538c2ecf20Sopenharmony_ci	/* HW requires time limit to be set if frame limit is set */
18548c2ecf20Sopenharmony_ci	if ((tx_fr && !ec->tx_coalesce_usecs) ||
18558c2ecf20Sopenharmony_ci	    (rx_fr && !ec->rx_coalesce_usecs))
18568c2ecf20Sopenharmony_ci		return -EINVAL;
18578c2ecf20Sopenharmony_ci
18588c2ecf20Sopenharmony_ci	w |= FIELD_PREP(RTL_COALESCE_TX_FRAMES, DIV_ROUND_UP(tx_fr, 4));
18598c2ecf20Sopenharmony_ci	w |= FIELD_PREP(RTL_COALESCE_RX_FRAMES, DIV_ROUND_UP(rx_fr, 4));
18608c2ecf20Sopenharmony_ci
18618c2ecf20Sopenharmony_ci	units = DIV_ROUND_UP(ec->tx_coalesce_usecs * 1000U, scale);
18628c2ecf20Sopenharmony_ci	w |= FIELD_PREP(RTL_COALESCE_TX_USECS, units);
18638c2ecf20Sopenharmony_ci	units = DIV_ROUND_UP(ec->rx_coalesce_usecs * 1000U, scale);
18648c2ecf20Sopenharmony_ci	w |= FIELD_PREP(RTL_COALESCE_RX_USECS, units);
18658c2ecf20Sopenharmony_ci
18668c2ecf20Sopenharmony_ci	RTL_W16(tp, IntrMitigate, w);
18678c2ecf20Sopenharmony_ci
18688c2ecf20Sopenharmony_ci	/* Meaning of PktCntrDisable bit changed from RTL8168e-vl */
18698c2ecf20Sopenharmony_ci	if (rtl_is_8168evl_up(tp)) {
18708c2ecf20Sopenharmony_ci		if (!rx_fr && !tx_fr)
18718c2ecf20Sopenharmony_ci			/* disable packet counter */
18728c2ecf20Sopenharmony_ci			tp->cp_cmd |= PktCntrDisable;
18738c2ecf20Sopenharmony_ci		else
18748c2ecf20Sopenharmony_ci			tp->cp_cmd &= ~PktCntrDisable;
18758c2ecf20Sopenharmony_ci	}
18768c2ecf20Sopenharmony_ci
18778c2ecf20Sopenharmony_ci	tp->cp_cmd = (tp->cp_cmd & ~INTT_MASK) | cp01;
18788c2ecf20Sopenharmony_ci	RTL_W16(tp, CPlusCmd, tp->cp_cmd);
18798c2ecf20Sopenharmony_ci	rtl_pci_commit(tp);
18808c2ecf20Sopenharmony_ci
18818c2ecf20Sopenharmony_ci	return 0;
18828c2ecf20Sopenharmony_ci}
18838c2ecf20Sopenharmony_ci
18848c2ecf20Sopenharmony_cistatic int rtl8169_get_eee(struct net_device *dev, struct ethtool_eee *data)
18858c2ecf20Sopenharmony_ci{
18868c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = netdev_priv(dev);
18878c2ecf20Sopenharmony_ci
18888c2ecf20Sopenharmony_ci	if (!rtl_supports_eee(tp))
18898c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
18908c2ecf20Sopenharmony_ci
18918c2ecf20Sopenharmony_ci	return phy_ethtool_get_eee(tp->phydev, data);
18928c2ecf20Sopenharmony_ci}
18938c2ecf20Sopenharmony_ci
18948c2ecf20Sopenharmony_cistatic int rtl8169_set_eee(struct net_device *dev, struct ethtool_eee *data)
18958c2ecf20Sopenharmony_ci{
18968c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = netdev_priv(dev);
18978c2ecf20Sopenharmony_ci	int ret;
18988c2ecf20Sopenharmony_ci
18998c2ecf20Sopenharmony_ci	if (!rtl_supports_eee(tp))
19008c2ecf20Sopenharmony_ci		return -EOPNOTSUPP;
19018c2ecf20Sopenharmony_ci
19028c2ecf20Sopenharmony_ci	ret = phy_ethtool_set_eee(tp->phydev, data);
19038c2ecf20Sopenharmony_ci
19048c2ecf20Sopenharmony_ci	if (!ret)
19058c2ecf20Sopenharmony_ci		tp->eee_adv = phy_read_mmd(dev->phydev, MDIO_MMD_AN,
19068c2ecf20Sopenharmony_ci					   MDIO_AN_EEE_ADV);
19078c2ecf20Sopenharmony_ci	return ret;
19088c2ecf20Sopenharmony_ci}
19098c2ecf20Sopenharmony_ci
19108c2ecf20Sopenharmony_cistatic const struct ethtool_ops rtl8169_ethtool_ops = {
19118c2ecf20Sopenharmony_ci	.supported_coalesce_params = ETHTOOL_COALESCE_USECS |
19128c2ecf20Sopenharmony_ci				     ETHTOOL_COALESCE_MAX_FRAMES,
19138c2ecf20Sopenharmony_ci	.get_drvinfo		= rtl8169_get_drvinfo,
19148c2ecf20Sopenharmony_ci	.get_regs_len		= rtl8169_get_regs_len,
19158c2ecf20Sopenharmony_ci	.get_link		= ethtool_op_get_link,
19168c2ecf20Sopenharmony_ci	.get_coalesce		= rtl_get_coalesce,
19178c2ecf20Sopenharmony_ci	.set_coalesce		= rtl_set_coalesce,
19188c2ecf20Sopenharmony_ci	.get_regs		= rtl8169_get_regs,
19198c2ecf20Sopenharmony_ci	.get_wol		= rtl8169_get_wol,
19208c2ecf20Sopenharmony_ci	.set_wol		= rtl8169_set_wol,
19218c2ecf20Sopenharmony_ci	.get_strings		= rtl8169_get_strings,
19228c2ecf20Sopenharmony_ci	.get_sset_count		= rtl8169_get_sset_count,
19238c2ecf20Sopenharmony_ci	.get_ethtool_stats	= rtl8169_get_ethtool_stats,
19248c2ecf20Sopenharmony_ci	.get_ts_info		= ethtool_op_get_ts_info,
19258c2ecf20Sopenharmony_ci	.nway_reset		= phy_ethtool_nway_reset,
19268c2ecf20Sopenharmony_ci	.get_eee		= rtl8169_get_eee,
19278c2ecf20Sopenharmony_ci	.set_eee		= rtl8169_set_eee,
19288c2ecf20Sopenharmony_ci	.get_link_ksettings	= phy_ethtool_get_link_ksettings,
19298c2ecf20Sopenharmony_ci	.set_link_ksettings	= phy_ethtool_set_link_ksettings,
19308c2ecf20Sopenharmony_ci};
19318c2ecf20Sopenharmony_ci
19328c2ecf20Sopenharmony_cistatic void rtl_enable_eee(struct rtl8169_private *tp)
19338c2ecf20Sopenharmony_ci{
19348c2ecf20Sopenharmony_ci	struct phy_device *phydev = tp->phydev;
19358c2ecf20Sopenharmony_ci	int adv;
19368c2ecf20Sopenharmony_ci
19378c2ecf20Sopenharmony_ci	/* respect EEE advertisement the user may have set */
19388c2ecf20Sopenharmony_ci	if (tp->eee_adv >= 0)
19398c2ecf20Sopenharmony_ci		adv = tp->eee_adv;
19408c2ecf20Sopenharmony_ci	else
19418c2ecf20Sopenharmony_ci		adv = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
19428c2ecf20Sopenharmony_ci
19438c2ecf20Sopenharmony_ci	if (adv >= 0)
19448c2ecf20Sopenharmony_ci		phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, adv);
19458c2ecf20Sopenharmony_ci}
19468c2ecf20Sopenharmony_ci
19478c2ecf20Sopenharmony_cistatic enum mac_version rtl8169_get_mac_version(u16 xid, bool gmii)
19488c2ecf20Sopenharmony_ci{
19498c2ecf20Sopenharmony_ci	/*
19508c2ecf20Sopenharmony_ci	 * The driver currently handles the 8168Bf and the 8168Be identically
19518c2ecf20Sopenharmony_ci	 * but they can be identified more specifically through the test below
19528c2ecf20Sopenharmony_ci	 * if needed:
19538c2ecf20Sopenharmony_ci	 *
19548c2ecf20Sopenharmony_ci	 * (RTL_R32(tp, TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be
19558c2ecf20Sopenharmony_ci	 *
19568c2ecf20Sopenharmony_ci	 * Same thing for the 8101Eb and the 8101Ec:
19578c2ecf20Sopenharmony_ci	 *
19588c2ecf20Sopenharmony_ci	 * (RTL_R32(tp, TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec
19598c2ecf20Sopenharmony_ci	 */
19608c2ecf20Sopenharmony_ci	static const struct rtl_mac_info {
19618c2ecf20Sopenharmony_ci		u16 mask;
19628c2ecf20Sopenharmony_ci		u16 val;
19638c2ecf20Sopenharmony_ci		enum mac_version ver;
19648c2ecf20Sopenharmony_ci	} mac_info[] = {
19658c2ecf20Sopenharmony_ci		/* 8125B family. */
19668c2ecf20Sopenharmony_ci		{ 0x7cf, 0x641,	RTL_GIGA_MAC_VER_63 },
19678c2ecf20Sopenharmony_ci
19688c2ecf20Sopenharmony_ci		/* 8125A family. */
19698c2ecf20Sopenharmony_ci		{ 0x7cf, 0x608,	RTL_GIGA_MAC_VER_60 },
19708c2ecf20Sopenharmony_ci		{ 0x7c8, 0x608,	RTL_GIGA_MAC_VER_61 },
19718c2ecf20Sopenharmony_ci
19728c2ecf20Sopenharmony_ci		/* RTL8117 */
19738c2ecf20Sopenharmony_ci		{ 0x7cf, 0x54a,	RTL_GIGA_MAC_VER_52 },
19748c2ecf20Sopenharmony_ci
19758c2ecf20Sopenharmony_ci		/* 8168EP family. */
19768c2ecf20Sopenharmony_ci		{ 0x7cf, 0x502,	RTL_GIGA_MAC_VER_51 },
19778c2ecf20Sopenharmony_ci		{ 0x7cf, 0x501,	RTL_GIGA_MAC_VER_50 },
19788c2ecf20Sopenharmony_ci		{ 0x7cf, 0x500,	RTL_GIGA_MAC_VER_49 },
19798c2ecf20Sopenharmony_ci
19808c2ecf20Sopenharmony_ci		/* 8168H family. */
19818c2ecf20Sopenharmony_ci		{ 0x7cf, 0x541,	RTL_GIGA_MAC_VER_46 },
19828c2ecf20Sopenharmony_ci		{ 0x7cf, 0x540,	RTL_GIGA_MAC_VER_45 },
19838c2ecf20Sopenharmony_ci
19848c2ecf20Sopenharmony_ci		/* 8168G family. */
19858c2ecf20Sopenharmony_ci		{ 0x7cf, 0x5c8,	RTL_GIGA_MAC_VER_44 },
19868c2ecf20Sopenharmony_ci		{ 0x7cf, 0x509,	RTL_GIGA_MAC_VER_42 },
19878c2ecf20Sopenharmony_ci		{ 0x7cf, 0x4c1,	RTL_GIGA_MAC_VER_41 },
19888c2ecf20Sopenharmony_ci		{ 0x7cf, 0x4c0,	RTL_GIGA_MAC_VER_40 },
19898c2ecf20Sopenharmony_ci
19908c2ecf20Sopenharmony_ci		/* 8168F family. */
19918c2ecf20Sopenharmony_ci		{ 0x7c8, 0x488,	RTL_GIGA_MAC_VER_38 },
19928c2ecf20Sopenharmony_ci		{ 0x7cf, 0x481,	RTL_GIGA_MAC_VER_36 },
19938c2ecf20Sopenharmony_ci		{ 0x7cf, 0x480,	RTL_GIGA_MAC_VER_35 },
19948c2ecf20Sopenharmony_ci
19958c2ecf20Sopenharmony_ci		/* 8168E family. */
19968c2ecf20Sopenharmony_ci		{ 0x7c8, 0x2c8,	RTL_GIGA_MAC_VER_34 },
19978c2ecf20Sopenharmony_ci		{ 0x7cf, 0x2c1,	RTL_GIGA_MAC_VER_32 },
19988c2ecf20Sopenharmony_ci		{ 0x7c8, 0x2c0,	RTL_GIGA_MAC_VER_33 },
19998c2ecf20Sopenharmony_ci
20008c2ecf20Sopenharmony_ci		/* 8168D family. */
20018c2ecf20Sopenharmony_ci		{ 0x7cf, 0x281,	RTL_GIGA_MAC_VER_25 },
20028c2ecf20Sopenharmony_ci		{ 0x7c8, 0x280,	RTL_GIGA_MAC_VER_26 },
20038c2ecf20Sopenharmony_ci
20048c2ecf20Sopenharmony_ci		/* 8168DP family. */
20058c2ecf20Sopenharmony_ci		{ 0x7cf, 0x288,	RTL_GIGA_MAC_VER_27 },
20068c2ecf20Sopenharmony_ci		{ 0x7cf, 0x28a,	RTL_GIGA_MAC_VER_28 },
20078c2ecf20Sopenharmony_ci		{ 0x7cf, 0x28b,	RTL_GIGA_MAC_VER_31 },
20088c2ecf20Sopenharmony_ci
20098c2ecf20Sopenharmony_ci		/* 8168C family. */
20108c2ecf20Sopenharmony_ci		{ 0x7cf, 0x3c9,	RTL_GIGA_MAC_VER_23 },
20118c2ecf20Sopenharmony_ci		{ 0x7cf, 0x3c8,	RTL_GIGA_MAC_VER_18 },
20128c2ecf20Sopenharmony_ci		{ 0x7c8, 0x3c8,	RTL_GIGA_MAC_VER_24 },
20138c2ecf20Sopenharmony_ci		{ 0x7cf, 0x3c0,	RTL_GIGA_MAC_VER_19 },
20148c2ecf20Sopenharmony_ci		{ 0x7cf, 0x3c2,	RTL_GIGA_MAC_VER_20 },
20158c2ecf20Sopenharmony_ci		{ 0x7cf, 0x3c3,	RTL_GIGA_MAC_VER_21 },
20168c2ecf20Sopenharmony_ci		{ 0x7c8, 0x3c0,	RTL_GIGA_MAC_VER_22 },
20178c2ecf20Sopenharmony_ci
20188c2ecf20Sopenharmony_ci		/* 8168B family. */
20198c2ecf20Sopenharmony_ci		{ 0x7cf, 0x380,	RTL_GIGA_MAC_VER_12 },
20208c2ecf20Sopenharmony_ci		{ 0x7c8, 0x380,	RTL_GIGA_MAC_VER_17 },
20218c2ecf20Sopenharmony_ci		{ 0x7c8, 0x300,	RTL_GIGA_MAC_VER_11 },
20228c2ecf20Sopenharmony_ci
20238c2ecf20Sopenharmony_ci		/* 8101 family. */
20248c2ecf20Sopenharmony_ci		{ 0x7c8, 0x448,	RTL_GIGA_MAC_VER_39 },
20258c2ecf20Sopenharmony_ci		{ 0x7c8, 0x440,	RTL_GIGA_MAC_VER_37 },
20268c2ecf20Sopenharmony_ci		{ 0x7cf, 0x409,	RTL_GIGA_MAC_VER_29 },
20278c2ecf20Sopenharmony_ci		{ 0x7c8, 0x408,	RTL_GIGA_MAC_VER_30 },
20288c2ecf20Sopenharmony_ci		{ 0x7cf, 0x349,	RTL_GIGA_MAC_VER_08 },
20298c2ecf20Sopenharmony_ci		{ 0x7cf, 0x249,	RTL_GIGA_MAC_VER_08 },
20308c2ecf20Sopenharmony_ci		{ 0x7cf, 0x348,	RTL_GIGA_MAC_VER_07 },
20318c2ecf20Sopenharmony_ci		{ 0x7cf, 0x248,	RTL_GIGA_MAC_VER_07 },
20328c2ecf20Sopenharmony_ci		{ 0x7cf, 0x340,	RTL_GIGA_MAC_VER_13 },
20338c2ecf20Sopenharmony_ci		{ 0x7cf, 0x240,	RTL_GIGA_MAC_VER_14 },
20348c2ecf20Sopenharmony_ci		{ 0x7cf, 0x343,	RTL_GIGA_MAC_VER_10 },
20358c2ecf20Sopenharmony_ci		{ 0x7cf, 0x342,	RTL_GIGA_MAC_VER_16 },
20368c2ecf20Sopenharmony_ci		{ 0x7c8, 0x348,	RTL_GIGA_MAC_VER_09 },
20378c2ecf20Sopenharmony_ci		{ 0x7c8, 0x248,	RTL_GIGA_MAC_VER_09 },
20388c2ecf20Sopenharmony_ci		{ 0x7c8, 0x340,	RTL_GIGA_MAC_VER_16 },
20398c2ecf20Sopenharmony_ci		/* FIXME: where did these entries come from ? -- FR */
20408c2ecf20Sopenharmony_ci		{ 0xfc8, 0x388,	RTL_GIGA_MAC_VER_13 },
20418c2ecf20Sopenharmony_ci		{ 0xfc8, 0x308,	RTL_GIGA_MAC_VER_13 },
20428c2ecf20Sopenharmony_ci
20438c2ecf20Sopenharmony_ci		/* 8110 family. */
20448c2ecf20Sopenharmony_ci		{ 0xfc8, 0x980,	RTL_GIGA_MAC_VER_06 },
20458c2ecf20Sopenharmony_ci		{ 0xfc8, 0x180,	RTL_GIGA_MAC_VER_05 },
20468c2ecf20Sopenharmony_ci		{ 0xfc8, 0x100,	RTL_GIGA_MAC_VER_04 },
20478c2ecf20Sopenharmony_ci		{ 0xfc8, 0x040,	RTL_GIGA_MAC_VER_03 },
20488c2ecf20Sopenharmony_ci		{ 0xfc8, 0x008,	RTL_GIGA_MAC_VER_02 },
20498c2ecf20Sopenharmony_ci
20508c2ecf20Sopenharmony_ci		/* Catch-all */
20518c2ecf20Sopenharmony_ci		{ 0x000, 0x000,	RTL_GIGA_MAC_NONE   }
20528c2ecf20Sopenharmony_ci	};
20538c2ecf20Sopenharmony_ci	const struct rtl_mac_info *p = mac_info;
20548c2ecf20Sopenharmony_ci	enum mac_version ver;
20558c2ecf20Sopenharmony_ci
20568c2ecf20Sopenharmony_ci	while ((xid & p->mask) != p->val)
20578c2ecf20Sopenharmony_ci		p++;
20588c2ecf20Sopenharmony_ci	ver = p->ver;
20598c2ecf20Sopenharmony_ci
20608c2ecf20Sopenharmony_ci	if (ver != RTL_GIGA_MAC_NONE && !gmii) {
20618c2ecf20Sopenharmony_ci		if (ver == RTL_GIGA_MAC_VER_42)
20628c2ecf20Sopenharmony_ci			ver = RTL_GIGA_MAC_VER_43;
20638c2ecf20Sopenharmony_ci		else if (ver == RTL_GIGA_MAC_VER_45)
20648c2ecf20Sopenharmony_ci			ver = RTL_GIGA_MAC_VER_47;
20658c2ecf20Sopenharmony_ci		else if (ver == RTL_GIGA_MAC_VER_46)
20668c2ecf20Sopenharmony_ci			ver = RTL_GIGA_MAC_VER_48;
20678c2ecf20Sopenharmony_ci	}
20688c2ecf20Sopenharmony_ci
20698c2ecf20Sopenharmony_ci	return ver;
20708c2ecf20Sopenharmony_ci}
20718c2ecf20Sopenharmony_ci
20728c2ecf20Sopenharmony_cistatic void rtl_release_firmware(struct rtl8169_private *tp)
20738c2ecf20Sopenharmony_ci{
20748c2ecf20Sopenharmony_ci	if (tp->rtl_fw) {
20758c2ecf20Sopenharmony_ci		rtl_fw_release_firmware(tp->rtl_fw);
20768c2ecf20Sopenharmony_ci		kfree(tp->rtl_fw);
20778c2ecf20Sopenharmony_ci		tp->rtl_fw = NULL;
20788c2ecf20Sopenharmony_ci	}
20798c2ecf20Sopenharmony_ci}
20808c2ecf20Sopenharmony_ci
20818c2ecf20Sopenharmony_civoid r8169_apply_firmware(struct rtl8169_private *tp)
20828c2ecf20Sopenharmony_ci{
20838c2ecf20Sopenharmony_ci	int val;
20848c2ecf20Sopenharmony_ci
20858c2ecf20Sopenharmony_ci	/* TODO: release firmware if rtl_fw_write_firmware signals failure. */
20868c2ecf20Sopenharmony_ci	if (tp->rtl_fw) {
20878c2ecf20Sopenharmony_ci		rtl_fw_write_firmware(tp, tp->rtl_fw);
20888c2ecf20Sopenharmony_ci		/* At least one firmware doesn't reset tp->ocp_base. */
20898c2ecf20Sopenharmony_ci		tp->ocp_base = OCP_STD_PHY_BASE;
20908c2ecf20Sopenharmony_ci
20918c2ecf20Sopenharmony_ci		/* PHY soft reset may still be in progress */
20928c2ecf20Sopenharmony_ci		phy_read_poll_timeout(tp->phydev, MII_BMCR, val,
20938c2ecf20Sopenharmony_ci				      !(val & BMCR_RESET),
20948c2ecf20Sopenharmony_ci				      50000, 600000, true);
20958c2ecf20Sopenharmony_ci	}
20968c2ecf20Sopenharmony_ci}
20978c2ecf20Sopenharmony_ci
20988c2ecf20Sopenharmony_cistatic void rtl8168_config_eee_mac(struct rtl8169_private *tp)
20998c2ecf20Sopenharmony_ci{
21008c2ecf20Sopenharmony_ci	/* Adjust EEE LED frequency */
21018c2ecf20Sopenharmony_ci	if (tp->mac_version != RTL_GIGA_MAC_VER_38)
21028c2ecf20Sopenharmony_ci		RTL_W8(tp, EEE_LED, RTL_R8(tp, EEE_LED) & ~0x07);
21038c2ecf20Sopenharmony_ci
21048c2ecf20Sopenharmony_ci	rtl_eri_set_bits(tp, 0x1b0, 0x0003);
21058c2ecf20Sopenharmony_ci}
21068c2ecf20Sopenharmony_ci
21078c2ecf20Sopenharmony_cistatic void rtl8125a_config_eee_mac(struct rtl8169_private *tp)
21088c2ecf20Sopenharmony_ci{
21098c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xe040, 0, BIT(1) | BIT(0));
21108c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xeb62, 0, BIT(2) | BIT(1));
21118c2ecf20Sopenharmony_ci}
21128c2ecf20Sopenharmony_ci
21138c2ecf20Sopenharmony_cistatic void rtl8125_set_eee_txidle_timer(struct rtl8169_private *tp)
21148c2ecf20Sopenharmony_ci{
21158c2ecf20Sopenharmony_ci	RTL_W16(tp, EEE_TXIDLE_TIMER_8125, tp->dev->mtu + ETH_HLEN + 0x20);
21168c2ecf20Sopenharmony_ci}
21178c2ecf20Sopenharmony_ci
21188c2ecf20Sopenharmony_cistatic void rtl8125b_config_eee_mac(struct rtl8169_private *tp)
21198c2ecf20Sopenharmony_ci{
21208c2ecf20Sopenharmony_ci	rtl8125_set_eee_txidle_timer(tp);
21218c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xe040, 0, BIT(1) | BIT(0));
21228c2ecf20Sopenharmony_ci}
21238c2ecf20Sopenharmony_ci
21248c2ecf20Sopenharmony_cistatic void rtl_rar_exgmac_set(struct rtl8169_private *tp, u8 *addr)
21258c2ecf20Sopenharmony_ci{
21268c2ecf20Sopenharmony_ci	const u16 w[] = {
21278c2ecf20Sopenharmony_ci		addr[0] | (addr[1] << 8),
21288c2ecf20Sopenharmony_ci		addr[2] | (addr[3] << 8),
21298c2ecf20Sopenharmony_ci		addr[4] | (addr[5] << 8)
21308c2ecf20Sopenharmony_ci	};
21318c2ecf20Sopenharmony_ci
21328c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xe0, ERIAR_MASK_1111, w[0] | (w[1] << 16));
21338c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xe4, ERIAR_MASK_1111, w[2]);
21348c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xf0, ERIAR_MASK_1111, w[0] << 16);
21358c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xf4, ERIAR_MASK_1111, w[1] | (w[2] << 16));
21368c2ecf20Sopenharmony_ci}
21378c2ecf20Sopenharmony_ci
21388c2ecf20Sopenharmony_ciu16 rtl8168h_2_get_adc_bias_ioffset(struct rtl8169_private *tp)
21398c2ecf20Sopenharmony_ci{
21408c2ecf20Sopenharmony_ci	u16 data1, data2, ioffset;
21418c2ecf20Sopenharmony_ci
21428c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xdd02, 0x807d);
21438c2ecf20Sopenharmony_ci	data1 = r8168_mac_ocp_read(tp, 0xdd02);
21448c2ecf20Sopenharmony_ci	data2 = r8168_mac_ocp_read(tp, 0xdd00);
21458c2ecf20Sopenharmony_ci
21468c2ecf20Sopenharmony_ci	ioffset = (data2 >> 1) & 0x7ff8;
21478c2ecf20Sopenharmony_ci	ioffset |= data2 & 0x0007;
21488c2ecf20Sopenharmony_ci	if (data1 & BIT(7))
21498c2ecf20Sopenharmony_ci		ioffset |= BIT(15);
21508c2ecf20Sopenharmony_ci
21518c2ecf20Sopenharmony_ci	return ioffset;
21528c2ecf20Sopenharmony_ci}
21538c2ecf20Sopenharmony_ci
21548c2ecf20Sopenharmony_cistatic void rtl_schedule_task(struct rtl8169_private *tp, enum rtl_flag flag)
21558c2ecf20Sopenharmony_ci{
21568c2ecf20Sopenharmony_ci	set_bit(flag, tp->wk.flags);
21578c2ecf20Sopenharmony_ci	schedule_work(&tp->wk.work);
21588c2ecf20Sopenharmony_ci}
21598c2ecf20Sopenharmony_ci
21608c2ecf20Sopenharmony_cistatic void rtl8169_init_phy(struct rtl8169_private *tp)
21618c2ecf20Sopenharmony_ci{
21628c2ecf20Sopenharmony_ci	r8169_hw_phy_config(tp, tp->phydev, tp->mac_version);
21638c2ecf20Sopenharmony_ci
21648c2ecf20Sopenharmony_ci	if (tp->mac_version <= RTL_GIGA_MAC_VER_06) {
21658c2ecf20Sopenharmony_ci		pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40);
21668c2ecf20Sopenharmony_ci		pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08);
21678c2ecf20Sopenharmony_ci		/* set undocumented MAC Reg C+CR Offset 0x82h */
21688c2ecf20Sopenharmony_ci		RTL_W8(tp, 0x82, 0x01);
21698c2ecf20Sopenharmony_ci	}
21708c2ecf20Sopenharmony_ci
21718c2ecf20Sopenharmony_ci	if (tp->mac_version == RTL_GIGA_MAC_VER_05 &&
21728c2ecf20Sopenharmony_ci	    tp->pci_dev->subsystem_vendor == PCI_VENDOR_ID_GIGABYTE &&
21738c2ecf20Sopenharmony_ci	    tp->pci_dev->subsystem_device == 0xe000)
21748c2ecf20Sopenharmony_ci		phy_write_paged(tp->phydev, 0x0001, 0x10, 0xf01b);
21758c2ecf20Sopenharmony_ci
21768c2ecf20Sopenharmony_ci	/* We may have called phy_speed_down before */
21778c2ecf20Sopenharmony_ci	phy_speed_up(tp->phydev);
21788c2ecf20Sopenharmony_ci
21798c2ecf20Sopenharmony_ci	if (rtl_supports_eee(tp))
21808c2ecf20Sopenharmony_ci		rtl_enable_eee(tp);
21818c2ecf20Sopenharmony_ci
21828c2ecf20Sopenharmony_ci	genphy_soft_reset(tp->phydev);
21838c2ecf20Sopenharmony_ci}
21848c2ecf20Sopenharmony_ci
21858c2ecf20Sopenharmony_cistatic void rtl_rar_set(struct rtl8169_private *tp, u8 *addr)
21868c2ecf20Sopenharmony_ci{
21878c2ecf20Sopenharmony_ci	rtl_unlock_config_regs(tp);
21888c2ecf20Sopenharmony_ci
21898c2ecf20Sopenharmony_ci	RTL_W32(tp, MAC4, addr[4] | addr[5] << 8);
21908c2ecf20Sopenharmony_ci	rtl_pci_commit(tp);
21918c2ecf20Sopenharmony_ci
21928c2ecf20Sopenharmony_ci	RTL_W32(tp, MAC0, addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24);
21938c2ecf20Sopenharmony_ci	rtl_pci_commit(tp);
21948c2ecf20Sopenharmony_ci
21958c2ecf20Sopenharmony_ci	if (tp->mac_version == RTL_GIGA_MAC_VER_34)
21968c2ecf20Sopenharmony_ci		rtl_rar_exgmac_set(tp, addr);
21978c2ecf20Sopenharmony_ci
21988c2ecf20Sopenharmony_ci	rtl_lock_config_regs(tp);
21998c2ecf20Sopenharmony_ci}
22008c2ecf20Sopenharmony_ci
22018c2ecf20Sopenharmony_cistatic int rtl_set_mac_address(struct net_device *dev, void *p)
22028c2ecf20Sopenharmony_ci{
22038c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = netdev_priv(dev);
22048c2ecf20Sopenharmony_ci	int ret;
22058c2ecf20Sopenharmony_ci
22068c2ecf20Sopenharmony_ci	ret = eth_mac_addr(dev, p);
22078c2ecf20Sopenharmony_ci	if (ret)
22088c2ecf20Sopenharmony_ci		return ret;
22098c2ecf20Sopenharmony_ci
22108c2ecf20Sopenharmony_ci	rtl_rar_set(tp, dev->dev_addr);
22118c2ecf20Sopenharmony_ci
22128c2ecf20Sopenharmony_ci	return 0;
22138c2ecf20Sopenharmony_ci}
22148c2ecf20Sopenharmony_ci
22158c2ecf20Sopenharmony_cistatic void rtl_wol_suspend_quirk(struct rtl8169_private *tp)
22168c2ecf20Sopenharmony_ci{
22178c2ecf20Sopenharmony_ci	switch (tp->mac_version) {
22188c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_25:
22198c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_26:
22208c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_29:
22218c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_30:
22228c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_32:
22238c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_33:
22248c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_34:
22258c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_37 ... RTL_GIGA_MAC_VER_63:
22268c2ecf20Sopenharmony_ci		RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) |
22278c2ecf20Sopenharmony_ci			AcceptBroadcast | AcceptMulticast | AcceptMyPhys);
22288c2ecf20Sopenharmony_ci		break;
22298c2ecf20Sopenharmony_ci	default:
22308c2ecf20Sopenharmony_ci		break;
22318c2ecf20Sopenharmony_ci	}
22328c2ecf20Sopenharmony_ci}
22338c2ecf20Sopenharmony_ci
22348c2ecf20Sopenharmony_cistatic void rtl_pll_power_down(struct rtl8169_private *tp)
22358c2ecf20Sopenharmony_ci{
22368c2ecf20Sopenharmony_ci	if (r8168_check_dash(tp))
22378c2ecf20Sopenharmony_ci		return;
22388c2ecf20Sopenharmony_ci
22398c2ecf20Sopenharmony_ci	if (tp->mac_version == RTL_GIGA_MAC_VER_32 ||
22408c2ecf20Sopenharmony_ci	    tp->mac_version == RTL_GIGA_MAC_VER_33)
22418c2ecf20Sopenharmony_ci		rtl_ephy_write(tp, 0x19, 0xff64);
22428c2ecf20Sopenharmony_ci
22438c2ecf20Sopenharmony_ci	if (device_may_wakeup(tp_to_dev(tp))) {
22448c2ecf20Sopenharmony_ci		phy_speed_down(tp->phydev, false);
22458c2ecf20Sopenharmony_ci		rtl_wol_suspend_quirk(tp);
22468c2ecf20Sopenharmony_ci		return;
22478c2ecf20Sopenharmony_ci	}
22488c2ecf20Sopenharmony_ci
22498c2ecf20Sopenharmony_ci	switch (tp->mac_version) {
22508c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_25 ... RTL_GIGA_MAC_VER_26:
22518c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_29 ... RTL_GIGA_MAC_VER_30:
22528c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_32 ... RTL_GIGA_MAC_VER_33:
22538c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_37:
22548c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_39:
22558c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_43:
22568c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_44:
22578c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_45:
22588c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_46:
22598c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_47:
22608c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_48:
22618c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_50 ... RTL_GIGA_MAC_VER_63:
22628c2ecf20Sopenharmony_ci		RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) & ~0x80);
22638c2ecf20Sopenharmony_ci		break;
22648c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_40:
22658c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_41:
22668c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_49:
22678c2ecf20Sopenharmony_ci		rtl_eri_clear_bits(tp, 0x1a8, 0xfc000000);
22688c2ecf20Sopenharmony_ci		RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) & ~0x80);
22698c2ecf20Sopenharmony_ci		break;
22708c2ecf20Sopenharmony_ci	default:
22718c2ecf20Sopenharmony_ci		break;
22728c2ecf20Sopenharmony_ci	}
22738c2ecf20Sopenharmony_ci}
22748c2ecf20Sopenharmony_ci
22758c2ecf20Sopenharmony_cistatic void rtl_pll_power_up(struct rtl8169_private *tp)
22768c2ecf20Sopenharmony_ci{
22778c2ecf20Sopenharmony_ci	switch (tp->mac_version) {
22788c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_25 ... RTL_GIGA_MAC_VER_26:
22798c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_29 ... RTL_GIGA_MAC_VER_30:
22808c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_32 ... RTL_GIGA_MAC_VER_33:
22818c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_37:
22828c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_39:
22838c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_43:
22848c2ecf20Sopenharmony_ci		RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) | 0x80);
22858c2ecf20Sopenharmony_ci		break;
22868c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_44:
22878c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_45:
22888c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_46:
22898c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_47:
22908c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_48:
22918c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_50 ... RTL_GIGA_MAC_VER_63:
22928c2ecf20Sopenharmony_ci		RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) | 0xc0);
22938c2ecf20Sopenharmony_ci		break;
22948c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_40:
22958c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_41:
22968c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_49:
22978c2ecf20Sopenharmony_ci		RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) | 0xc0);
22988c2ecf20Sopenharmony_ci		rtl_eri_set_bits(tp, 0x1a8, 0xfc000000);
22998c2ecf20Sopenharmony_ci		break;
23008c2ecf20Sopenharmony_ci	default:
23018c2ecf20Sopenharmony_ci		break;
23028c2ecf20Sopenharmony_ci	}
23038c2ecf20Sopenharmony_ci
23048c2ecf20Sopenharmony_ci	phy_resume(tp->phydev);
23058c2ecf20Sopenharmony_ci}
23068c2ecf20Sopenharmony_ci
23078c2ecf20Sopenharmony_cistatic void rtl_init_rxcfg(struct rtl8169_private *tp)
23088c2ecf20Sopenharmony_ci{
23098c2ecf20Sopenharmony_ci	switch (tp->mac_version) {
23108c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06:
23118c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_10 ... RTL_GIGA_MAC_VER_17:
23128c2ecf20Sopenharmony_ci		RTL_W32(tp, RxConfig, RX_FIFO_THRESH | RX_DMA_BURST);
23138c2ecf20Sopenharmony_ci		break;
23148c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_18 ... RTL_GIGA_MAC_VER_24:
23158c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_36:
23168c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_38:
23178c2ecf20Sopenharmony_ci		RTL_W32(tp, RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST);
23188c2ecf20Sopenharmony_ci		break;
23198c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_52:
23208c2ecf20Sopenharmony_ci		RTL_W32(tp, RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST | RX_EARLY_OFF);
23218c2ecf20Sopenharmony_ci		break;
23228c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_61:
23238c2ecf20Sopenharmony_ci		RTL_W32(tp, RxConfig, RX_FETCH_DFLT_8125 | RX_DMA_BURST);
23248c2ecf20Sopenharmony_ci		break;
23258c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_63:
23268c2ecf20Sopenharmony_ci		RTL_W32(tp, RxConfig, RX_FETCH_DFLT_8125 | RX_DMA_BURST |
23278c2ecf20Sopenharmony_ci			RX_PAUSE_SLOT_ON);
23288c2ecf20Sopenharmony_ci		break;
23298c2ecf20Sopenharmony_ci	default:
23308c2ecf20Sopenharmony_ci		RTL_W32(tp, RxConfig, RX128_INT_EN | RX_DMA_BURST);
23318c2ecf20Sopenharmony_ci		break;
23328c2ecf20Sopenharmony_ci	}
23338c2ecf20Sopenharmony_ci}
23348c2ecf20Sopenharmony_ci
23358c2ecf20Sopenharmony_cistatic void rtl8169_init_ring_indexes(struct rtl8169_private *tp)
23368c2ecf20Sopenharmony_ci{
23378c2ecf20Sopenharmony_ci	tp->dirty_tx = tp->cur_tx = tp->cur_rx = 0;
23388c2ecf20Sopenharmony_ci}
23398c2ecf20Sopenharmony_ci
23408c2ecf20Sopenharmony_cistatic void r8168c_hw_jumbo_enable(struct rtl8169_private *tp)
23418c2ecf20Sopenharmony_ci{
23428c2ecf20Sopenharmony_ci	RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0);
23438c2ecf20Sopenharmony_ci	RTL_W8(tp, Config4, RTL_R8(tp, Config4) | Jumbo_En1);
23448c2ecf20Sopenharmony_ci}
23458c2ecf20Sopenharmony_ci
23468c2ecf20Sopenharmony_cistatic void r8168c_hw_jumbo_disable(struct rtl8169_private *tp)
23478c2ecf20Sopenharmony_ci{
23488c2ecf20Sopenharmony_ci	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0);
23498c2ecf20Sopenharmony_ci	RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~Jumbo_En1);
23508c2ecf20Sopenharmony_ci}
23518c2ecf20Sopenharmony_ci
23528c2ecf20Sopenharmony_cistatic void r8168dp_hw_jumbo_enable(struct rtl8169_private *tp)
23538c2ecf20Sopenharmony_ci{
23548c2ecf20Sopenharmony_ci	RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0);
23558c2ecf20Sopenharmony_ci}
23568c2ecf20Sopenharmony_ci
23578c2ecf20Sopenharmony_cistatic void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp)
23588c2ecf20Sopenharmony_ci{
23598c2ecf20Sopenharmony_ci	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0);
23608c2ecf20Sopenharmony_ci}
23618c2ecf20Sopenharmony_ci
23628c2ecf20Sopenharmony_cistatic void r8168e_hw_jumbo_enable(struct rtl8169_private *tp)
23638c2ecf20Sopenharmony_ci{
23648c2ecf20Sopenharmony_ci	RTL_W8(tp, MaxTxPacketSize, 0x24);
23658c2ecf20Sopenharmony_ci	RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0);
23668c2ecf20Sopenharmony_ci	RTL_W8(tp, Config4, RTL_R8(tp, Config4) | 0x01);
23678c2ecf20Sopenharmony_ci}
23688c2ecf20Sopenharmony_ci
23698c2ecf20Sopenharmony_cistatic void r8168e_hw_jumbo_disable(struct rtl8169_private *tp)
23708c2ecf20Sopenharmony_ci{
23718c2ecf20Sopenharmony_ci	RTL_W8(tp, MaxTxPacketSize, 0x3f);
23728c2ecf20Sopenharmony_ci	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0);
23738c2ecf20Sopenharmony_ci	RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~0x01);
23748c2ecf20Sopenharmony_ci}
23758c2ecf20Sopenharmony_ci
23768c2ecf20Sopenharmony_cistatic void r8168b_1_hw_jumbo_enable(struct rtl8169_private *tp)
23778c2ecf20Sopenharmony_ci{
23788c2ecf20Sopenharmony_ci	RTL_W8(tp, Config4, RTL_R8(tp, Config4) | (1 << 0));
23798c2ecf20Sopenharmony_ci}
23808c2ecf20Sopenharmony_ci
23818c2ecf20Sopenharmony_cistatic void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp)
23828c2ecf20Sopenharmony_ci{
23838c2ecf20Sopenharmony_ci	RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~(1 << 0));
23848c2ecf20Sopenharmony_ci}
23858c2ecf20Sopenharmony_ci
23868c2ecf20Sopenharmony_cistatic void rtl_jumbo_config(struct rtl8169_private *tp)
23878c2ecf20Sopenharmony_ci{
23888c2ecf20Sopenharmony_ci	bool jumbo = tp->dev->mtu > ETH_DATA_LEN;
23898c2ecf20Sopenharmony_ci	int readrq = 4096;
23908c2ecf20Sopenharmony_ci
23918c2ecf20Sopenharmony_ci	rtl_unlock_config_regs(tp);
23928c2ecf20Sopenharmony_ci	switch (tp->mac_version) {
23938c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_12:
23948c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_17:
23958c2ecf20Sopenharmony_ci		if (jumbo) {
23968c2ecf20Sopenharmony_ci			readrq = 512;
23978c2ecf20Sopenharmony_ci			r8168b_1_hw_jumbo_enable(tp);
23988c2ecf20Sopenharmony_ci		} else {
23998c2ecf20Sopenharmony_ci			r8168b_1_hw_jumbo_disable(tp);
24008c2ecf20Sopenharmony_ci		}
24018c2ecf20Sopenharmony_ci		break;
24028c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_18 ... RTL_GIGA_MAC_VER_26:
24038c2ecf20Sopenharmony_ci		if (jumbo) {
24048c2ecf20Sopenharmony_ci			readrq = 512;
24058c2ecf20Sopenharmony_ci			r8168c_hw_jumbo_enable(tp);
24068c2ecf20Sopenharmony_ci		} else {
24078c2ecf20Sopenharmony_ci			r8168c_hw_jumbo_disable(tp);
24088c2ecf20Sopenharmony_ci		}
24098c2ecf20Sopenharmony_ci		break;
24108c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_27 ... RTL_GIGA_MAC_VER_28:
24118c2ecf20Sopenharmony_ci		if (jumbo)
24128c2ecf20Sopenharmony_ci			r8168dp_hw_jumbo_enable(tp);
24138c2ecf20Sopenharmony_ci		else
24148c2ecf20Sopenharmony_ci			r8168dp_hw_jumbo_disable(tp);
24158c2ecf20Sopenharmony_ci		break;
24168c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_31 ... RTL_GIGA_MAC_VER_33:
24178c2ecf20Sopenharmony_ci		if (jumbo) {
24188c2ecf20Sopenharmony_ci			pcie_set_readrq(tp->pci_dev, 512);
24198c2ecf20Sopenharmony_ci			r8168e_hw_jumbo_enable(tp);
24208c2ecf20Sopenharmony_ci		} else {
24218c2ecf20Sopenharmony_ci			r8168e_hw_jumbo_disable(tp);
24228c2ecf20Sopenharmony_ci		}
24238c2ecf20Sopenharmony_ci		break;
24248c2ecf20Sopenharmony_ci	default:
24258c2ecf20Sopenharmony_ci		break;
24268c2ecf20Sopenharmony_ci	}
24278c2ecf20Sopenharmony_ci	rtl_lock_config_regs(tp);
24288c2ecf20Sopenharmony_ci
24298c2ecf20Sopenharmony_ci	if (pci_is_pcie(tp->pci_dev) && tp->supports_gmii)
24308c2ecf20Sopenharmony_ci		pcie_set_readrq(tp->pci_dev, readrq);
24318c2ecf20Sopenharmony_ci
24328c2ecf20Sopenharmony_ci	/* Chip doesn't support pause in jumbo mode */
24338c2ecf20Sopenharmony_ci	linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT,
24348c2ecf20Sopenharmony_ci			 tp->phydev->advertising, !jumbo);
24358c2ecf20Sopenharmony_ci	linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
24368c2ecf20Sopenharmony_ci			 tp->phydev->advertising, !jumbo);
24378c2ecf20Sopenharmony_ci	phy_start_aneg(tp->phydev);
24388c2ecf20Sopenharmony_ci}
24398c2ecf20Sopenharmony_ci
24408c2ecf20Sopenharmony_ciDECLARE_RTL_COND(rtl_chipcmd_cond)
24418c2ecf20Sopenharmony_ci{
24428c2ecf20Sopenharmony_ci	return RTL_R8(tp, ChipCmd) & CmdReset;
24438c2ecf20Sopenharmony_ci}
24448c2ecf20Sopenharmony_ci
24458c2ecf20Sopenharmony_cistatic void rtl_hw_reset(struct rtl8169_private *tp)
24468c2ecf20Sopenharmony_ci{
24478c2ecf20Sopenharmony_ci	RTL_W8(tp, ChipCmd, CmdReset);
24488c2ecf20Sopenharmony_ci
24498c2ecf20Sopenharmony_ci	rtl_loop_wait_low(tp, &rtl_chipcmd_cond, 100, 100);
24508c2ecf20Sopenharmony_ci}
24518c2ecf20Sopenharmony_ci
24528c2ecf20Sopenharmony_cistatic void rtl_request_firmware(struct rtl8169_private *tp)
24538c2ecf20Sopenharmony_ci{
24548c2ecf20Sopenharmony_ci	struct rtl_fw *rtl_fw;
24558c2ecf20Sopenharmony_ci
24568c2ecf20Sopenharmony_ci	/* firmware loaded already or no firmware available */
24578c2ecf20Sopenharmony_ci	if (tp->rtl_fw || !tp->fw_name)
24588c2ecf20Sopenharmony_ci		return;
24598c2ecf20Sopenharmony_ci
24608c2ecf20Sopenharmony_ci	rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL);
24618c2ecf20Sopenharmony_ci	if (!rtl_fw)
24628c2ecf20Sopenharmony_ci		return;
24638c2ecf20Sopenharmony_ci
24648c2ecf20Sopenharmony_ci	rtl_fw->phy_write = rtl_writephy;
24658c2ecf20Sopenharmony_ci	rtl_fw->phy_read = rtl_readphy;
24668c2ecf20Sopenharmony_ci	rtl_fw->mac_mcu_write = mac_mcu_write;
24678c2ecf20Sopenharmony_ci	rtl_fw->mac_mcu_read = mac_mcu_read;
24688c2ecf20Sopenharmony_ci	rtl_fw->fw_name = tp->fw_name;
24698c2ecf20Sopenharmony_ci	rtl_fw->dev = tp_to_dev(tp);
24708c2ecf20Sopenharmony_ci
24718c2ecf20Sopenharmony_ci	if (rtl_fw_request_firmware(rtl_fw))
24728c2ecf20Sopenharmony_ci		kfree(rtl_fw);
24738c2ecf20Sopenharmony_ci	else
24748c2ecf20Sopenharmony_ci		tp->rtl_fw = rtl_fw;
24758c2ecf20Sopenharmony_ci}
24768c2ecf20Sopenharmony_ci
24778c2ecf20Sopenharmony_cistatic void rtl_rx_close(struct rtl8169_private *tp)
24788c2ecf20Sopenharmony_ci{
24798c2ecf20Sopenharmony_ci	RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) & ~RX_CONFIG_ACCEPT_MASK);
24808c2ecf20Sopenharmony_ci}
24818c2ecf20Sopenharmony_ci
24828c2ecf20Sopenharmony_ciDECLARE_RTL_COND(rtl_npq_cond)
24838c2ecf20Sopenharmony_ci{
24848c2ecf20Sopenharmony_ci	return RTL_R8(tp, TxPoll) & NPQ;
24858c2ecf20Sopenharmony_ci}
24868c2ecf20Sopenharmony_ci
24878c2ecf20Sopenharmony_ciDECLARE_RTL_COND(rtl_txcfg_empty_cond)
24888c2ecf20Sopenharmony_ci{
24898c2ecf20Sopenharmony_ci	return RTL_R32(tp, TxConfig) & TXCFG_EMPTY;
24908c2ecf20Sopenharmony_ci}
24918c2ecf20Sopenharmony_ci
24928c2ecf20Sopenharmony_ciDECLARE_RTL_COND(rtl_rxtx_empty_cond)
24938c2ecf20Sopenharmony_ci{
24948c2ecf20Sopenharmony_ci	return (RTL_R8(tp, MCU) & RXTX_EMPTY) == RXTX_EMPTY;
24958c2ecf20Sopenharmony_ci}
24968c2ecf20Sopenharmony_ci
24978c2ecf20Sopenharmony_ciDECLARE_RTL_COND(rtl_rxtx_empty_cond_2)
24988c2ecf20Sopenharmony_ci{
24998c2ecf20Sopenharmony_ci	/* IntrMitigate has new functionality on RTL8125 */
25008c2ecf20Sopenharmony_ci	return (RTL_R16(tp, IntrMitigate) & 0x0103) == 0x0103;
25018c2ecf20Sopenharmony_ci}
25028c2ecf20Sopenharmony_ci
25038c2ecf20Sopenharmony_cistatic void rtl_wait_txrx_fifo_empty(struct rtl8169_private *tp)
25048c2ecf20Sopenharmony_ci{
25058c2ecf20Sopenharmony_ci	switch (tp->mac_version) {
25068c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_52:
25078c2ecf20Sopenharmony_ci		rtl_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 42);
25088c2ecf20Sopenharmony_ci		rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42);
25098c2ecf20Sopenharmony_ci		break;
25108c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_60 ... RTL_GIGA_MAC_VER_61:
25118c2ecf20Sopenharmony_ci		rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42);
25128c2ecf20Sopenharmony_ci		break;
25138c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_63:
25148c2ecf20Sopenharmony_ci		RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq);
25158c2ecf20Sopenharmony_ci		rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42);
25168c2ecf20Sopenharmony_ci		rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond_2, 100, 42);
25178c2ecf20Sopenharmony_ci		break;
25188c2ecf20Sopenharmony_ci	default:
25198c2ecf20Sopenharmony_ci		break;
25208c2ecf20Sopenharmony_ci	}
25218c2ecf20Sopenharmony_ci}
25228c2ecf20Sopenharmony_ci
25238c2ecf20Sopenharmony_cistatic void rtl_enable_rxdvgate(struct rtl8169_private *tp)
25248c2ecf20Sopenharmony_ci{
25258c2ecf20Sopenharmony_ci	RTL_W32(tp, MISC, RTL_R32(tp, MISC) | RXDV_GATED_EN);
25268c2ecf20Sopenharmony_ci	fsleep(2000);
25278c2ecf20Sopenharmony_ci	rtl_wait_txrx_fifo_empty(tp);
25288c2ecf20Sopenharmony_ci}
25298c2ecf20Sopenharmony_ci
25308c2ecf20Sopenharmony_cistatic void rtl_set_tx_config_registers(struct rtl8169_private *tp)
25318c2ecf20Sopenharmony_ci{
25328c2ecf20Sopenharmony_ci	u32 val = TX_DMA_BURST << TxDMAShift |
25338c2ecf20Sopenharmony_ci		  InterFrameGap << TxInterFrameGapShift;
25348c2ecf20Sopenharmony_ci
25358c2ecf20Sopenharmony_ci	if (rtl_is_8168evl_up(tp))
25368c2ecf20Sopenharmony_ci		val |= TXCFG_AUTO_FIFO;
25378c2ecf20Sopenharmony_ci
25388c2ecf20Sopenharmony_ci	RTL_W32(tp, TxConfig, val);
25398c2ecf20Sopenharmony_ci}
25408c2ecf20Sopenharmony_ci
25418c2ecf20Sopenharmony_cistatic void rtl_set_rx_max_size(struct rtl8169_private *tp)
25428c2ecf20Sopenharmony_ci{
25438c2ecf20Sopenharmony_ci	/* Low hurts. Let's disable the filtering. */
25448c2ecf20Sopenharmony_ci	RTL_W16(tp, RxMaxSize, R8169_RX_BUF_SIZE + 1);
25458c2ecf20Sopenharmony_ci}
25468c2ecf20Sopenharmony_ci
25478c2ecf20Sopenharmony_cistatic void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp)
25488c2ecf20Sopenharmony_ci{
25498c2ecf20Sopenharmony_ci	/*
25508c2ecf20Sopenharmony_ci	 * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh
25518c2ecf20Sopenharmony_ci	 * register to be written before TxDescAddrLow to work.
25528c2ecf20Sopenharmony_ci	 * Switching from MMIO to I/O access fixes the issue as well.
25538c2ecf20Sopenharmony_ci	 */
25548c2ecf20Sopenharmony_ci	RTL_W32(tp, TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32);
25558c2ecf20Sopenharmony_ci	RTL_W32(tp, TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32));
25568c2ecf20Sopenharmony_ci	RTL_W32(tp, RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32);
25578c2ecf20Sopenharmony_ci	RTL_W32(tp, RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32));
25588c2ecf20Sopenharmony_ci}
25598c2ecf20Sopenharmony_ci
25608c2ecf20Sopenharmony_cistatic void rtl8169_set_magic_reg(struct rtl8169_private *tp)
25618c2ecf20Sopenharmony_ci{
25628c2ecf20Sopenharmony_ci	u32 val;
25638c2ecf20Sopenharmony_ci
25648c2ecf20Sopenharmony_ci	if (tp->mac_version == RTL_GIGA_MAC_VER_05)
25658c2ecf20Sopenharmony_ci		val = 0x000fff00;
25668c2ecf20Sopenharmony_ci	else if (tp->mac_version == RTL_GIGA_MAC_VER_06)
25678c2ecf20Sopenharmony_ci		val = 0x00ffff00;
25688c2ecf20Sopenharmony_ci	else
25698c2ecf20Sopenharmony_ci		return;
25708c2ecf20Sopenharmony_ci
25718c2ecf20Sopenharmony_ci	if (RTL_R8(tp, Config2) & PCI_Clock_66MHz)
25728c2ecf20Sopenharmony_ci		val |= 0xff;
25738c2ecf20Sopenharmony_ci
25748c2ecf20Sopenharmony_ci	RTL_W32(tp, 0x7c, val);
25758c2ecf20Sopenharmony_ci}
25768c2ecf20Sopenharmony_ci
25778c2ecf20Sopenharmony_cistatic void rtl_set_rx_mode(struct net_device *dev)
25788c2ecf20Sopenharmony_ci{
25798c2ecf20Sopenharmony_ci	u32 rx_mode = AcceptBroadcast | AcceptMyPhys | AcceptMulticast;
25808c2ecf20Sopenharmony_ci	/* Multicast hash filter */
25818c2ecf20Sopenharmony_ci	u32 mc_filter[2] = { 0xffffffff, 0xffffffff };
25828c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = netdev_priv(dev);
25838c2ecf20Sopenharmony_ci	u32 tmp;
25848c2ecf20Sopenharmony_ci
25858c2ecf20Sopenharmony_ci	if (dev->flags & IFF_PROMISC) {
25868c2ecf20Sopenharmony_ci		rx_mode |= AcceptAllPhys;
25878c2ecf20Sopenharmony_ci	} else if (!(dev->flags & IFF_MULTICAST)) {
25888c2ecf20Sopenharmony_ci		rx_mode &= ~AcceptMulticast;
25898c2ecf20Sopenharmony_ci	} else if (netdev_mc_count(dev) > MC_FILTER_LIMIT ||
25908c2ecf20Sopenharmony_ci		   dev->flags & IFF_ALLMULTI ||
25918c2ecf20Sopenharmony_ci		   tp->mac_version == RTL_GIGA_MAC_VER_35) {
25928c2ecf20Sopenharmony_ci		/* accept all multicasts */
25938c2ecf20Sopenharmony_ci	} else if (netdev_mc_empty(dev)) {
25948c2ecf20Sopenharmony_ci		rx_mode &= ~AcceptMulticast;
25958c2ecf20Sopenharmony_ci	} else {
25968c2ecf20Sopenharmony_ci		struct netdev_hw_addr *ha;
25978c2ecf20Sopenharmony_ci
25988c2ecf20Sopenharmony_ci		mc_filter[1] = mc_filter[0] = 0;
25998c2ecf20Sopenharmony_ci		netdev_for_each_mc_addr(ha, dev) {
26008c2ecf20Sopenharmony_ci			u32 bit_nr = eth_hw_addr_crc(ha) >> 26;
26018c2ecf20Sopenharmony_ci			mc_filter[bit_nr >> 5] |= BIT(bit_nr & 31);
26028c2ecf20Sopenharmony_ci		}
26038c2ecf20Sopenharmony_ci
26048c2ecf20Sopenharmony_ci		if (tp->mac_version > RTL_GIGA_MAC_VER_06) {
26058c2ecf20Sopenharmony_ci			tmp = mc_filter[0];
26068c2ecf20Sopenharmony_ci			mc_filter[0] = swab32(mc_filter[1]);
26078c2ecf20Sopenharmony_ci			mc_filter[1] = swab32(tmp);
26088c2ecf20Sopenharmony_ci		}
26098c2ecf20Sopenharmony_ci	}
26108c2ecf20Sopenharmony_ci
26118c2ecf20Sopenharmony_ci	RTL_W32(tp, MAR0 + 4, mc_filter[1]);
26128c2ecf20Sopenharmony_ci	RTL_W32(tp, MAR0 + 0, mc_filter[0]);
26138c2ecf20Sopenharmony_ci
26148c2ecf20Sopenharmony_ci	tmp = RTL_R32(tp, RxConfig);
26158c2ecf20Sopenharmony_ci	RTL_W32(tp, RxConfig, (tmp & ~RX_CONFIG_ACCEPT_OK_MASK) | rx_mode);
26168c2ecf20Sopenharmony_ci}
26178c2ecf20Sopenharmony_ci
26188c2ecf20Sopenharmony_ciDECLARE_RTL_COND(rtl_csiar_cond)
26198c2ecf20Sopenharmony_ci{
26208c2ecf20Sopenharmony_ci	return RTL_R32(tp, CSIAR) & CSIAR_FLAG;
26218c2ecf20Sopenharmony_ci}
26228c2ecf20Sopenharmony_ci
26238c2ecf20Sopenharmony_cistatic void rtl_csi_write(struct rtl8169_private *tp, int addr, int value)
26248c2ecf20Sopenharmony_ci{
26258c2ecf20Sopenharmony_ci	u32 func = PCI_FUNC(tp->pci_dev->devfn);
26268c2ecf20Sopenharmony_ci
26278c2ecf20Sopenharmony_ci	RTL_W32(tp, CSIDR, value);
26288c2ecf20Sopenharmony_ci	RTL_W32(tp, CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) |
26298c2ecf20Sopenharmony_ci		CSIAR_BYTE_ENABLE | func << 16);
26308c2ecf20Sopenharmony_ci
26318c2ecf20Sopenharmony_ci	rtl_loop_wait_low(tp, &rtl_csiar_cond, 10, 100);
26328c2ecf20Sopenharmony_ci}
26338c2ecf20Sopenharmony_ci
26348c2ecf20Sopenharmony_cistatic u32 rtl_csi_read(struct rtl8169_private *tp, int addr)
26358c2ecf20Sopenharmony_ci{
26368c2ecf20Sopenharmony_ci	u32 func = PCI_FUNC(tp->pci_dev->devfn);
26378c2ecf20Sopenharmony_ci
26388c2ecf20Sopenharmony_ci	RTL_W32(tp, CSIAR, (addr & CSIAR_ADDR_MASK) | func << 16 |
26398c2ecf20Sopenharmony_ci		CSIAR_BYTE_ENABLE);
26408c2ecf20Sopenharmony_ci
26418c2ecf20Sopenharmony_ci	return rtl_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ?
26428c2ecf20Sopenharmony_ci		RTL_R32(tp, CSIDR) : ~0;
26438c2ecf20Sopenharmony_ci}
26448c2ecf20Sopenharmony_ci
26458c2ecf20Sopenharmony_cistatic void rtl_csi_access_enable(struct rtl8169_private *tp, u8 val)
26468c2ecf20Sopenharmony_ci{
26478c2ecf20Sopenharmony_ci	struct pci_dev *pdev = tp->pci_dev;
26488c2ecf20Sopenharmony_ci	u32 csi;
26498c2ecf20Sopenharmony_ci
26508c2ecf20Sopenharmony_ci	/* According to Realtek the value at config space address 0x070f
26518c2ecf20Sopenharmony_ci	 * controls the L0s/L1 entrance latency. We try standard ECAM access
26528c2ecf20Sopenharmony_ci	 * first and if it fails fall back to CSI.
26538c2ecf20Sopenharmony_ci	 */
26548c2ecf20Sopenharmony_ci	if (pdev->cfg_size > 0x070f &&
26558c2ecf20Sopenharmony_ci	    pci_write_config_byte(pdev, 0x070f, val) == PCIBIOS_SUCCESSFUL)
26568c2ecf20Sopenharmony_ci		return;
26578c2ecf20Sopenharmony_ci
26588c2ecf20Sopenharmony_ci	netdev_notice_once(tp->dev,
26598c2ecf20Sopenharmony_ci		"No native access to PCI extended config space, falling back to CSI\n");
26608c2ecf20Sopenharmony_ci	csi = rtl_csi_read(tp, 0x070c) & 0x00ffffff;
26618c2ecf20Sopenharmony_ci	rtl_csi_write(tp, 0x070c, csi | val << 24);
26628c2ecf20Sopenharmony_ci}
26638c2ecf20Sopenharmony_ci
26648c2ecf20Sopenharmony_cistatic void rtl_set_def_aspm_entry_latency(struct rtl8169_private *tp)
26658c2ecf20Sopenharmony_ci{
26668c2ecf20Sopenharmony_ci	rtl_csi_access_enable(tp, 0x27);
26678c2ecf20Sopenharmony_ci}
26688c2ecf20Sopenharmony_ci
26698c2ecf20Sopenharmony_cistruct ephy_info {
26708c2ecf20Sopenharmony_ci	unsigned int offset;
26718c2ecf20Sopenharmony_ci	u16 mask;
26728c2ecf20Sopenharmony_ci	u16 bits;
26738c2ecf20Sopenharmony_ci};
26748c2ecf20Sopenharmony_ci
26758c2ecf20Sopenharmony_cistatic void __rtl_ephy_init(struct rtl8169_private *tp,
26768c2ecf20Sopenharmony_ci			    const struct ephy_info *e, int len)
26778c2ecf20Sopenharmony_ci{
26788c2ecf20Sopenharmony_ci	u16 w;
26798c2ecf20Sopenharmony_ci
26808c2ecf20Sopenharmony_ci	while (len-- > 0) {
26818c2ecf20Sopenharmony_ci		w = (rtl_ephy_read(tp, e->offset) & ~e->mask) | e->bits;
26828c2ecf20Sopenharmony_ci		rtl_ephy_write(tp, e->offset, w);
26838c2ecf20Sopenharmony_ci		e++;
26848c2ecf20Sopenharmony_ci	}
26858c2ecf20Sopenharmony_ci}
26868c2ecf20Sopenharmony_ci
26878c2ecf20Sopenharmony_ci#define rtl_ephy_init(tp, a) __rtl_ephy_init(tp, a, ARRAY_SIZE(a))
26888c2ecf20Sopenharmony_ci
26898c2ecf20Sopenharmony_cistatic void rtl_disable_clock_request(struct rtl8169_private *tp)
26908c2ecf20Sopenharmony_ci{
26918c2ecf20Sopenharmony_ci	pcie_capability_clear_word(tp->pci_dev, PCI_EXP_LNKCTL,
26928c2ecf20Sopenharmony_ci				   PCI_EXP_LNKCTL_CLKREQ_EN);
26938c2ecf20Sopenharmony_ci}
26948c2ecf20Sopenharmony_ci
26958c2ecf20Sopenharmony_cistatic void rtl_enable_clock_request(struct rtl8169_private *tp)
26968c2ecf20Sopenharmony_ci{
26978c2ecf20Sopenharmony_ci	pcie_capability_set_word(tp->pci_dev, PCI_EXP_LNKCTL,
26988c2ecf20Sopenharmony_ci				 PCI_EXP_LNKCTL_CLKREQ_EN);
26998c2ecf20Sopenharmony_ci}
27008c2ecf20Sopenharmony_ci
27018c2ecf20Sopenharmony_cistatic void rtl_pcie_state_l2l3_disable(struct rtl8169_private *tp)
27028c2ecf20Sopenharmony_ci{
27038c2ecf20Sopenharmony_ci	/* work around an issue when PCI reset occurs during L2/L3 state */
27048c2ecf20Sopenharmony_ci	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Rdy_to_L23);
27058c2ecf20Sopenharmony_ci}
27068c2ecf20Sopenharmony_ci
27078c2ecf20Sopenharmony_cistatic void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
27088c2ecf20Sopenharmony_ci{
27098c2ecf20Sopenharmony_ci	/* Don't enable ASPM in the chip if OS can't control ASPM */
27108c2ecf20Sopenharmony_ci	if (enable && tp->aspm_manageable) {
27118c2ecf20Sopenharmony_ci		RTL_W8(tp, Config5, RTL_R8(tp, Config5) | ASPM_en);
27128c2ecf20Sopenharmony_ci		RTL_W8(tp, Config2, RTL_R8(tp, Config2) | ClkReqEn);
27138c2ecf20Sopenharmony_ci	} else {
27148c2ecf20Sopenharmony_ci		RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn);
27158c2ecf20Sopenharmony_ci		RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en);
27168c2ecf20Sopenharmony_ci	}
27178c2ecf20Sopenharmony_ci
27188c2ecf20Sopenharmony_ci	udelay(10);
27198c2ecf20Sopenharmony_ci}
27208c2ecf20Sopenharmony_ci
27218c2ecf20Sopenharmony_cistatic void rtl_set_fifo_size(struct rtl8169_private *tp, u16 rx_stat,
27228c2ecf20Sopenharmony_ci			      u16 tx_stat, u16 rx_dyn, u16 tx_dyn)
27238c2ecf20Sopenharmony_ci{
27248c2ecf20Sopenharmony_ci	/* Usage of dynamic vs. static FIFO is controlled by bit
27258c2ecf20Sopenharmony_ci	 * TXCFG_AUTO_FIFO. Exact meaning of FIFO values isn't known.
27268c2ecf20Sopenharmony_ci	 */
27278c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, (rx_stat << 16) | rx_dyn);
27288c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, (tx_stat << 16) | tx_dyn);
27298c2ecf20Sopenharmony_ci}
27308c2ecf20Sopenharmony_ci
27318c2ecf20Sopenharmony_cistatic void rtl8168g_set_pause_thresholds(struct rtl8169_private *tp,
27328c2ecf20Sopenharmony_ci					  u8 low, u8 high)
27338c2ecf20Sopenharmony_ci{
27348c2ecf20Sopenharmony_ci	/* FIFO thresholds for pause flow control */
27358c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xcc, ERIAR_MASK_0001, low);
27368c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xd0, ERIAR_MASK_0001, high);
27378c2ecf20Sopenharmony_ci}
27388c2ecf20Sopenharmony_ci
27398c2ecf20Sopenharmony_cistatic void rtl_hw_start_8168b(struct rtl8169_private *tp)
27408c2ecf20Sopenharmony_ci{
27418c2ecf20Sopenharmony_ci	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en);
27428c2ecf20Sopenharmony_ci}
27438c2ecf20Sopenharmony_ci
27448c2ecf20Sopenharmony_cistatic void __rtl_hw_start_8168cp(struct rtl8169_private *tp)
27458c2ecf20Sopenharmony_ci{
27468c2ecf20Sopenharmony_ci	RTL_W8(tp, Config1, RTL_R8(tp, Config1) | Speed_down);
27478c2ecf20Sopenharmony_ci
27488c2ecf20Sopenharmony_ci	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en);
27498c2ecf20Sopenharmony_ci
27508c2ecf20Sopenharmony_ci	rtl_disable_clock_request(tp);
27518c2ecf20Sopenharmony_ci}
27528c2ecf20Sopenharmony_ci
27538c2ecf20Sopenharmony_cistatic void rtl_hw_start_8168cp_1(struct rtl8169_private *tp)
27548c2ecf20Sopenharmony_ci{
27558c2ecf20Sopenharmony_ci	static const struct ephy_info e_info_8168cp[] = {
27568c2ecf20Sopenharmony_ci		{ 0x01, 0,	0x0001 },
27578c2ecf20Sopenharmony_ci		{ 0x02, 0x0800,	0x1000 },
27588c2ecf20Sopenharmony_ci		{ 0x03, 0,	0x0042 },
27598c2ecf20Sopenharmony_ci		{ 0x06, 0x0080,	0x0000 },
27608c2ecf20Sopenharmony_ci		{ 0x07, 0,	0x2000 }
27618c2ecf20Sopenharmony_ci	};
27628c2ecf20Sopenharmony_ci
27638c2ecf20Sopenharmony_ci	rtl_set_def_aspm_entry_latency(tp);
27648c2ecf20Sopenharmony_ci
27658c2ecf20Sopenharmony_ci	rtl_ephy_init(tp, e_info_8168cp);
27668c2ecf20Sopenharmony_ci
27678c2ecf20Sopenharmony_ci	__rtl_hw_start_8168cp(tp);
27688c2ecf20Sopenharmony_ci}
27698c2ecf20Sopenharmony_ci
27708c2ecf20Sopenharmony_cistatic void rtl_hw_start_8168cp_2(struct rtl8169_private *tp)
27718c2ecf20Sopenharmony_ci{
27728c2ecf20Sopenharmony_ci	rtl_set_def_aspm_entry_latency(tp);
27738c2ecf20Sopenharmony_ci
27748c2ecf20Sopenharmony_ci	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en);
27758c2ecf20Sopenharmony_ci}
27768c2ecf20Sopenharmony_ci
27778c2ecf20Sopenharmony_cistatic void rtl_hw_start_8168cp_3(struct rtl8169_private *tp)
27788c2ecf20Sopenharmony_ci{
27798c2ecf20Sopenharmony_ci	rtl_set_def_aspm_entry_latency(tp);
27808c2ecf20Sopenharmony_ci
27818c2ecf20Sopenharmony_ci	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en);
27828c2ecf20Sopenharmony_ci
27838c2ecf20Sopenharmony_ci	/* Magic. */
27848c2ecf20Sopenharmony_ci	RTL_W8(tp, DBG_REG, 0x20);
27858c2ecf20Sopenharmony_ci}
27868c2ecf20Sopenharmony_ci
27878c2ecf20Sopenharmony_cistatic void rtl_hw_start_8168c_1(struct rtl8169_private *tp)
27888c2ecf20Sopenharmony_ci{
27898c2ecf20Sopenharmony_ci	static const struct ephy_info e_info_8168c_1[] = {
27908c2ecf20Sopenharmony_ci		{ 0x02, 0x0800,	0x1000 },
27918c2ecf20Sopenharmony_ci		{ 0x03, 0,	0x0002 },
27928c2ecf20Sopenharmony_ci		{ 0x06, 0x0080,	0x0000 }
27938c2ecf20Sopenharmony_ci	};
27948c2ecf20Sopenharmony_ci
27958c2ecf20Sopenharmony_ci	rtl_set_def_aspm_entry_latency(tp);
27968c2ecf20Sopenharmony_ci
27978c2ecf20Sopenharmony_ci	RTL_W8(tp, DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2);
27988c2ecf20Sopenharmony_ci
27998c2ecf20Sopenharmony_ci	rtl_ephy_init(tp, e_info_8168c_1);
28008c2ecf20Sopenharmony_ci
28018c2ecf20Sopenharmony_ci	__rtl_hw_start_8168cp(tp);
28028c2ecf20Sopenharmony_ci}
28038c2ecf20Sopenharmony_ci
28048c2ecf20Sopenharmony_cistatic void rtl_hw_start_8168c_2(struct rtl8169_private *tp)
28058c2ecf20Sopenharmony_ci{
28068c2ecf20Sopenharmony_ci	static const struct ephy_info e_info_8168c_2[] = {
28078c2ecf20Sopenharmony_ci		{ 0x01, 0,	0x0001 },
28088c2ecf20Sopenharmony_ci		{ 0x03, 0x0400,	0x0020 }
28098c2ecf20Sopenharmony_ci	};
28108c2ecf20Sopenharmony_ci
28118c2ecf20Sopenharmony_ci	rtl_set_def_aspm_entry_latency(tp);
28128c2ecf20Sopenharmony_ci
28138c2ecf20Sopenharmony_ci	rtl_ephy_init(tp, e_info_8168c_2);
28148c2ecf20Sopenharmony_ci
28158c2ecf20Sopenharmony_ci	__rtl_hw_start_8168cp(tp);
28168c2ecf20Sopenharmony_ci}
28178c2ecf20Sopenharmony_ci
28188c2ecf20Sopenharmony_cistatic void rtl_hw_start_8168c_3(struct rtl8169_private *tp)
28198c2ecf20Sopenharmony_ci{
28208c2ecf20Sopenharmony_ci	rtl_hw_start_8168c_2(tp);
28218c2ecf20Sopenharmony_ci}
28228c2ecf20Sopenharmony_ci
28238c2ecf20Sopenharmony_cistatic void rtl_hw_start_8168c_4(struct rtl8169_private *tp)
28248c2ecf20Sopenharmony_ci{
28258c2ecf20Sopenharmony_ci	rtl_set_def_aspm_entry_latency(tp);
28268c2ecf20Sopenharmony_ci
28278c2ecf20Sopenharmony_ci	__rtl_hw_start_8168cp(tp);
28288c2ecf20Sopenharmony_ci}
28298c2ecf20Sopenharmony_ci
28308c2ecf20Sopenharmony_cistatic void rtl_hw_start_8168d(struct rtl8169_private *tp)
28318c2ecf20Sopenharmony_ci{
28328c2ecf20Sopenharmony_ci	rtl_set_def_aspm_entry_latency(tp);
28338c2ecf20Sopenharmony_ci
28348c2ecf20Sopenharmony_ci	rtl_disable_clock_request(tp);
28358c2ecf20Sopenharmony_ci}
28368c2ecf20Sopenharmony_ci
28378c2ecf20Sopenharmony_cistatic void rtl_hw_start_8168d_4(struct rtl8169_private *tp)
28388c2ecf20Sopenharmony_ci{
28398c2ecf20Sopenharmony_ci	static const struct ephy_info e_info_8168d_4[] = {
28408c2ecf20Sopenharmony_ci		{ 0x0b, 0x0000,	0x0048 },
28418c2ecf20Sopenharmony_ci		{ 0x19, 0x0020,	0x0050 },
28428c2ecf20Sopenharmony_ci		{ 0x0c, 0x0100,	0x0020 },
28438c2ecf20Sopenharmony_ci		{ 0x10, 0x0004,	0x0000 },
28448c2ecf20Sopenharmony_ci	};
28458c2ecf20Sopenharmony_ci
28468c2ecf20Sopenharmony_ci	rtl_set_def_aspm_entry_latency(tp);
28478c2ecf20Sopenharmony_ci
28488c2ecf20Sopenharmony_ci	rtl_ephy_init(tp, e_info_8168d_4);
28498c2ecf20Sopenharmony_ci
28508c2ecf20Sopenharmony_ci	rtl_enable_clock_request(tp);
28518c2ecf20Sopenharmony_ci}
28528c2ecf20Sopenharmony_ci
28538c2ecf20Sopenharmony_cistatic void rtl_hw_start_8168e_1(struct rtl8169_private *tp)
28548c2ecf20Sopenharmony_ci{
28558c2ecf20Sopenharmony_ci	static const struct ephy_info e_info_8168e_1[] = {
28568c2ecf20Sopenharmony_ci		{ 0x00, 0x0200,	0x0100 },
28578c2ecf20Sopenharmony_ci		{ 0x00, 0x0000,	0x0004 },
28588c2ecf20Sopenharmony_ci		{ 0x06, 0x0002,	0x0001 },
28598c2ecf20Sopenharmony_ci		{ 0x06, 0x0000,	0x0030 },
28608c2ecf20Sopenharmony_ci		{ 0x07, 0x0000,	0x2000 },
28618c2ecf20Sopenharmony_ci		{ 0x00, 0x0000,	0x0020 },
28628c2ecf20Sopenharmony_ci		{ 0x03, 0x5800,	0x2000 },
28638c2ecf20Sopenharmony_ci		{ 0x03, 0x0000,	0x0001 },
28648c2ecf20Sopenharmony_ci		{ 0x01, 0x0800,	0x1000 },
28658c2ecf20Sopenharmony_ci		{ 0x07, 0x0000,	0x4000 },
28668c2ecf20Sopenharmony_ci		{ 0x1e, 0x0000,	0x2000 },
28678c2ecf20Sopenharmony_ci		{ 0x19, 0xffff,	0xfe6c },
28688c2ecf20Sopenharmony_ci		{ 0x0a, 0x0000,	0x0040 }
28698c2ecf20Sopenharmony_ci	};
28708c2ecf20Sopenharmony_ci
28718c2ecf20Sopenharmony_ci	rtl_set_def_aspm_entry_latency(tp);
28728c2ecf20Sopenharmony_ci
28738c2ecf20Sopenharmony_ci	rtl_ephy_init(tp, e_info_8168e_1);
28748c2ecf20Sopenharmony_ci
28758c2ecf20Sopenharmony_ci	rtl_disable_clock_request(tp);
28768c2ecf20Sopenharmony_ci
28778c2ecf20Sopenharmony_ci	/* Reset tx FIFO pointer */
28788c2ecf20Sopenharmony_ci	RTL_W32(tp, MISC, RTL_R32(tp, MISC) | TXPLA_RST);
28798c2ecf20Sopenharmony_ci	RTL_W32(tp, MISC, RTL_R32(tp, MISC) & ~TXPLA_RST);
28808c2ecf20Sopenharmony_ci
28818c2ecf20Sopenharmony_ci	RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~Spi_en);
28828c2ecf20Sopenharmony_ci}
28838c2ecf20Sopenharmony_ci
28848c2ecf20Sopenharmony_cistatic void rtl_hw_start_8168e_2(struct rtl8169_private *tp)
28858c2ecf20Sopenharmony_ci{
28868c2ecf20Sopenharmony_ci	static const struct ephy_info e_info_8168e_2[] = {
28878c2ecf20Sopenharmony_ci		{ 0x09, 0x0000,	0x0080 },
28888c2ecf20Sopenharmony_ci		{ 0x19, 0x0000,	0x0224 },
28898c2ecf20Sopenharmony_ci		{ 0x00, 0x0000,	0x0004 },
28908c2ecf20Sopenharmony_ci		{ 0x0c, 0x3df0,	0x0200 },
28918c2ecf20Sopenharmony_ci	};
28928c2ecf20Sopenharmony_ci
28938c2ecf20Sopenharmony_ci	rtl_set_def_aspm_entry_latency(tp);
28948c2ecf20Sopenharmony_ci
28958c2ecf20Sopenharmony_ci	rtl_ephy_init(tp, e_info_8168e_2);
28968c2ecf20Sopenharmony_ci
28978c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000);
28988c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xb8, ERIAR_MASK_1111, 0x0000);
28998c2ecf20Sopenharmony_ci	rtl_set_fifo_size(tp, 0x10, 0x10, 0x02, 0x06);
29008c2ecf20Sopenharmony_ci	rtl_eri_set_bits(tp, 0x0d4, 0x1f00);
29018c2ecf20Sopenharmony_ci	rtl_eri_set_bits(tp, 0x1d0, BIT(1));
29028c2ecf20Sopenharmony_ci	rtl_reset_packet_filter(tp);
29038c2ecf20Sopenharmony_ci	rtl_eri_set_bits(tp, 0x1b0, BIT(4));
29048c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050);
29058c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x07ff0060);
29068c2ecf20Sopenharmony_ci
29078c2ecf20Sopenharmony_ci	rtl_disable_clock_request(tp);
29088c2ecf20Sopenharmony_ci
29098c2ecf20Sopenharmony_ci	RTL_W8(tp, MCU, RTL_R8(tp, MCU) & ~NOW_IS_OOB);
29108c2ecf20Sopenharmony_ci
29118c2ecf20Sopenharmony_ci	rtl8168_config_eee_mac(tp);
29128c2ecf20Sopenharmony_ci
29138c2ecf20Sopenharmony_ci	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) | PFM_EN);
29148c2ecf20Sopenharmony_ci	RTL_W32(tp, MISC, RTL_R32(tp, MISC) | PWM_EN);
29158c2ecf20Sopenharmony_ci	RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~Spi_en);
29168c2ecf20Sopenharmony_ci
29178c2ecf20Sopenharmony_ci	rtl_hw_aspm_clkreq_enable(tp, true);
29188c2ecf20Sopenharmony_ci}
29198c2ecf20Sopenharmony_ci
29208c2ecf20Sopenharmony_cistatic void rtl_hw_start_8168f(struct rtl8169_private *tp)
29218c2ecf20Sopenharmony_ci{
29228c2ecf20Sopenharmony_ci	rtl_set_def_aspm_entry_latency(tp);
29238c2ecf20Sopenharmony_ci
29248c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000);
29258c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xb8, ERIAR_MASK_1111, 0x0000);
29268c2ecf20Sopenharmony_ci	rtl_set_fifo_size(tp, 0x10, 0x10, 0x02, 0x06);
29278c2ecf20Sopenharmony_ci	rtl_reset_packet_filter(tp);
29288c2ecf20Sopenharmony_ci	rtl_eri_set_bits(tp, 0x1b0, BIT(4));
29298c2ecf20Sopenharmony_ci	rtl_eri_set_bits(tp, 0x1d0, BIT(4) | BIT(1));
29308c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050);
29318c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x00000060);
29328c2ecf20Sopenharmony_ci
29338c2ecf20Sopenharmony_ci	rtl_disable_clock_request(tp);
29348c2ecf20Sopenharmony_ci
29358c2ecf20Sopenharmony_ci	RTL_W8(tp, MCU, RTL_R8(tp, MCU) & ~NOW_IS_OOB);
29368c2ecf20Sopenharmony_ci	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) | PFM_EN);
29378c2ecf20Sopenharmony_ci	RTL_W32(tp, MISC, RTL_R32(tp, MISC) | PWM_EN);
29388c2ecf20Sopenharmony_ci	RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~Spi_en);
29398c2ecf20Sopenharmony_ci
29408c2ecf20Sopenharmony_ci	rtl8168_config_eee_mac(tp);
29418c2ecf20Sopenharmony_ci}
29428c2ecf20Sopenharmony_ci
29438c2ecf20Sopenharmony_cistatic void rtl_hw_start_8168f_1(struct rtl8169_private *tp)
29448c2ecf20Sopenharmony_ci{
29458c2ecf20Sopenharmony_ci	static const struct ephy_info e_info_8168f_1[] = {
29468c2ecf20Sopenharmony_ci		{ 0x06, 0x00c0,	0x0020 },
29478c2ecf20Sopenharmony_ci		{ 0x08, 0x0001,	0x0002 },
29488c2ecf20Sopenharmony_ci		{ 0x09, 0x0000,	0x0080 },
29498c2ecf20Sopenharmony_ci		{ 0x19, 0x0000,	0x0224 },
29508c2ecf20Sopenharmony_ci		{ 0x00, 0x0000,	0x0008 },
29518c2ecf20Sopenharmony_ci		{ 0x0c, 0x3df0,	0x0200 },
29528c2ecf20Sopenharmony_ci	};
29538c2ecf20Sopenharmony_ci
29548c2ecf20Sopenharmony_ci	rtl_hw_start_8168f(tp);
29558c2ecf20Sopenharmony_ci
29568c2ecf20Sopenharmony_ci	rtl_ephy_init(tp, e_info_8168f_1);
29578c2ecf20Sopenharmony_ci
29588c2ecf20Sopenharmony_ci	rtl_eri_set_bits(tp, 0x0d4, 0x1f00);
29598c2ecf20Sopenharmony_ci}
29608c2ecf20Sopenharmony_ci
29618c2ecf20Sopenharmony_cistatic void rtl_hw_start_8411(struct rtl8169_private *tp)
29628c2ecf20Sopenharmony_ci{
29638c2ecf20Sopenharmony_ci	static const struct ephy_info e_info_8168f_1[] = {
29648c2ecf20Sopenharmony_ci		{ 0x06, 0x00c0,	0x0020 },
29658c2ecf20Sopenharmony_ci		{ 0x0f, 0xffff,	0x5200 },
29668c2ecf20Sopenharmony_ci		{ 0x19, 0x0000,	0x0224 },
29678c2ecf20Sopenharmony_ci		{ 0x00, 0x0000,	0x0008 },
29688c2ecf20Sopenharmony_ci		{ 0x0c, 0x3df0,	0x0200 },
29698c2ecf20Sopenharmony_ci	};
29708c2ecf20Sopenharmony_ci
29718c2ecf20Sopenharmony_ci	rtl_hw_start_8168f(tp);
29728c2ecf20Sopenharmony_ci	rtl_pcie_state_l2l3_disable(tp);
29738c2ecf20Sopenharmony_ci
29748c2ecf20Sopenharmony_ci	rtl_ephy_init(tp, e_info_8168f_1);
29758c2ecf20Sopenharmony_ci
29768c2ecf20Sopenharmony_ci	rtl_eri_set_bits(tp, 0x0d4, 0x0c00);
29778c2ecf20Sopenharmony_ci}
29788c2ecf20Sopenharmony_ci
29798c2ecf20Sopenharmony_cistatic void rtl_hw_start_8168g(struct rtl8169_private *tp)
29808c2ecf20Sopenharmony_ci{
29818c2ecf20Sopenharmony_ci	rtl_set_fifo_size(tp, 0x08, 0x10, 0x02, 0x06);
29828c2ecf20Sopenharmony_ci	rtl8168g_set_pause_thresholds(tp, 0x38, 0x48);
29838c2ecf20Sopenharmony_ci
29848c2ecf20Sopenharmony_ci	rtl_set_def_aspm_entry_latency(tp);
29858c2ecf20Sopenharmony_ci
29868c2ecf20Sopenharmony_ci	rtl_reset_packet_filter(tp);
29878c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0x2f8, ERIAR_MASK_0011, 0x1d8f);
29888c2ecf20Sopenharmony_ci
29898c2ecf20Sopenharmony_ci	RTL_W32(tp, MISC, RTL_R32(tp, MISC) & ~RXDV_GATED_EN);
29908c2ecf20Sopenharmony_ci
29918c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000);
29928c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000);
29938c2ecf20Sopenharmony_ci	rtl_eri_set_bits(tp, 0x0d4, 0x1f80);
29948c2ecf20Sopenharmony_ci
29958c2ecf20Sopenharmony_ci	rtl8168_config_eee_mac(tp);
29968c2ecf20Sopenharmony_ci
29978c2ecf20Sopenharmony_ci	rtl_w0w1_eri(tp, 0x2fc, 0x01, 0x06);
29988c2ecf20Sopenharmony_ci	rtl_eri_clear_bits(tp, 0x1b0, BIT(12));
29998c2ecf20Sopenharmony_ci
30008c2ecf20Sopenharmony_ci	rtl_pcie_state_l2l3_disable(tp);
30018c2ecf20Sopenharmony_ci}
30028c2ecf20Sopenharmony_ci
30038c2ecf20Sopenharmony_cistatic void rtl_hw_start_8168g_1(struct rtl8169_private *tp)
30048c2ecf20Sopenharmony_ci{
30058c2ecf20Sopenharmony_ci	static const struct ephy_info e_info_8168g_1[] = {
30068c2ecf20Sopenharmony_ci		{ 0x00, 0x0008,	0x0000 },
30078c2ecf20Sopenharmony_ci		{ 0x0c, 0x3ff0,	0x0820 },
30088c2ecf20Sopenharmony_ci		{ 0x1e, 0x0000,	0x0001 },
30098c2ecf20Sopenharmony_ci		{ 0x19, 0x8000,	0x0000 }
30108c2ecf20Sopenharmony_ci	};
30118c2ecf20Sopenharmony_ci
30128c2ecf20Sopenharmony_ci	rtl_hw_start_8168g(tp);
30138c2ecf20Sopenharmony_ci
30148c2ecf20Sopenharmony_ci	/* disable aspm and clock request before access ephy */
30158c2ecf20Sopenharmony_ci	rtl_hw_aspm_clkreq_enable(tp, false);
30168c2ecf20Sopenharmony_ci	rtl_ephy_init(tp, e_info_8168g_1);
30178c2ecf20Sopenharmony_ci	rtl_hw_aspm_clkreq_enable(tp, true);
30188c2ecf20Sopenharmony_ci}
30198c2ecf20Sopenharmony_ci
30208c2ecf20Sopenharmony_cistatic void rtl_hw_start_8168g_2(struct rtl8169_private *tp)
30218c2ecf20Sopenharmony_ci{
30228c2ecf20Sopenharmony_ci	static const struct ephy_info e_info_8168g_2[] = {
30238c2ecf20Sopenharmony_ci		{ 0x00, 0x0008,	0x0000 },
30248c2ecf20Sopenharmony_ci		{ 0x0c, 0x3ff0,	0x0820 },
30258c2ecf20Sopenharmony_ci		{ 0x19, 0xffff,	0x7c00 },
30268c2ecf20Sopenharmony_ci		{ 0x1e, 0xffff,	0x20eb },
30278c2ecf20Sopenharmony_ci		{ 0x0d, 0xffff,	0x1666 },
30288c2ecf20Sopenharmony_ci		{ 0x00, 0xffff,	0x10a3 },
30298c2ecf20Sopenharmony_ci		{ 0x06, 0xffff,	0xf050 },
30308c2ecf20Sopenharmony_ci		{ 0x04, 0x0000,	0x0010 },
30318c2ecf20Sopenharmony_ci		{ 0x1d, 0x4000,	0x0000 },
30328c2ecf20Sopenharmony_ci	};
30338c2ecf20Sopenharmony_ci
30348c2ecf20Sopenharmony_ci	rtl_hw_start_8168g(tp);
30358c2ecf20Sopenharmony_ci
30368c2ecf20Sopenharmony_ci	/* disable aspm and clock request before access ephy */
30378c2ecf20Sopenharmony_ci	rtl_hw_aspm_clkreq_enable(tp, false);
30388c2ecf20Sopenharmony_ci	rtl_ephy_init(tp, e_info_8168g_2);
30398c2ecf20Sopenharmony_ci}
30408c2ecf20Sopenharmony_ci
30418c2ecf20Sopenharmony_cistatic void rtl_hw_start_8411_2(struct rtl8169_private *tp)
30428c2ecf20Sopenharmony_ci{
30438c2ecf20Sopenharmony_ci	static const struct ephy_info e_info_8411_2[] = {
30448c2ecf20Sopenharmony_ci		{ 0x00, 0x0008,	0x0000 },
30458c2ecf20Sopenharmony_ci		{ 0x0c, 0x37d0,	0x0820 },
30468c2ecf20Sopenharmony_ci		{ 0x1e, 0x0000,	0x0001 },
30478c2ecf20Sopenharmony_ci		{ 0x19, 0x8021,	0x0000 },
30488c2ecf20Sopenharmony_ci		{ 0x1e, 0x0000,	0x2000 },
30498c2ecf20Sopenharmony_ci		{ 0x0d, 0x0100,	0x0200 },
30508c2ecf20Sopenharmony_ci		{ 0x00, 0x0000,	0x0080 },
30518c2ecf20Sopenharmony_ci		{ 0x06, 0x0000,	0x0010 },
30528c2ecf20Sopenharmony_ci		{ 0x04, 0x0000,	0x0010 },
30538c2ecf20Sopenharmony_ci		{ 0x1d, 0x0000,	0x4000 },
30548c2ecf20Sopenharmony_ci	};
30558c2ecf20Sopenharmony_ci
30568c2ecf20Sopenharmony_ci	rtl_hw_start_8168g(tp);
30578c2ecf20Sopenharmony_ci
30588c2ecf20Sopenharmony_ci	/* disable aspm and clock request before access ephy */
30598c2ecf20Sopenharmony_ci	rtl_hw_aspm_clkreq_enable(tp, false);
30608c2ecf20Sopenharmony_ci	rtl_ephy_init(tp, e_info_8411_2);
30618c2ecf20Sopenharmony_ci
30628c2ecf20Sopenharmony_ci	/* The following Realtek-provided magic fixes an issue with the RX unit
30638c2ecf20Sopenharmony_ci	 * getting confused after the PHY having been powered-down.
30648c2ecf20Sopenharmony_ci	 */
30658c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xFC28, 0x0000);
30668c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xFC2A, 0x0000);
30678c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xFC2C, 0x0000);
30688c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xFC2E, 0x0000);
30698c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xFC30, 0x0000);
30708c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xFC32, 0x0000);
30718c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xFC34, 0x0000);
30728c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xFC36, 0x0000);
30738c2ecf20Sopenharmony_ci	mdelay(3);
30748c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xFC26, 0x0000);
30758c2ecf20Sopenharmony_ci
30768c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF800, 0xE008);
30778c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF802, 0xE00A);
30788c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF804, 0xE00C);
30798c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF806, 0xE00E);
30808c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF808, 0xE027);
30818c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF80A, 0xE04F);
30828c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF80C, 0xE05E);
30838c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF80E, 0xE065);
30848c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF810, 0xC602);
30858c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF812, 0xBE00);
30868c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF814, 0x0000);
30878c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF816, 0xC502);
30888c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF818, 0xBD00);
30898c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF81A, 0x074C);
30908c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF81C, 0xC302);
30918c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF81E, 0xBB00);
30928c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF820, 0x080A);
30938c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF822, 0x6420);
30948c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF824, 0x48C2);
30958c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF826, 0x8C20);
30968c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF828, 0xC516);
30978c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF82A, 0x64A4);
30988c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF82C, 0x49C0);
30998c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF82E, 0xF009);
31008c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF830, 0x74A2);
31018c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF832, 0x8CA5);
31028c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF834, 0x74A0);
31038c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF836, 0xC50E);
31048c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF838, 0x9CA2);
31058c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF83A, 0x1C11);
31068c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF83C, 0x9CA0);
31078c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF83E, 0xE006);
31088c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF840, 0x74F8);
31098c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF842, 0x48C4);
31108c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF844, 0x8CF8);
31118c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF846, 0xC404);
31128c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF848, 0xBC00);
31138c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF84A, 0xC403);
31148c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF84C, 0xBC00);
31158c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF84E, 0x0BF2);
31168c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF850, 0x0C0A);
31178c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF852, 0xE434);
31188c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF854, 0xD3C0);
31198c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF856, 0x49D9);
31208c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF858, 0xF01F);
31218c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF85A, 0xC526);
31228c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF85C, 0x64A5);
31238c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF85E, 0x1400);
31248c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF860, 0xF007);
31258c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF862, 0x0C01);
31268c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF864, 0x8CA5);
31278c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF866, 0x1C15);
31288c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF868, 0xC51B);
31298c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF86A, 0x9CA0);
31308c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF86C, 0xE013);
31318c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF86E, 0xC519);
31328c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF870, 0x74A0);
31338c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF872, 0x48C4);
31348c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF874, 0x8CA0);
31358c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF876, 0xC516);
31368c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF878, 0x74A4);
31378c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF87A, 0x48C8);
31388c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF87C, 0x48CA);
31398c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF87E, 0x9CA4);
31408c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF880, 0xC512);
31418c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF882, 0x1B00);
31428c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF884, 0x9BA0);
31438c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF886, 0x1B1C);
31448c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF888, 0x483F);
31458c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF88A, 0x9BA2);
31468c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF88C, 0x1B04);
31478c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF88E, 0xC508);
31488c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF890, 0x9BA0);
31498c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF892, 0xC505);
31508c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF894, 0xBD00);
31518c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF896, 0xC502);
31528c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF898, 0xBD00);
31538c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF89A, 0x0300);
31548c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF89C, 0x051E);
31558c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF89E, 0xE434);
31568c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8A0, 0xE018);
31578c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8A2, 0xE092);
31588c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8A4, 0xDE20);
31598c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8A6, 0xD3C0);
31608c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8A8, 0xC50F);
31618c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8AA, 0x76A4);
31628c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8AC, 0x49E3);
31638c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8AE, 0xF007);
31648c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8B0, 0x49C0);
31658c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8B2, 0xF103);
31668c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8B4, 0xC607);
31678c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8B6, 0xBE00);
31688c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8B8, 0xC606);
31698c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8BA, 0xBE00);
31708c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8BC, 0xC602);
31718c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8BE, 0xBE00);
31728c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8C0, 0x0C4C);
31738c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8C2, 0x0C28);
31748c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8C4, 0x0C2C);
31758c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8C6, 0xDC00);
31768c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8C8, 0xC707);
31778c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8CA, 0x1D00);
31788c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8CC, 0x8DE2);
31798c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8CE, 0x48C1);
31808c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8D0, 0xC502);
31818c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8D2, 0xBD00);
31828c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8D4, 0x00AA);
31838c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8D6, 0xE0C0);
31848c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8D8, 0xC502);
31858c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8DA, 0xBD00);
31868c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xF8DC, 0x0132);
31878c2ecf20Sopenharmony_ci
31888c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xFC26, 0x8000);
31898c2ecf20Sopenharmony_ci
31908c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xFC2A, 0x0743);
31918c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xFC2C, 0x0801);
31928c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xFC2E, 0x0BE9);
31938c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xFC30, 0x02FD);
31948c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xFC32, 0x0C25);
31958c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xFC34, 0x00A9);
31968c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xFC36, 0x012D);
31978c2ecf20Sopenharmony_ci
31988c2ecf20Sopenharmony_ci	rtl_hw_aspm_clkreq_enable(tp, true);
31998c2ecf20Sopenharmony_ci}
32008c2ecf20Sopenharmony_ci
32018c2ecf20Sopenharmony_cistatic void rtl_hw_start_8168h_1(struct rtl8169_private *tp)
32028c2ecf20Sopenharmony_ci{
32038c2ecf20Sopenharmony_ci	static const struct ephy_info e_info_8168h_1[] = {
32048c2ecf20Sopenharmony_ci		{ 0x1e, 0x0800,	0x0001 },
32058c2ecf20Sopenharmony_ci		{ 0x1d, 0x0000,	0x0800 },
32068c2ecf20Sopenharmony_ci		{ 0x05, 0xffff,	0x2089 },
32078c2ecf20Sopenharmony_ci		{ 0x06, 0xffff,	0x5881 },
32088c2ecf20Sopenharmony_ci		{ 0x04, 0xffff,	0x854a },
32098c2ecf20Sopenharmony_ci		{ 0x01, 0xffff,	0x068b }
32108c2ecf20Sopenharmony_ci	};
32118c2ecf20Sopenharmony_ci	int rg_saw_cnt;
32128c2ecf20Sopenharmony_ci
32138c2ecf20Sopenharmony_ci	/* disable aspm and clock request before access ephy */
32148c2ecf20Sopenharmony_ci	rtl_hw_aspm_clkreq_enable(tp, false);
32158c2ecf20Sopenharmony_ci	rtl_ephy_init(tp, e_info_8168h_1);
32168c2ecf20Sopenharmony_ci
32178c2ecf20Sopenharmony_ci	rtl_set_fifo_size(tp, 0x08, 0x10, 0x02, 0x06);
32188c2ecf20Sopenharmony_ci	rtl8168g_set_pause_thresholds(tp, 0x38, 0x48);
32198c2ecf20Sopenharmony_ci
32208c2ecf20Sopenharmony_ci	rtl_set_def_aspm_entry_latency(tp);
32218c2ecf20Sopenharmony_ci
32228c2ecf20Sopenharmony_ci	rtl_reset_packet_filter(tp);
32238c2ecf20Sopenharmony_ci
32248c2ecf20Sopenharmony_ci	rtl_eri_set_bits(tp, 0xd4, 0x1f00);
32258c2ecf20Sopenharmony_ci	rtl_eri_set_bits(tp, 0xdc, 0x001c);
32268c2ecf20Sopenharmony_ci
32278c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0x5f0, ERIAR_MASK_0011, 0x4f87);
32288c2ecf20Sopenharmony_ci
32298c2ecf20Sopenharmony_ci	RTL_W32(tp, MISC, RTL_R32(tp, MISC) & ~RXDV_GATED_EN);
32308c2ecf20Sopenharmony_ci
32318c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000);
32328c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000);
32338c2ecf20Sopenharmony_ci
32348c2ecf20Sopenharmony_ci	rtl8168_config_eee_mac(tp);
32358c2ecf20Sopenharmony_ci
32368c2ecf20Sopenharmony_ci	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN);
32378c2ecf20Sopenharmony_ci	RTL_W8(tp, MISC_1, RTL_R8(tp, MISC_1) & ~PFM_D3COLD_EN);
32388c2ecf20Sopenharmony_ci
32398c2ecf20Sopenharmony_ci	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~TX_10M_PS_EN);
32408c2ecf20Sopenharmony_ci
32418c2ecf20Sopenharmony_ci	rtl_eri_clear_bits(tp, 0x1b0, BIT(12));
32428c2ecf20Sopenharmony_ci
32438c2ecf20Sopenharmony_ci	rtl_pcie_state_l2l3_disable(tp);
32448c2ecf20Sopenharmony_ci
32458c2ecf20Sopenharmony_ci	rg_saw_cnt = phy_read_paged(tp->phydev, 0x0c42, 0x13) & 0x3fff;
32468c2ecf20Sopenharmony_ci	if (rg_saw_cnt > 0) {
32478c2ecf20Sopenharmony_ci		u16 sw_cnt_1ms_ini;
32488c2ecf20Sopenharmony_ci
32498c2ecf20Sopenharmony_ci		sw_cnt_1ms_ini = 16000000/rg_saw_cnt;
32508c2ecf20Sopenharmony_ci		sw_cnt_1ms_ini &= 0x0fff;
32518c2ecf20Sopenharmony_ci		r8168_mac_ocp_modify(tp, 0xd412, 0x0fff, sw_cnt_1ms_ini);
32528c2ecf20Sopenharmony_ci	}
32538c2ecf20Sopenharmony_ci
32548c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xe056, 0x00f0, 0x0070);
32558c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xe052, 0x6000, 0x8008);
32568c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xe0d6, 0x01ff, 0x017f);
32578c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xd420, 0x0fff, 0x047f);
32588c2ecf20Sopenharmony_ci
32598c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xe63e, 0x0001);
32608c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xe63e, 0x0000);
32618c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xc094, 0x0000);
32628c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xc09e, 0x0000);
32638c2ecf20Sopenharmony_ci
32648c2ecf20Sopenharmony_ci	rtl_hw_aspm_clkreq_enable(tp, true);
32658c2ecf20Sopenharmony_ci}
32668c2ecf20Sopenharmony_ci
32678c2ecf20Sopenharmony_cistatic void rtl_hw_start_8168ep(struct rtl8169_private *tp)
32688c2ecf20Sopenharmony_ci{
32698c2ecf20Sopenharmony_ci	rtl8168ep_stop_cmac(tp);
32708c2ecf20Sopenharmony_ci
32718c2ecf20Sopenharmony_ci	rtl_set_fifo_size(tp, 0x08, 0x10, 0x02, 0x06);
32728c2ecf20Sopenharmony_ci	rtl8168g_set_pause_thresholds(tp, 0x2f, 0x5f);
32738c2ecf20Sopenharmony_ci
32748c2ecf20Sopenharmony_ci	rtl_set_def_aspm_entry_latency(tp);
32758c2ecf20Sopenharmony_ci
32768c2ecf20Sopenharmony_ci	rtl_reset_packet_filter(tp);
32778c2ecf20Sopenharmony_ci
32788c2ecf20Sopenharmony_ci	rtl_eri_set_bits(tp, 0xd4, 0x1f80);
32798c2ecf20Sopenharmony_ci
32808c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0x5f0, ERIAR_MASK_0011, 0x4f87);
32818c2ecf20Sopenharmony_ci
32828c2ecf20Sopenharmony_ci	RTL_W32(tp, MISC, RTL_R32(tp, MISC) & ~RXDV_GATED_EN);
32838c2ecf20Sopenharmony_ci
32848c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000);
32858c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000);
32868c2ecf20Sopenharmony_ci
32878c2ecf20Sopenharmony_ci	rtl8168_config_eee_mac(tp);
32888c2ecf20Sopenharmony_ci
32898c2ecf20Sopenharmony_ci	rtl_w0w1_eri(tp, 0x2fc, 0x01, 0x06);
32908c2ecf20Sopenharmony_ci
32918c2ecf20Sopenharmony_ci	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~TX_10M_PS_EN);
32928c2ecf20Sopenharmony_ci
32938c2ecf20Sopenharmony_ci	rtl_pcie_state_l2l3_disable(tp);
32948c2ecf20Sopenharmony_ci}
32958c2ecf20Sopenharmony_ci
32968c2ecf20Sopenharmony_cistatic void rtl_hw_start_8168ep_1(struct rtl8169_private *tp)
32978c2ecf20Sopenharmony_ci{
32988c2ecf20Sopenharmony_ci	static const struct ephy_info e_info_8168ep_1[] = {
32998c2ecf20Sopenharmony_ci		{ 0x00, 0xffff,	0x10ab },
33008c2ecf20Sopenharmony_ci		{ 0x06, 0xffff,	0xf030 },
33018c2ecf20Sopenharmony_ci		{ 0x08, 0xffff,	0x2006 },
33028c2ecf20Sopenharmony_ci		{ 0x0d, 0xffff,	0x1666 },
33038c2ecf20Sopenharmony_ci		{ 0x0c, 0x3ff0,	0x0000 }
33048c2ecf20Sopenharmony_ci	};
33058c2ecf20Sopenharmony_ci
33068c2ecf20Sopenharmony_ci	/* disable aspm and clock request before access ephy */
33078c2ecf20Sopenharmony_ci	rtl_hw_aspm_clkreq_enable(tp, false);
33088c2ecf20Sopenharmony_ci	rtl_ephy_init(tp, e_info_8168ep_1);
33098c2ecf20Sopenharmony_ci
33108c2ecf20Sopenharmony_ci	rtl_hw_start_8168ep(tp);
33118c2ecf20Sopenharmony_ci
33128c2ecf20Sopenharmony_ci	rtl_hw_aspm_clkreq_enable(tp, true);
33138c2ecf20Sopenharmony_ci}
33148c2ecf20Sopenharmony_ci
33158c2ecf20Sopenharmony_cistatic void rtl_hw_start_8168ep_2(struct rtl8169_private *tp)
33168c2ecf20Sopenharmony_ci{
33178c2ecf20Sopenharmony_ci	static const struct ephy_info e_info_8168ep_2[] = {
33188c2ecf20Sopenharmony_ci		{ 0x00, 0xffff,	0x10a3 },
33198c2ecf20Sopenharmony_ci		{ 0x19, 0xffff,	0xfc00 },
33208c2ecf20Sopenharmony_ci		{ 0x1e, 0xffff,	0x20ea }
33218c2ecf20Sopenharmony_ci	};
33228c2ecf20Sopenharmony_ci
33238c2ecf20Sopenharmony_ci	/* disable aspm and clock request before access ephy */
33248c2ecf20Sopenharmony_ci	rtl_hw_aspm_clkreq_enable(tp, false);
33258c2ecf20Sopenharmony_ci	rtl_ephy_init(tp, e_info_8168ep_2);
33268c2ecf20Sopenharmony_ci
33278c2ecf20Sopenharmony_ci	rtl_hw_start_8168ep(tp);
33288c2ecf20Sopenharmony_ci
33298c2ecf20Sopenharmony_ci	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN);
33308c2ecf20Sopenharmony_ci	RTL_W8(tp, MISC_1, RTL_R8(tp, MISC_1) & ~PFM_D3COLD_EN);
33318c2ecf20Sopenharmony_ci
33328c2ecf20Sopenharmony_ci	rtl_hw_aspm_clkreq_enable(tp, true);
33338c2ecf20Sopenharmony_ci}
33348c2ecf20Sopenharmony_ci
33358c2ecf20Sopenharmony_cistatic void rtl_hw_start_8168ep_3(struct rtl8169_private *tp)
33368c2ecf20Sopenharmony_ci{
33378c2ecf20Sopenharmony_ci	static const struct ephy_info e_info_8168ep_3[] = {
33388c2ecf20Sopenharmony_ci		{ 0x00, 0x0000,	0x0080 },
33398c2ecf20Sopenharmony_ci		{ 0x0d, 0x0100,	0x0200 },
33408c2ecf20Sopenharmony_ci		{ 0x19, 0x8021,	0x0000 },
33418c2ecf20Sopenharmony_ci		{ 0x1e, 0x0000,	0x2000 },
33428c2ecf20Sopenharmony_ci	};
33438c2ecf20Sopenharmony_ci
33448c2ecf20Sopenharmony_ci	/* disable aspm and clock request before access ephy */
33458c2ecf20Sopenharmony_ci	rtl_hw_aspm_clkreq_enable(tp, false);
33468c2ecf20Sopenharmony_ci	rtl_ephy_init(tp, e_info_8168ep_3);
33478c2ecf20Sopenharmony_ci
33488c2ecf20Sopenharmony_ci	rtl_hw_start_8168ep(tp);
33498c2ecf20Sopenharmony_ci
33508c2ecf20Sopenharmony_ci	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN);
33518c2ecf20Sopenharmony_ci	RTL_W8(tp, MISC_1, RTL_R8(tp, MISC_1) & ~PFM_D3COLD_EN);
33528c2ecf20Sopenharmony_ci
33538c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xd3e2, 0x0fff, 0x0271);
33548c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xd3e4, 0x00ff, 0x0000);
33558c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xe860, 0x0000, 0x0080);
33568c2ecf20Sopenharmony_ci
33578c2ecf20Sopenharmony_ci	rtl_hw_aspm_clkreq_enable(tp, true);
33588c2ecf20Sopenharmony_ci}
33598c2ecf20Sopenharmony_ci
33608c2ecf20Sopenharmony_cistatic void rtl_hw_start_8117(struct rtl8169_private *tp)
33618c2ecf20Sopenharmony_ci{
33628c2ecf20Sopenharmony_ci	static const struct ephy_info e_info_8117[] = {
33638c2ecf20Sopenharmony_ci		{ 0x19, 0x0040,	0x1100 },
33648c2ecf20Sopenharmony_ci		{ 0x59, 0x0040,	0x1100 },
33658c2ecf20Sopenharmony_ci	};
33668c2ecf20Sopenharmony_ci	int rg_saw_cnt;
33678c2ecf20Sopenharmony_ci
33688c2ecf20Sopenharmony_ci	rtl8168ep_stop_cmac(tp);
33698c2ecf20Sopenharmony_ci
33708c2ecf20Sopenharmony_ci	/* disable aspm and clock request before access ephy */
33718c2ecf20Sopenharmony_ci	rtl_hw_aspm_clkreq_enable(tp, false);
33728c2ecf20Sopenharmony_ci	rtl_ephy_init(tp, e_info_8117);
33738c2ecf20Sopenharmony_ci
33748c2ecf20Sopenharmony_ci	rtl_set_fifo_size(tp, 0x08, 0x10, 0x02, 0x06);
33758c2ecf20Sopenharmony_ci	rtl8168g_set_pause_thresholds(tp, 0x2f, 0x5f);
33768c2ecf20Sopenharmony_ci
33778c2ecf20Sopenharmony_ci	rtl_set_def_aspm_entry_latency(tp);
33788c2ecf20Sopenharmony_ci
33798c2ecf20Sopenharmony_ci	rtl_reset_packet_filter(tp);
33808c2ecf20Sopenharmony_ci
33818c2ecf20Sopenharmony_ci	rtl_eri_set_bits(tp, 0xd4, 0x1f90);
33828c2ecf20Sopenharmony_ci
33838c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0x5f0, ERIAR_MASK_0011, 0x4f87);
33848c2ecf20Sopenharmony_ci
33858c2ecf20Sopenharmony_ci	RTL_W32(tp, MISC, RTL_R32(tp, MISC) & ~RXDV_GATED_EN);
33868c2ecf20Sopenharmony_ci
33878c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000);
33888c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000);
33898c2ecf20Sopenharmony_ci
33908c2ecf20Sopenharmony_ci	rtl8168_config_eee_mac(tp);
33918c2ecf20Sopenharmony_ci
33928c2ecf20Sopenharmony_ci	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN);
33938c2ecf20Sopenharmony_ci	RTL_W8(tp, MISC_1, RTL_R8(tp, MISC_1) & ~PFM_D3COLD_EN);
33948c2ecf20Sopenharmony_ci
33958c2ecf20Sopenharmony_ci	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~TX_10M_PS_EN);
33968c2ecf20Sopenharmony_ci
33978c2ecf20Sopenharmony_ci	rtl_eri_clear_bits(tp, 0x1b0, BIT(12));
33988c2ecf20Sopenharmony_ci
33998c2ecf20Sopenharmony_ci	rtl_pcie_state_l2l3_disable(tp);
34008c2ecf20Sopenharmony_ci
34018c2ecf20Sopenharmony_ci	rg_saw_cnt = phy_read_paged(tp->phydev, 0x0c42, 0x13) & 0x3fff;
34028c2ecf20Sopenharmony_ci	if (rg_saw_cnt > 0) {
34038c2ecf20Sopenharmony_ci		u16 sw_cnt_1ms_ini;
34048c2ecf20Sopenharmony_ci
34058c2ecf20Sopenharmony_ci		sw_cnt_1ms_ini = (16000000 / rg_saw_cnt) & 0x0fff;
34068c2ecf20Sopenharmony_ci		r8168_mac_ocp_modify(tp, 0xd412, 0x0fff, sw_cnt_1ms_ini);
34078c2ecf20Sopenharmony_ci	}
34088c2ecf20Sopenharmony_ci
34098c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xe056, 0x00f0, 0x0070);
34108c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xea80, 0x0003);
34118c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xe052, 0x0000, 0x0009);
34128c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xd420, 0x0fff, 0x047f);
34138c2ecf20Sopenharmony_ci
34148c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xe63e, 0x0001);
34158c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xe63e, 0x0000);
34168c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xc094, 0x0000);
34178c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xc09e, 0x0000);
34188c2ecf20Sopenharmony_ci
34198c2ecf20Sopenharmony_ci	/* firmware is for MAC only */
34208c2ecf20Sopenharmony_ci	r8169_apply_firmware(tp);
34218c2ecf20Sopenharmony_ci
34228c2ecf20Sopenharmony_ci	rtl_hw_aspm_clkreq_enable(tp, true);
34238c2ecf20Sopenharmony_ci}
34248c2ecf20Sopenharmony_ci
34258c2ecf20Sopenharmony_cistatic void rtl_hw_start_8102e_1(struct rtl8169_private *tp)
34268c2ecf20Sopenharmony_ci{
34278c2ecf20Sopenharmony_ci	static const struct ephy_info e_info_8102e_1[] = {
34288c2ecf20Sopenharmony_ci		{ 0x01,	0, 0x6e65 },
34298c2ecf20Sopenharmony_ci		{ 0x02,	0, 0x091f },
34308c2ecf20Sopenharmony_ci		{ 0x03,	0, 0xc2f9 },
34318c2ecf20Sopenharmony_ci		{ 0x06,	0, 0xafb5 },
34328c2ecf20Sopenharmony_ci		{ 0x07,	0, 0x0e00 },
34338c2ecf20Sopenharmony_ci		{ 0x19,	0, 0xec80 },
34348c2ecf20Sopenharmony_ci		{ 0x01,	0, 0x2e65 },
34358c2ecf20Sopenharmony_ci		{ 0x01,	0, 0x6e65 }
34368c2ecf20Sopenharmony_ci	};
34378c2ecf20Sopenharmony_ci	u8 cfg1;
34388c2ecf20Sopenharmony_ci
34398c2ecf20Sopenharmony_ci	rtl_set_def_aspm_entry_latency(tp);
34408c2ecf20Sopenharmony_ci
34418c2ecf20Sopenharmony_ci	RTL_W8(tp, DBG_REG, FIX_NAK_1);
34428c2ecf20Sopenharmony_ci
34438c2ecf20Sopenharmony_ci	RTL_W8(tp, Config1,
34448c2ecf20Sopenharmony_ci	       LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable);
34458c2ecf20Sopenharmony_ci	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en);
34468c2ecf20Sopenharmony_ci
34478c2ecf20Sopenharmony_ci	cfg1 = RTL_R8(tp, Config1);
34488c2ecf20Sopenharmony_ci	if ((cfg1 & LEDS0) && (cfg1 & LEDS1))
34498c2ecf20Sopenharmony_ci		RTL_W8(tp, Config1, cfg1 & ~LEDS0);
34508c2ecf20Sopenharmony_ci
34518c2ecf20Sopenharmony_ci	rtl_ephy_init(tp, e_info_8102e_1);
34528c2ecf20Sopenharmony_ci}
34538c2ecf20Sopenharmony_ci
34548c2ecf20Sopenharmony_cistatic void rtl_hw_start_8102e_2(struct rtl8169_private *tp)
34558c2ecf20Sopenharmony_ci{
34568c2ecf20Sopenharmony_ci	rtl_set_def_aspm_entry_latency(tp);
34578c2ecf20Sopenharmony_ci
34588c2ecf20Sopenharmony_ci	RTL_W8(tp, Config1, MEMMAP | IOMAP | VPD | PMEnable);
34598c2ecf20Sopenharmony_ci	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en);
34608c2ecf20Sopenharmony_ci}
34618c2ecf20Sopenharmony_ci
34628c2ecf20Sopenharmony_cistatic void rtl_hw_start_8102e_3(struct rtl8169_private *tp)
34638c2ecf20Sopenharmony_ci{
34648c2ecf20Sopenharmony_ci	rtl_hw_start_8102e_2(tp);
34658c2ecf20Sopenharmony_ci
34668c2ecf20Sopenharmony_ci	rtl_ephy_write(tp, 0x03, 0xc2f9);
34678c2ecf20Sopenharmony_ci}
34688c2ecf20Sopenharmony_ci
34698c2ecf20Sopenharmony_cistatic void rtl_hw_start_8401(struct rtl8169_private *tp)
34708c2ecf20Sopenharmony_ci{
34718c2ecf20Sopenharmony_ci	static const struct ephy_info e_info_8401[] = {
34728c2ecf20Sopenharmony_ci		{ 0x01,	0xffff, 0x6fe5 },
34738c2ecf20Sopenharmony_ci		{ 0x03,	0xffff, 0x0599 },
34748c2ecf20Sopenharmony_ci		{ 0x06,	0xffff, 0xaf25 },
34758c2ecf20Sopenharmony_ci		{ 0x07,	0xffff, 0x8e68 },
34768c2ecf20Sopenharmony_ci	};
34778c2ecf20Sopenharmony_ci
34788c2ecf20Sopenharmony_ci	rtl_ephy_init(tp, e_info_8401);
34798c2ecf20Sopenharmony_ci	RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en);
34808c2ecf20Sopenharmony_ci}
34818c2ecf20Sopenharmony_ci
34828c2ecf20Sopenharmony_cistatic void rtl_hw_start_8105e_1(struct rtl8169_private *tp)
34838c2ecf20Sopenharmony_ci{
34848c2ecf20Sopenharmony_ci	static const struct ephy_info e_info_8105e_1[] = {
34858c2ecf20Sopenharmony_ci		{ 0x07,	0, 0x4000 },
34868c2ecf20Sopenharmony_ci		{ 0x19,	0, 0x0200 },
34878c2ecf20Sopenharmony_ci		{ 0x19,	0, 0x0020 },
34888c2ecf20Sopenharmony_ci		{ 0x1e,	0, 0x2000 },
34898c2ecf20Sopenharmony_ci		{ 0x03,	0, 0x0001 },
34908c2ecf20Sopenharmony_ci		{ 0x19,	0, 0x0100 },
34918c2ecf20Sopenharmony_ci		{ 0x19,	0, 0x0004 },
34928c2ecf20Sopenharmony_ci		{ 0x0a,	0, 0x0020 }
34938c2ecf20Sopenharmony_ci	};
34948c2ecf20Sopenharmony_ci
34958c2ecf20Sopenharmony_ci	/* Force LAN exit from ASPM if Rx/Tx are not idle */
34968c2ecf20Sopenharmony_ci	RTL_W32(tp, FuncEvent, RTL_R32(tp, FuncEvent) | 0x002800);
34978c2ecf20Sopenharmony_ci
34988c2ecf20Sopenharmony_ci	/* Disable Early Tally Counter */
34998c2ecf20Sopenharmony_ci	RTL_W32(tp, FuncEvent, RTL_R32(tp, FuncEvent) & ~0x010000);
35008c2ecf20Sopenharmony_ci
35018c2ecf20Sopenharmony_ci	RTL_W8(tp, MCU, RTL_R8(tp, MCU) | EN_NDP | EN_OOB_RESET);
35028c2ecf20Sopenharmony_ci	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) | PFM_EN);
35038c2ecf20Sopenharmony_ci
35048c2ecf20Sopenharmony_ci	rtl_ephy_init(tp, e_info_8105e_1);
35058c2ecf20Sopenharmony_ci
35068c2ecf20Sopenharmony_ci	rtl_pcie_state_l2l3_disable(tp);
35078c2ecf20Sopenharmony_ci}
35088c2ecf20Sopenharmony_ci
35098c2ecf20Sopenharmony_cistatic void rtl_hw_start_8105e_2(struct rtl8169_private *tp)
35108c2ecf20Sopenharmony_ci{
35118c2ecf20Sopenharmony_ci	rtl_hw_start_8105e_1(tp);
35128c2ecf20Sopenharmony_ci	rtl_ephy_write(tp, 0x1e, rtl_ephy_read(tp, 0x1e) | 0x8000);
35138c2ecf20Sopenharmony_ci}
35148c2ecf20Sopenharmony_ci
35158c2ecf20Sopenharmony_cistatic void rtl_hw_start_8402(struct rtl8169_private *tp)
35168c2ecf20Sopenharmony_ci{
35178c2ecf20Sopenharmony_ci	static const struct ephy_info e_info_8402[] = {
35188c2ecf20Sopenharmony_ci		{ 0x19,	0xffff, 0xff64 },
35198c2ecf20Sopenharmony_ci		{ 0x1e,	0, 0x4000 }
35208c2ecf20Sopenharmony_ci	};
35218c2ecf20Sopenharmony_ci
35228c2ecf20Sopenharmony_ci	rtl_set_def_aspm_entry_latency(tp);
35238c2ecf20Sopenharmony_ci
35248c2ecf20Sopenharmony_ci	/* Force LAN exit from ASPM if Rx/Tx are not idle */
35258c2ecf20Sopenharmony_ci	RTL_W32(tp, FuncEvent, RTL_R32(tp, FuncEvent) | 0x002800);
35268c2ecf20Sopenharmony_ci
35278c2ecf20Sopenharmony_ci	RTL_W8(tp, MCU, RTL_R8(tp, MCU) & ~NOW_IS_OOB);
35288c2ecf20Sopenharmony_ci
35298c2ecf20Sopenharmony_ci	rtl_ephy_init(tp, e_info_8402);
35308c2ecf20Sopenharmony_ci
35318c2ecf20Sopenharmony_ci	rtl_set_fifo_size(tp, 0x00, 0x00, 0x02, 0x06);
35328c2ecf20Sopenharmony_ci	rtl_reset_packet_filter(tp);
35338c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000);
35348c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000);
35358c2ecf20Sopenharmony_ci	rtl_w0w1_eri(tp, 0x0d4, 0x0e00, 0xff00);
35368c2ecf20Sopenharmony_ci
35378c2ecf20Sopenharmony_ci	/* disable EEE */
35388c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000);
35398c2ecf20Sopenharmony_ci
35408c2ecf20Sopenharmony_ci	rtl_pcie_state_l2l3_disable(tp);
35418c2ecf20Sopenharmony_ci}
35428c2ecf20Sopenharmony_ci
35438c2ecf20Sopenharmony_cistatic void rtl_hw_start_8106(struct rtl8169_private *tp)
35448c2ecf20Sopenharmony_ci{
35458c2ecf20Sopenharmony_ci	rtl_hw_aspm_clkreq_enable(tp, false);
35468c2ecf20Sopenharmony_ci
35478c2ecf20Sopenharmony_ci	/* Force LAN exit from ASPM if Rx/Tx are not idle */
35488c2ecf20Sopenharmony_ci	RTL_W32(tp, FuncEvent, RTL_R32(tp, FuncEvent) | 0x002800);
35498c2ecf20Sopenharmony_ci
35508c2ecf20Sopenharmony_ci	RTL_W32(tp, MISC, (RTL_R32(tp, MISC) | DISABLE_LAN_EN) & ~EARLY_TALLY_EN);
35518c2ecf20Sopenharmony_ci	RTL_W8(tp, MCU, RTL_R8(tp, MCU) | EN_NDP | EN_OOB_RESET);
35528c2ecf20Sopenharmony_ci	RTL_W8(tp, DLLPR, RTL_R8(tp, DLLPR) & ~PFM_EN);
35538c2ecf20Sopenharmony_ci
35548c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000);
35558c2ecf20Sopenharmony_ci
35568c2ecf20Sopenharmony_ci	/* disable EEE */
35578c2ecf20Sopenharmony_ci	rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000);
35588c2ecf20Sopenharmony_ci
35598c2ecf20Sopenharmony_ci	rtl_pcie_state_l2l3_disable(tp);
35608c2ecf20Sopenharmony_ci	rtl_hw_aspm_clkreq_enable(tp, true);
35618c2ecf20Sopenharmony_ci}
35628c2ecf20Sopenharmony_ci
35638c2ecf20Sopenharmony_ciDECLARE_RTL_COND(rtl_mac_ocp_e00e_cond)
35648c2ecf20Sopenharmony_ci{
35658c2ecf20Sopenharmony_ci	return r8168_mac_ocp_read(tp, 0xe00e) & BIT(13);
35668c2ecf20Sopenharmony_ci}
35678c2ecf20Sopenharmony_ci
35688c2ecf20Sopenharmony_cistatic void rtl_hw_start_8125_common(struct rtl8169_private *tp)
35698c2ecf20Sopenharmony_ci{
35708c2ecf20Sopenharmony_ci	rtl_pcie_state_l2l3_disable(tp);
35718c2ecf20Sopenharmony_ci
35728c2ecf20Sopenharmony_ci	RTL_W16(tp, 0x382, 0x221b);
35738c2ecf20Sopenharmony_ci	RTL_W8(tp, 0x4500, 0);
35748c2ecf20Sopenharmony_ci	RTL_W16(tp, 0x4800, 0);
35758c2ecf20Sopenharmony_ci
35768c2ecf20Sopenharmony_ci	/* disable UPS */
35778c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xd40a, 0x0010, 0x0000);
35788c2ecf20Sopenharmony_ci
35798c2ecf20Sopenharmony_ci	RTL_W8(tp, Config1, RTL_R8(tp, Config1) & ~0x10);
35808c2ecf20Sopenharmony_ci
35818c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xc140, 0xffff);
35828c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xc142, 0xffff);
35838c2ecf20Sopenharmony_ci
35848c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xd3e2, 0x0fff, 0x03a9);
35858c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xd3e4, 0x00ff, 0x0000);
35868c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xe860, 0x0000, 0x0080);
35878c2ecf20Sopenharmony_ci
35888c2ecf20Sopenharmony_ci	/* disable new tx descriptor format */
35898c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xeb58, 0x0001, 0x0000);
35908c2ecf20Sopenharmony_ci
35918c2ecf20Sopenharmony_ci	if (tp->mac_version == RTL_GIGA_MAC_VER_63)
35928c2ecf20Sopenharmony_ci		r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0200);
35938c2ecf20Sopenharmony_ci	else
35948c2ecf20Sopenharmony_ci		r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0400);
35958c2ecf20Sopenharmony_ci
35968c2ecf20Sopenharmony_ci	if (tp->mac_version == RTL_GIGA_MAC_VER_63)
35978c2ecf20Sopenharmony_ci		r8168_mac_ocp_modify(tp, 0xe63e, 0x0c30, 0x0000);
35988c2ecf20Sopenharmony_ci	else
35998c2ecf20Sopenharmony_ci		r8168_mac_ocp_modify(tp, 0xe63e, 0x0c30, 0x0020);
36008c2ecf20Sopenharmony_ci
36018c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xc0b4, 0x0000, 0x000c);
36028c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xeb6a, 0x00ff, 0x0033);
36038c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xeb50, 0x03e0, 0x0040);
36048c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xe056, 0x00f0, 0x0030);
36058c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xe040, 0x1000, 0x0000);
36068c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xea1c, 0x0003, 0x0001);
36078c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xe0c0, 0x4f0f, 0x4403);
36088c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xe052, 0x0080, 0x0068);
36098c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xc0ac, 0x0080, 0x1f00);
36108c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xd430, 0x0fff, 0x047f);
36118c2ecf20Sopenharmony_ci
36128c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xea1c, 0x0004, 0x0000);
36138c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xeb54, 0x0000, 0x0001);
36148c2ecf20Sopenharmony_ci	udelay(1);
36158c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xeb54, 0x0001, 0x0000);
36168c2ecf20Sopenharmony_ci	RTL_W16(tp, 0x1880, RTL_R16(tp, 0x1880) & ~0x0030);
36178c2ecf20Sopenharmony_ci
36188c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xe098, 0xc302);
36198c2ecf20Sopenharmony_ci
36208c2ecf20Sopenharmony_ci	rtl_loop_wait_low(tp, &rtl_mac_ocp_e00e_cond, 1000, 10);
36218c2ecf20Sopenharmony_ci
36228c2ecf20Sopenharmony_ci	if (tp->mac_version == RTL_GIGA_MAC_VER_63)
36238c2ecf20Sopenharmony_ci		rtl8125b_config_eee_mac(tp);
36248c2ecf20Sopenharmony_ci	else
36258c2ecf20Sopenharmony_ci		rtl8125a_config_eee_mac(tp);
36268c2ecf20Sopenharmony_ci
36278c2ecf20Sopenharmony_ci	RTL_W32(tp, MISC, RTL_R32(tp, MISC) & ~RXDV_GATED_EN);
36288c2ecf20Sopenharmony_ci	udelay(10);
36298c2ecf20Sopenharmony_ci}
36308c2ecf20Sopenharmony_ci
36318c2ecf20Sopenharmony_cistatic void rtl_hw_start_8125a_1(struct rtl8169_private *tp)
36328c2ecf20Sopenharmony_ci{
36338c2ecf20Sopenharmony_ci	static const struct ephy_info e_info_8125a_1[] = {
36348c2ecf20Sopenharmony_ci		{ 0x01, 0xffff, 0xa812 },
36358c2ecf20Sopenharmony_ci		{ 0x09, 0xffff, 0x520c },
36368c2ecf20Sopenharmony_ci		{ 0x04, 0xffff, 0xd000 },
36378c2ecf20Sopenharmony_ci		{ 0x0d, 0xffff, 0xf702 },
36388c2ecf20Sopenharmony_ci		{ 0x0a, 0xffff, 0x8653 },
36398c2ecf20Sopenharmony_ci		{ 0x06, 0xffff, 0x001e },
36408c2ecf20Sopenharmony_ci		{ 0x08, 0xffff, 0x3595 },
36418c2ecf20Sopenharmony_ci		{ 0x20, 0xffff, 0x9455 },
36428c2ecf20Sopenharmony_ci		{ 0x21, 0xffff, 0x99ff },
36438c2ecf20Sopenharmony_ci		{ 0x02, 0xffff, 0x6046 },
36448c2ecf20Sopenharmony_ci		{ 0x29, 0xffff, 0xfe00 },
36458c2ecf20Sopenharmony_ci		{ 0x23, 0xffff, 0xab62 },
36468c2ecf20Sopenharmony_ci
36478c2ecf20Sopenharmony_ci		{ 0x41, 0xffff, 0xa80c },
36488c2ecf20Sopenharmony_ci		{ 0x49, 0xffff, 0x520c },
36498c2ecf20Sopenharmony_ci		{ 0x44, 0xffff, 0xd000 },
36508c2ecf20Sopenharmony_ci		{ 0x4d, 0xffff, 0xf702 },
36518c2ecf20Sopenharmony_ci		{ 0x4a, 0xffff, 0x8653 },
36528c2ecf20Sopenharmony_ci		{ 0x46, 0xffff, 0x001e },
36538c2ecf20Sopenharmony_ci		{ 0x48, 0xffff, 0x3595 },
36548c2ecf20Sopenharmony_ci		{ 0x60, 0xffff, 0x9455 },
36558c2ecf20Sopenharmony_ci		{ 0x61, 0xffff, 0x99ff },
36568c2ecf20Sopenharmony_ci		{ 0x42, 0xffff, 0x6046 },
36578c2ecf20Sopenharmony_ci		{ 0x69, 0xffff, 0xfe00 },
36588c2ecf20Sopenharmony_ci		{ 0x63, 0xffff, 0xab62 },
36598c2ecf20Sopenharmony_ci	};
36608c2ecf20Sopenharmony_ci
36618c2ecf20Sopenharmony_ci	rtl_set_def_aspm_entry_latency(tp);
36628c2ecf20Sopenharmony_ci
36638c2ecf20Sopenharmony_ci	/* disable aspm and clock request before access ephy */
36648c2ecf20Sopenharmony_ci	rtl_hw_aspm_clkreq_enable(tp, false);
36658c2ecf20Sopenharmony_ci	rtl_ephy_init(tp, e_info_8125a_1);
36668c2ecf20Sopenharmony_ci
36678c2ecf20Sopenharmony_ci	rtl_hw_start_8125_common(tp);
36688c2ecf20Sopenharmony_ci	rtl_hw_aspm_clkreq_enable(tp, true);
36698c2ecf20Sopenharmony_ci}
36708c2ecf20Sopenharmony_ci
36718c2ecf20Sopenharmony_cistatic void rtl_hw_start_8125a_2(struct rtl8169_private *tp)
36728c2ecf20Sopenharmony_ci{
36738c2ecf20Sopenharmony_ci	static const struct ephy_info e_info_8125a_2[] = {
36748c2ecf20Sopenharmony_ci		{ 0x04, 0xffff, 0xd000 },
36758c2ecf20Sopenharmony_ci		{ 0x0a, 0xffff, 0x8653 },
36768c2ecf20Sopenharmony_ci		{ 0x23, 0xffff, 0xab66 },
36778c2ecf20Sopenharmony_ci		{ 0x20, 0xffff, 0x9455 },
36788c2ecf20Sopenharmony_ci		{ 0x21, 0xffff, 0x99ff },
36798c2ecf20Sopenharmony_ci		{ 0x29, 0xffff, 0xfe04 },
36808c2ecf20Sopenharmony_ci
36818c2ecf20Sopenharmony_ci		{ 0x44, 0xffff, 0xd000 },
36828c2ecf20Sopenharmony_ci		{ 0x4a, 0xffff, 0x8653 },
36838c2ecf20Sopenharmony_ci		{ 0x63, 0xffff, 0xab66 },
36848c2ecf20Sopenharmony_ci		{ 0x60, 0xffff, 0x9455 },
36858c2ecf20Sopenharmony_ci		{ 0x61, 0xffff, 0x99ff },
36868c2ecf20Sopenharmony_ci		{ 0x69, 0xffff, 0xfe04 },
36878c2ecf20Sopenharmony_ci	};
36888c2ecf20Sopenharmony_ci
36898c2ecf20Sopenharmony_ci	rtl_set_def_aspm_entry_latency(tp);
36908c2ecf20Sopenharmony_ci
36918c2ecf20Sopenharmony_ci	/* disable aspm and clock request before access ephy */
36928c2ecf20Sopenharmony_ci	rtl_hw_aspm_clkreq_enable(tp, false);
36938c2ecf20Sopenharmony_ci	rtl_ephy_init(tp, e_info_8125a_2);
36948c2ecf20Sopenharmony_ci
36958c2ecf20Sopenharmony_ci	rtl_hw_start_8125_common(tp);
36968c2ecf20Sopenharmony_ci	rtl_hw_aspm_clkreq_enable(tp, true);
36978c2ecf20Sopenharmony_ci}
36988c2ecf20Sopenharmony_ci
36998c2ecf20Sopenharmony_cistatic void rtl_hw_start_8125b(struct rtl8169_private *tp)
37008c2ecf20Sopenharmony_ci{
37018c2ecf20Sopenharmony_ci	static const struct ephy_info e_info_8125b[] = {
37028c2ecf20Sopenharmony_ci		{ 0x0b, 0xffff, 0xa908 },
37038c2ecf20Sopenharmony_ci		{ 0x1e, 0xffff, 0x20eb },
37048c2ecf20Sopenharmony_ci		{ 0x4b, 0xffff, 0xa908 },
37058c2ecf20Sopenharmony_ci		{ 0x5e, 0xffff, 0x20eb },
37068c2ecf20Sopenharmony_ci		{ 0x22, 0x0030, 0x0020 },
37078c2ecf20Sopenharmony_ci		{ 0x62, 0x0030, 0x0020 },
37088c2ecf20Sopenharmony_ci	};
37098c2ecf20Sopenharmony_ci
37108c2ecf20Sopenharmony_ci	rtl_set_def_aspm_entry_latency(tp);
37118c2ecf20Sopenharmony_ci	rtl_hw_aspm_clkreq_enable(tp, false);
37128c2ecf20Sopenharmony_ci
37138c2ecf20Sopenharmony_ci	rtl_ephy_init(tp, e_info_8125b);
37148c2ecf20Sopenharmony_ci	rtl_hw_start_8125_common(tp);
37158c2ecf20Sopenharmony_ci
37168c2ecf20Sopenharmony_ci	rtl_hw_aspm_clkreq_enable(tp, true);
37178c2ecf20Sopenharmony_ci}
37188c2ecf20Sopenharmony_ci
37198c2ecf20Sopenharmony_cistatic void rtl_hw_config(struct rtl8169_private *tp)
37208c2ecf20Sopenharmony_ci{
37218c2ecf20Sopenharmony_ci	static const rtl_generic_fct hw_configs[] = {
37228c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_07] = rtl_hw_start_8102e_1,
37238c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_08] = rtl_hw_start_8102e_3,
37248c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_09] = rtl_hw_start_8102e_2,
37258c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_10] = NULL,
37268c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_11] = rtl_hw_start_8168b,
37278c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_12] = rtl_hw_start_8168b,
37288c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_13] = NULL,
37298c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_14] = rtl_hw_start_8401,
37308c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_16] = NULL,
37318c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_17] = rtl_hw_start_8168b,
37328c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_18] = rtl_hw_start_8168cp_1,
37338c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_19] = rtl_hw_start_8168c_1,
37348c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_20] = rtl_hw_start_8168c_2,
37358c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_21] = rtl_hw_start_8168c_3,
37368c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_22] = rtl_hw_start_8168c_4,
37378c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_23] = rtl_hw_start_8168cp_2,
37388c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_24] = rtl_hw_start_8168cp_3,
37398c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_25] = rtl_hw_start_8168d,
37408c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_26] = rtl_hw_start_8168d,
37418c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_27] = rtl_hw_start_8168d,
37428c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_28] = rtl_hw_start_8168d_4,
37438c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_29] = rtl_hw_start_8105e_1,
37448c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_30] = rtl_hw_start_8105e_2,
37458c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_31] = rtl_hw_start_8168d,
37468c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_32] = rtl_hw_start_8168e_1,
37478c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_33] = rtl_hw_start_8168e_1,
37488c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_34] = rtl_hw_start_8168e_2,
37498c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_35] = rtl_hw_start_8168f_1,
37508c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_36] = rtl_hw_start_8168f_1,
37518c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_37] = rtl_hw_start_8402,
37528c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_38] = rtl_hw_start_8411,
37538c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_39] = rtl_hw_start_8106,
37548c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_40] = rtl_hw_start_8168g_1,
37558c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_41] = rtl_hw_start_8168g_1,
37568c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_42] = rtl_hw_start_8168g_2,
37578c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_43] = rtl_hw_start_8168g_2,
37588c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_44] = rtl_hw_start_8411_2,
37598c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_45] = rtl_hw_start_8168h_1,
37608c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_46] = rtl_hw_start_8168h_1,
37618c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_47] = rtl_hw_start_8168h_1,
37628c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_48] = rtl_hw_start_8168h_1,
37638c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_49] = rtl_hw_start_8168ep_1,
37648c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_50] = rtl_hw_start_8168ep_2,
37658c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_51] = rtl_hw_start_8168ep_3,
37668c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_52] = rtl_hw_start_8117,
37678c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_60] = rtl_hw_start_8125a_1,
37688c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_61] = rtl_hw_start_8125a_2,
37698c2ecf20Sopenharmony_ci		[RTL_GIGA_MAC_VER_63] = rtl_hw_start_8125b,
37708c2ecf20Sopenharmony_ci	};
37718c2ecf20Sopenharmony_ci
37728c2ecf20Sopenharmony_ci	if (hw_configs[tp->mac_version])
37738c2ecf20Sopenharmony_ci		hw_configs[tp->mac_version](tp);
37748c2ecf20Sopenharmony_ci}
37758c2ecf20Sopenharmony_ci
37768c2ecf20Sopenharmony_cistatic void rtl_hw_start_8125(struct rtl8169_private *tp)
37778c2ecf20Sopenharmony_ci{
37788c2ecf20Sopenharmony_ci	int i;
37798c2ecf20Sopenharmony_ci
37808c2ecf20Sopenharmony_ci	/* disable interrupt coalescing */
37818c2ecf20Sopenharmony_ci	for (i = 0xa00; i < 0xb00; i += 4)
37828c2ecf20Sopenharmony_ci		RTL_W32(tp, i, 0);
37838c2ecf20Sopenharmony_ci
37848c2ecf20Sopenharmony_ci	rtl_hw_config(tp);
37858c2ecf20Sopenharmony_ci}
37868c2ecf20Sopenharmony_ci
37878c2ecf20Sopenharmony_cistatic void rtl_hw_start_8168(struct rtl8169_private *tp)
37888c2ecf20Sopenharmony_ci{
37898c2ecf20Sopenharmony_ci	if (rtl_is_8168evl_up(tp))
37908c2ecf20Sopenharmony_ci		RTL_W8(tp, MaxTxPacketSize, EarlySize);
37918c2ecf20Sopenharmony_ci	else
37928c2ecf20Sopenharmony_ci		RTL_W8(tp, MaxTxPacketSize, TxPacketMax);
37938c2ecf20Sopenharmony_ci
37948c2ecf20Sopenharmony_ci	rtl_hw_config(tp);
37958c2ecf20Sopenharmony_ci
37968c2ecf20Sopenharmony_ci	/* disable interrupt coalescing */
37978c2ecf20Sopenharmony_ci	RTL_W16(tp, IntrMitigate, 0x0000);
37988c2ecf20Sopenharmony_ci}
37998c2ecf20Sopenharmony_ci
38008c2ecf20Sopenharmony_cistatic void rtl_hw_start_8169(struct rtl8169_private *tp)
38018c2ecf20Sopenharmony_ci{
38028c2ecf20Sopenharmony_ci	RTL_W8(tp, EarlyTxThres, NoEarlyTx);
38038c2ecf20Sopenharmony_ci
38048c2ecf20Sopenharmony_ci	tp->cp_cmd |= PCIMulRW;
38058c2ecf20Sopenharmony_ci
38068c2ecf20Sopenharmony_ci	if (tp->mac_version == RTL_GIGA_MAC_VER_02 ||
38078c2ecf20Sopenharmony_ci	    tp->mac_version == RTL_GIGA_MAC_VER_03)
38088c2ecf20Sopenharmony_ci		tp->cp_cmd |= EnAnaPLL;
38098c2ecf20Sopenharmony_ci
38108c2ecf20Sopenharmony_ci	RTL_W16(tp, CPlusCmd, tp->cp_cmd);
38118c2ecf20Sopenharmony_ci
38128c2ecf20Sopenharmony_ci	rtl8169_set_magic_reg(tp);
38138c2ecf20Sopenharmony_ci
38148c2ecf20Sopenharmony_ci	/* disable interrupt coalescing */
38158c2ecf20Sopenharmony_ci	RTL_W16(tp, IntrMitigate, 0x0000);
38168c2ecf20Sopenharmony_ci}
38178c2ecf20Sopenharmony_ci
38188c2ecf20Sopenharmony_cistatic void rtl_hw_start(struct  rtl8169_private *tp)
38198c2ecf20Sopenharmony_ci{
38208c2ecf20Sopenharmony_ci	rtl_unlock_config_regs(tp);
38218c2ecf20Sopenharmony_ci
38228c2ecf20Sopenharmony_ci	RTL_W16(tp, CPlusCmd, tp->cp_cmd);
38238c2ecf20Sopenharmony_ci
38248c2ecf20Sopenharmony_ci	if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
38258c2ecf20Sopenharmony_ci		rtl_hw_start_8169(tp);
38268c2ecf20Sopenharmony_ci	else if (rtl_is_8125(tp))
38278c2ecf20Sopenharmony_ci		rtl_hw_start_8125(tp);
38288c2ecf20Sopenharmony_ci	else
38298c2ecf20Sopenharmony_ci		rtl_hw_start_8168(tp);
38308c2ecf20Sopenharmony_ci
38318c2ecf20Sopenharmony_ci	rtl_set_rx_max_size(tp);
38328c2ecf20Sopenharmony_ci	rtl_set_rx_tx_desc_registers(tp);
38338c2ecf20Sopenharmony_ci	rtl_lock_config_regs(tp);
38348c2ecf20Sopenharmony_ci
38358c2ecf20Sopenharmony_ci	rtl_jumbo_config(tp);
38368c2ecf20Sopenharmony_ci
38378c2ecf20Sopenharmony_ci	/* Initially a 10 us delay. Turned it into a PCI commit. - FR */
38388c2ecf20Sopenharmony_ci	rtl_pci_commit(tp);
38398c2ecf20Sopenharmony_ci
38408c2ecf20Sopenharmony_ci	RTL_W8(tp, ChipCmd, CmdTxEnb | CmdRxEnb);
38418c2ecf20Sopenharmony_ci	rtl_init_rxcfg(tp);
38428c2ecf20Sopenharmony_ci	rtl_set_tx_config_registers(tp);
38438c2ecf20Sopenharmony_ci	rtl_set_rx_config_features(tp, tp->dev->features);
38448c2ecf20Sopenharmony_ci	rtl_set_rx_mode(tp->dev);
38458c2ecf20Sopenharmony_ci	rtl_irq_enable(tp);
38468c2ecf20Sopenharmony_ci}
38478c2ecf20Sopenharmony_ci
38488c2ecf20Sopenharmony_cistatic int rtl8169_change_mtu(struct net_device *dev, int new_mtu)
38498c2ecf20Sopenharmony_ci{
38508c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = netdev_priv(dev);
38518c2ecf20Sopenharmony_ci
38528c2ecf20Sopenharmony_ci	dev->mtu = new_mtu;
38538c2ecf20Sopenharmony_ci	netdev_update_features(dev);
38548c2ecf20Sopenharmony_ci	rtl_jumbo_config(tp);
38558c2ecf20Sopenharmony_ci
38568c2ecf20Sopenharmony_ci	switch (tp->mac_version) {
38578c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_61:
38588c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_63:
38598c2ecf20Sopenharmony_ci		rtl8125_set_eee_txidle_timer(tp);
38608c2ecf20Sopenharmony_ci		break;
38618c2ecf20Sopenharmony_ci	default:
38628c2ecf20Sopenharmony_ci		break;
38638c2ecf20Sopenharmony_ci	}
38648c2ecf20Sopenharmony_ci
38658c2ecf20Sopenharmony_ci	return 0;
38668c2ecf20Sopenharmony_ci}
38678c2ecf20Sopenharmony_ci
38688c2ecf20Sopenharmony_cistatic void rtl8169_mark_to_asic(struct RxDesc *desc)
38698c2ecf20Sopenharmony_ci{
38708c2ecf20Sopenharmony_ci	u32 eor = le32_to_cpu(desc->opts1) & RingEnd;
38718c2ecf20Sopenharmony_ci
38728c2ecf20Sopenharmony_ci	desc->opts2 = 0;
38738c2ecf20Sopenharmony_ci	/* Force memory writes to complete before releasing descriptor */
38748c2ecf20Sopenharmony_ci	dma_wmb();
38758c2ecf20Sopenharmony_ci	WRITE_ONCE(desc->opts1, cpu_to_le32(DescOwn | eor | R8169_RX_BUF_SIZE));
38768c2ecf20Sopenharmony_ci}
38778c2ecf20Sopenharmony_ci
38788c2ecf20Sopenharmony_cistatic struct page *rtl8169_alloc_rx_data(struct rtl8169_private *tp,
38798c2ecf20Sopenharmony_ci					  struct RxDesc *desc)
38808c2ecf20Sopenharmony_ci{
38818c2ecf20Sopenharmony_ci	struct device *d = tp_to_dev(tp);
38828c2ecf20Sopenharmony_ci	int node = dev_to_node(d);
38838c2ecf20Sopenharmony_ci	dma_addr_t mapping;
38848c2ecf20Sopenharmony_ci	struct page *data;
38858c2ecf20Sopenharmony_ci
38868c2ecf20Sopenharmony_ci	data = alloc_pages_node(node, GFP_KERNEL, get_order(R8169_RX_BUF_SIZE));
38878c2ecf20Sopenharmony_ci	if (!data)
38888c2ecf20Sopenharmony_ci		return NULL;
38898c2ecf20Sopenharmony_ci
38908c2ecf20Sopenharmony_ci	mapping = dma_map_page(d, data, 0, R8169_RX_BUF_SIZE, DMA_FROM_DEVICE);
38918c2ecf20Sopenharmony_ci	if (unlikely(dma_mapping_error(d, mapping))) {
38928c2ecf20Sopenharmony_ci		netdev_err(tp->dev, "Failed to map RX DMA!\n");
38938c2ecf20Sopenharmony_ci		__free_pages(data, get_order(R8169_RX_BUF_SIZE));
38948c2ecf20Sopenharmony_ci		return NULL;
38958c2ecf20Sopenharmony_ci	}
38968c2ecf20Sopenharmony_ci
38978c2ecf20Sopenharmony_ci	desc->addr = cpu_to_le64(mapping);
38988c2ecf20Sopenharmony_ci	rtl8169_mark_to_asic(desc);
38998c2ecf20Sopenharmony_ci
39008c2ecf20Sopenharmony_ci	return data;
39018c2ecf20Sopenharmony_ci}
39028c2ecf20Sopenharmony_ci
39038c2ecf20Sopenharmony_cistatic void rtl8169_rx_clear(struct rtl8169_private *tp)
39048c2ecf20Sopenharmony_ci{
39058c2ecf20Sopenharmony_ci	unsigned int i;
39068c2ecf20Sopenharmony_ci
39078c2ecf20Sopenharmony_ci	for (i = 0; i < NUM_RX_DESC && tp->Rx_databuff[i]; i++) {
39088c2ecf20Sopenharmony_ci		dma_unmap_page(tp_to_dev(tp),
39098c2ecf20Sopenharmony_ci			       le64_to_cpu(tp->RxDescArray[i].addr),
39108c2ecf20Sopenharmony_ci			       R8169_RX_BUF_SIZE, DMA_FROM_DEVICE);
39118c2ecf20Sopenharmony_ci		__free_pages(tp->Rx_databuff[i], get_order(R8169_RX_BUF_SIZE));
39128c2ecf20Sopenharmony_ci		tp->Rx_databuff[i] = NULL;
39138c2ecf20Sopenharmony_ci		tp->RxDescArray[i].addr = 0;
39148c2ecf20Sopenharmony_ci		tp->RxDescArray[i].opts1 = 0;
39158c2ecf20Sopenharmony_ci	}
39168c2ecf20Sopenharmony_ci}
39178c2ecf20Sopenharmony_ci
39188c2ecf20Sopenharmony_cistatic int rtl8169_rx_fill(struct rtl8169_private *tp)
39198c2ecf20Sopenharmony_ci{
39208c2ecf20Sopenharmony_ci	unsigned int i;
39218c2ecf20Sopenharmony_ci
39228c2ecf20Sopenharmony_ci	for (i = 0; i < NUM_RX_DESC; i++) {
39238c2ecf20Sopenharmony_ci		struct page *data;
39248c2ecf20Sopenharmony_ci
39258c2ecf20Sopenharmony_ci		data = rtl8169_alloc_rx_data(tp, tp->RxDescArray + i);
39268c2ecf20Sopenharmony_ci		if (!data) {
39278c2ecf20Sopenharmony_ci			rtl8169_rx_clear(tp);
39288c2ecf20Sopenharmony_ci			return -ENOMEM;
39298c2ecf20Sopenharmony_ci		}
39308c2ecf20Sopenharmony_ci		tp->Rx_databuff[i] = data;
39318c2ecf20Sopenharmony_ci	}
39328c2ecf20Sopenharmony_ci
39338c2ecf20Sopenharmony_ci	/* mark as last descriptor in the ring */
39348c2ecf20Sopenharmony_ci	tp->RxDescArray[NUM_RX_DESC - 1].opts1 |= cpu_to_le32(RingEnd);
39358c2ecf20Sopenharmony_ci
39368c2ecf20Sopenharmony_ci	return 0;
39378c2ecf20Sopenharmony_ci}
39388c2ecf20Sopenharmony_ci
39398c2ecf20Sopenharmony_cistatic int rtl8169_init_ring(struct rtl8169_private *tp)
39408c2ecf20Sopenharmony_ci{
39418c2ecf20Sopenharmony_ci	rtl8169_init_ring_indexes(tp);
39428c2ecf20Sopenharmony_ci
39438c2ecf20Sopenharmony_ci	memset(tp->tx_skb, 0, sizeof(tp->tx_skb));
39448c2ecf20Sopenharmony_ci	memset(tp->Rx_databuff, 0, sizeof(tp->Rx_databuff));
39458c2ecf20Sopenharmony_ci
39468c2ecf20Sopenharmony_ci	return rtl8169_rx_fill(tp);
39478c2ecf20Sopenharmony_ci}
39488c2ecf20Sopenharmony_ci
39498c2ecf20Sopenharmony_cistatic void rtl8169_unmap_tx_skb(struct rtl8169_private *tp, unsigned int entry)
39508c2ecf20Sopenharmony_ci{
39518c2ecf20Sopenharmony_ci	struct ring_info *tx_skb = tp->tx_skb + entry;
39528c2ecf20Sopenharmony_ci	struct TxDesc *desc = tp->TxDescArray + entry;
39538c2ecf20Sopenharmony_ci
39548c2ecf20Sopenharmony_ci	dma_unmap_single(tp_to_dev(tp), le64_to_cpu(desc->addr), tx_skb->len,
39558c2ecf20Sopenharmony_ci			 DMA_TO_DEVICE);
39568c2ecf20Sopenharmony_ci	memset(desc, 0, sizeof(*desc));
39578c2ecf20Sopenharmony_ci	memset(tx_skb, 0, sizeof(*tx_skb));
39588c2ecf20Sopenharmony_ci}
39598c2ecf20Sopenharmony_ci
39608c2ecf20Sopenharmony_cistatic void rtl8169_tx_clear_range(struct rtl8169_private *tp, u32 start,
39618c2ecf20Sopenharmony_ci				   unsigned int n)
39628c2ecf20Sopenharmony_ci{
39638c2ecf20Sopenharmony_ci	unsigned int i;
39648c2ecf20Sopenharmony_ci
39658c2ecf20Sopenharmony_ci	for (i = 0; i < n; i++) {
39668c2ecf20Sopenharmony_ci		unsigned int entry = (start + i) % NUM_TX_DESC;
39678c2ecf20Sopenharmony_ci		struct ring_info *tx_skb = tp->tx_skb + entry;
39688c2ecf20Sopenharmony_ci		unsigned int len = tx_skb->len;
39698c2ecf20Sopenharmony_ci
39708c2ecf20Sopenharmony_ci		if (len) {
39718c2ecf20Sopenharmony_ci			struct sk_buff *skb = tx_skb->skb;
39728c2ecf20Sopenharmony_ci
39738c2ecf20Sopenharmony_ci			rtl8169_unmap_tx_skb(tp, entry);
39748c2ecf20Sopenharmony_ci			if (skb)
39758c2ecf20Sopenharmony_ci				dev_consume_skb_any(skb);
39768c2ecf20Sopenharmony_ci		}
39778c2ecf20Sopenharmony_ci	}
39788c2ecf20Sopenharmony_ci}
39798c2ecf20Sopenharmony_ci
39808c2ecf20Sopenharmony_cistatic void rtl8169_tx_clear(struct rtl8169_private *tp)
39818c2ecf20Sopenharmony_ci{
39828c2ecf20Sopenharmony_ci	rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC);
39838c2ecf20Sopenharmony_ci	netdev_reset_queue(tp->dev);
39848c2ecf20Sopenharmony_ci}
39858c2ecf20Sopenharmony_ci
39868c2ecf20Sopenharmony_cistatic void rtl8169_cleanup(struct rtl8169_private *tp, bool going_down)
39878c2ecf20Sopenharmony_ci{
39888c2ecf20Sopenharmony_ci	napi_disable(&tp->napi);
39898c2ecf20Sopenharmony_ci
39908c2ecf20Sopenharmony_ci	/* Give a racing hard_start_xmit a few cycles to complete. */
39918c2ecf20Sopenharmony_ci	synchronize_net();
39928c2ecf20Sopenharmony_ci
39938c2ecf20Sopenharmony_ci	/* Disable interrupts */
39948c2ecf20Sopenharmony_ci	rtl8169_irq_mask_and_ack(tp);
39958c2ecf20Sopenharmony_ci
39968c2ecf20Sopenharmony_ci	rtl_rx_close(tp);
39978c2ecf20Sopenharmony_ci
39988c2ecf20Sopenharmony_ci	if (going_down && tp->dev->wol_enabled)
39998c2ecf20Sopenharmony_ci		goto no_reset;
40008c2ecf20Sopenharmony_ci
40018c2ecf20Sopenharmony_ci	switch (tp->mac_version) {
40028c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_27:
40038c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_28:
40048c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_31:
40058c2ecf20Sopenharmony_ci		rtl_loop_wait_low(tp, &rtl_npq_cond, 20, 2000);
40068c2ecf20Sopenharmony_ci		break;
40078c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_38:
40088c2ecf20Sopenharmony_ci		RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq);
40098c2ecf20Sopenharmony_ci		rtl_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666);
40108c2ecf20Sopenharmony_ci		break;
40118c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_63:
40128c2ecf20Sopenharmony_ci		rtl_enable_rxdvgate(tp);
40138c2ecf20Sopenharmony_ci		fsleep(2000);
40148c2ecf20Sopenharmony_ci		break;
40158c2ecf20Sopenharmony_ci	default:
40168c2ecf20Sopenharmony_ci		RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq);
40178c2ecf20Sopenharmony_ci		fsleep(100);
40188c2ecf20Sopenharmony_ci		break;
40198c2ecf20Sopenharmony_ci	}
40208c2ecf20Sopenharmony_ci
40218c2ecf20Sopenharmony_ci	rtl_hw_reset(tp);
40228c2ecf20Sopenharmony_cino_reset:
40238c2ecf20Sopenharmony_ci	rtl8169_tx_clear(tp);
40248c2ecf20Sopenharmony_ci	rtl8169_init_ring_indexes(tp);
40258c2ecf20Sopenharmony_ci}
40268c2ecf20Sopenharmony_ci
40278c2ecf20Sopenharmony_cistatic void rtl_reset_work(struct rtl8169_private *tp)
40288c2ecf20Sopenharmony_ci{
40298c2ecf20Sopenharmony_ci	int i;
40308c2ecf20Sopenharmony_ci
40318c2ecf20Sopenharmony_ci	netif_stop_queue(tp->dev);
40328c2ecf20Sopenharmony_ci
40338c2ecf20Sopenharmony_ci	rtl8169_cleanup(tp, false);
40348c2ecf20Sopenharmony_ci
40358c2ecf20Sopenharmony_ci	for (i = 0; i < NUM_RX_DESC; i++)
40368c2ecf20Sopenharmony_ci		rtl8169_mark_to_asic(tp->RxDescArray + i);
40378c2ecf20Sopenharmony_ci
40388c2ecf20Sopenharmony_ci	napi_enable(&tp->napi);
40398c2ecf20Sopenharmony_ci	rtl_hw_start(tp);
40408c2ecf20Sopenharmony_ci}
40418c2ecf20Sopenharmony_ci
40428c2ecf20Sopenharmony_cistatic void rtl8169_tx_timeout(struct net_device *dev, unsigned int txqueue)
40438c2ecf20Sopenharmony_ci{
40448c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = netdev_priv(dev);
40458c2ecf20Sopenharmony_ci
40468c2ecf20Sopenharmony_ci	rtl_schedule_task(tp, RTL_FLAG_TASK_TX_TIMEOUT);
40478c2ecf20Sopenharmony_ci}
40488c2ecf20Sopenharmony_ci
40498c2ecf20Sopenharmony_cistatic int rtl8169_tx_map(struct rtl8169_private *tp, const u32 *opts, u32 len,
40508c2ecf20Sopenharmony_ci			  void *addr, unsigned int entry, bool desc_own)
40518c2ecf20Sopenharmony_ci{
40528c2ecf20Sopenharmony_ci	struct TxDesc *txd = tp->TxDescArray + entry;
40538c2ecf20Sopenharmony_ci	struct device *d = tp_to_dev(tp);
40548c2ecf20Sopenharmony_ci	dma_addr_t mapping;
40558c2ecf20Sopenharmony_ci	u32 opts1;
40568c2ecf20Sopenharmony_ci	int ret;
40578c2ecf20Sopenharmony_ci
40588c2ecf20Sopenharmony_ci	mapping = dma_map_single(d, addr, len, DMA_TO_DEVICE);
40598c2ecf20Sopenharmony_ci	ret = dma_mapping_error(d, mapping);
40608c2ecf20Sopenharmony_ci	if (unlikely(ret)) {
40618c2ecf20Sopenharmony_ci		if (net_ratelimit())
40628c2ecf20Sopenharmony_ci			netdev_err(tp->dev, "Failed to map TX data!\n");
40638c2ecf20Sopenharmony_ci		return ret;
40648c2ecf20Sopenharmony_ci	}
40658c2ecf20Sopenharmony_ci
40668c2ecf20Sopenharmony_ci	txd->addr = cpu_to_le64(mapping);
40678c2ecf20Sopenharmony_ci	txd->opts2 = cpu_to_le32(opts[1]);
40688c2ecf20Sopenharmony_ci
40698c2ecf20Sopenharmony_ci	opts1 = opts[0] | len;
40708c2ecf20Sopenharmony_ci	if (entry == NUM_TX_DESC - 1)
40718c2ecf20Sopenharmony_ci		opts1 |= RingEnd;
40728c2ecf20Sopenharmony_ci	if (desc_own)
40738c2ecf20Sopenharmony_ci		opts1 |= DescOwn;
40748c2ecf20Sopenharmony_ci	txd->opts1 = cpu_to_le32(opts1);
40758c2ecf20Sopenharmony_ci
40768c2ecf20Sopenharmony_ci	tp->tx_skb[entry].len = len;
40778c2ecf20Sopenharmony_ci
40788c2ecf20Sopenharmony_ci	return 0;
40798c2ecf20Sopenharmony_ci}
40808c2ecf20Sopenharmony_ci
40818c2ecf20Sopenharmony_cistatic int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb,
40828c2ecf20Sopenharmony_ci			      const u32 *opts, unsigned int entry)
40838c2ecf20Sopenharmony_ci{
40848c2ecf20Sopenharmony_ci	struct skb_shared_info *info = skb_shinfo(skb);
40858c2ecf20Sopenharmony_ci	unsigned int cur_frag;
40868c2ecf20Sopenharmony_ci
40878c2ecf20Sopenharmony_ci	for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) {
40888c2ecf20Sopenharmony_ci		const skb_frag_t *frag = info->frags + cur_frag;
40898c2ecf20Sopenharmony_ci		void *addr = skb_frag_address(frag);
40908c2ecf20Sopenharmony_ci		u32 len = skb_frag_size(frag);
40918c2ecf20Sopenharmony_ci
40928c2ecf20Sopenharmony_ci		entry = (entry + 1) % NUM_TX_DESC;
40938c2ecf20Sopenharmony_ci
40948c2ecf20Sopenharmony_ci		if (unlikely(rtl8169_tx_map(tp, opts, len, addr, entry, true)))
40958c2ecf20Sopenharmony_ci			goto err_out;
40968c2ecf20Sopenharmony_ci	}
40978c2ecf20Sopenharmony_ci
40988c2ecf20Sopenharmony_ci	return 0;
40998c2ecf20Sopenharmony_ci
41008c2ecf20Sopenharmony_cierr_out:
41018c2ecf20Sopenharmony_ci	rtl8169_tx_clear_range(tp, tp->cur_tx + 1, cur_frag);
41028c2ecf20Sopenharmony_ci	return -EIO;
41038c2ecf20Sopenharmony_ci}
41048c2ecf20Sopenharmony_ci
41058c2ecf20Sopenharmony_cistatic bool rtl_skb_is_udp(struct sk_buff *skb)
41068c2ecf20Sopenharmony_ci{
41078c2ecf20Sopenharmony_ci	int no = skb_network_offset(skb);
41088c2ecf20Sopenharmony_ci	struct ipv6hdr *i6h, _i6h;
41098c2ecf20Sopenharmony_ci	struct iphdr *ih, _ih;
41108c2ecf20Sopenharmony_ci
41118c2ecf20Sopenharmony_ci	switch (vlan_get_protocol(skb)) {
41128c2ecf20Sopenharmony_ci	case htons(ETH_P_IP):
41138c2ecf20Sopenharmony_ci		ih = skb_header_pointer(skb, no, sizeof(_ih), &_ih);
41148c2ecf20Sopenharmony_ci		return ih && ih->protocol == IPPROTO_UDP;
41158c2ecf20Sopenharmony_ci	case htons(ETH_P_IPV6):
41168c2ecf20Sopenharmony_ci		i6h = skb_header_pointer(skb, no, sizeof(_i6h), &_i6h);
41178c2ecf20Sopenharmony_ci		return i6h && i6h->nexthdr == IPPROTO_UDP;
41188c2ecf20Sopenharmony_ci	default:
41198c2ecf20Sopenharmony_ci		return false;
41208c2ecf20Sopenharmony_ci	}
41218c2ecf20Sopenharmony_ci}
41228c2ecf20Sopenharmony_ci
41238c2ecf20Sopenharmony_ci#define RTL_MIN_PATCH_LEN	47
41248c2ecf20Sopenharmony_ci
41258c2ecf20Sopenharmony_ci/* see rtl8125_get_patch_pad_len() in r8125 vendor driver */
41268c2ecf20Sopenharmony_cistatic unsigned int rtl8125_quirk_udp_padto(struct rtl8169_private *tp,
41278c2ecf20Sopenharmony_ci					    struct sk_buff *skb)
41288c2ecf20Sopenharmony_ci{
41298c2ecf20Sopenharmony_ci	unsigned int padto = 0, len = skb->len;
41308c2ecf20Sopenharmony_ci
41318c2ecf20Sopenharmony_ci	if (rtl_is_8125(tp) && len < 128 + RTL_MIN_PATCH_LEN &&
41328c2ecf20Sopenharmony_ci	    rtl_skb_is_udp(skb) && skb_transport_header_was_set(skb)) {
41338c2ecf20Sopenharmony_ci		unsigned int trans_data_len = skb_tail_pointer(skb) -
41348c2ecf20Sopenharmony_ci					      skb_transport_header(skb);
41358c2ecf20Sopenharmony_ci
41368c2ecf20Sopenharmony_ci		if (trans_data_len >= offsetof(struct udphdr, len) &&
41378c2ecf20Sopenharmony_ci		    trans_data_len < RTL_MIN_PATCH_LEN) {
41388c2ecf20Sopenharmony_ci			u16 dest = ntohs(udp_hdr(skb)->dest);
41398c2ecf20Sopenharmony_ci
41408c2ecf20Sopenharmony_ci			/* dest is a standard PTP port */
41418c2ecf20Sopenharmony_ci			if (dest == 319 || dest == 320)
41428c2ecf20Sopenharmony_ci				padto = len + RTL_MIN_PATCH_LEN - trans_data_len;
41438c2ecf20Sopenharmony_ci		}
41448c2ecf20Sopenharmony_ci
41458c2ecf20Sopenharmony_ci		if (trans_data_len < sizeof(struct udphdr))
41468c2ecf20Sopenharmony_ci			padto = max_t(unsigned int, padto,
41478c2ecf20Sopenharmony_ci				      len + sizeof(struct udphdr) - trans_data_len);
41488c2ecf20Sopenharmony_ci	}
41498c2ecf20Sopenharmony_ci
41508c2ecf20Sopenharmony_ci	return padto;
41518c2ecf20Sopenharmony_ci}
41528c2ecf20Sopenharmony_ci
41538c2ecf20Sopenharmony_cistatic unsigned int rtl_quirk_packet_padto(struct rtl8169_private *tp,
41548c2ecf20Sopenharmony_ci					   struct sk_buff *skb)
41558c2ecf20Sopenharmony_ci{
41568c2ecf20Sopenharmony_ci	unsigned int padto;
41578c2ecf20Sopenharmony_ci
41588c2ecf20Sopenharmony_ci	padto = rtl8125_quirk_udp_padto(tp, skb);
41598c2ecf20Sopenharmony_ci
41608c2ecf20Sopenharmony_ci	switch (tp->mac_version) {
41618c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_34:
41628c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_60:
41638c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_61:
41648c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_63:
41658c2ecf20Sopenharmony_ci		padto = max_t(unsigned int, padto, ETH_ZLEN);
41668c2ecf20Sopenharmony_ci	default:
41678c2ecf20Sopenharmony_ci		break;
41688c2ecf20Sopenharmony_ci	}
41698c2ecf20Sopenharmony_ci
41708c2ecf20Sopenharmony_ci	return padto;
41718c2ecf20Sopenharmony_ci}
41728c2ecf20Sopenharmony_ci
41738c2ecf20Sopenharmony_cistatic void rtl8169_tso_csum_v1(struct sk_buff *skb, u32 *opts)
41748c2ecf20Sopenharmony_ci{
41758c2ecf20Sopenharmony_ci	u32 mss = skb_shinfo(skb)->gso_size;
41768c2ecf20Sopenharmony_ci
41778c2ecf20Sopenharmony_ci	if (mss) {
41788c2ecf20Sopenharmony_ci		opts[0] |= TD_LSO;
41798c2ecf20Sopenharmony_ci		opts[0] |= mss << TD0_MSS_SHIFT;
41808c2ecf20Sopenharmony_ci	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
41818c2ecf20Sopenharmony_ci		const struct iphdr *ip = ip_hdr(skb);
41828c2ecf20Sopenharmony_ci
41838c2ecf20Sopenharmony_ci		if (ip->protocol == IPPROTO_TCP)
41848c2ecf20Sopenharmony_ci			opts[0] |= TD0_IP_CS | TD0_TCP_CS;
41858c2ecf20Sopenharmony_ci		else if (ip->protocol == IPPROTO_UDP)
41868c2ecf20Sopenharmony_ci			opts[0] |= TD0_IP_CS | TD0_UDP_CS;
41878c2ecf20Sopenharmony_ci		else
41888c2ecf20Sopenharmony_ci			WARN_ON_ONCE(1);
41898c2ecf20Sopenharmony_ci	}
41908c2ecf20Sopenharmony_ci}
41918c2ecf20Sopenharmony_ci
41928c2ecf20Sopenharmony_cistatic bool rtl8169_tso_csum_v2(struct rtl8169_private *tp,
41938c2ecf20Sopenharmony_ci				struct sk_buff *skb, u32 *opts)
41948c2ecf20Sopenharmony_ci{
41958c2ecf20Sopenharmony_ci	struct skb_shared_info *shinfo = skb_shinfo(skb);
41968c2ecf20Sopenharmony_ci	u32 mss = shinfo->gso_size;
41978c2ecf20Sopenharmony_ci
41988c2ecf20Sopenharmony_ci	if (mss) {
41998c2ecf20Sopenharmony_ci		if (shinfo->gso_type & SKB_GSO_TCPV4) {
42008c2ecf20Sopenharmony_ci			opts[0] |= TD1_GTSENV4;
42018c2ecf20Sopenharmony_ci		} else if (shinfo->gso_type & SKB_GSO_TCPV6) {
42028c2ecf20Sopenharmony_ci			if (skb_cow_head(skb, 0))
42038c2ecf20Sopenharmony_ci				return false;
42048c2ecf20Sopenharmony_ci
42058c2ecf20Sopenharmony_ci			tcp_v6_gso_csum_prep(skb);
42068c2ecf20Sopenharmony_ci			opts[0] |= TD1_GTSENV6;
42078c2ecf20Sopenharmony_ci		} else {
42088c2ecf20Sopenharmony_ci			WARN_ON_ONCE(1);
42098c2ecf20Sopenharmony_ci		}
42108c2ecf20Sopenharmony_ci
42118c2ecf20Sopenharmony_ci		opts[0] |= skb_transport_offset(skb) << GTTCPHO_SHIFT;
42128c2ecf20Sopenharmony_ci		opts[1] |= mss << TD1_MSS_SHIFT;
42138c2ecf20Sopenharmony_ci	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
42148c2ecf20Sopenharmony_ci		u8 ip_protocol;
42158c2ecf20Sopenharmony_ci
42168c2ecf20Sopenharmony_ci		switch (vlan_get_protocol(skb)) {
42178c2ecf20Sopenharmony_ci		case htons(ETH_P_IP):
42188c2ecf20Sopenharmony_ci			opts[1] |= TD1_IPv4_CS;
42198c2ecf20Sopenharmony_ci			ip_protocol = ip_hdr(skb)->protocol;
42208c2ecf20Sopenharmony_ci			break;
42218c2ecf20Sopenharmony_ci
42228c2ecf20Sopenharmony_ci		case htons(ETH_P_IPV6):
42238c2ecf20Sopenharmony_ci			opts[1] |= TD1_IPv6_CS;
42248c2ecf20Sopenharmony_ci			ip_protocol = ipv6_hdr(skb)->nexthdr;
42258c2ecf20Sopenharmony_ci			break;
42268c2ecf20Sopenharmony_ci
42278c2ecf20Sopenharmony_ci		default:
42288c2ecf20Sopenharmony_ci			ip_protocol = IPPROTO_RAW;
42298c2ecf20Sopenharmony_ci			break;
42308c2ecf20Sopenharmony_ci		}
42318c2ecf20Sopenharmony_ci
42328c2ecf20Sopenharmony_ci		if (ip_protocol == IPPROTO_TCP)
42338c2ecf20Sopenharmony_ci			opts[1] |= TD1_TCP_CS;
42348c2ecf20Sopenharmony_ci		else if (ip_protocol == IPPROTO_UDP)
42358c2ecf20Sopenharmony_ci			opts[1] |= TD1_UDP_CS;
42368c2ecf20Sopenharmony_ci		else
42378c2ecf20Sopenharmony_ci			WARN_ON_ONCE(1);
42388c2ecf20Sopenharmony_ci
42398c2ecf20Sopenharmony_ci		opts[1] |= skb_transport_offset(skb) << TCPHO_SHIFT;
42408c2ecf20Sopenharmony_ci	} else {
42418c2ecf20Sopenharmony_ci		unsigned int padto = rtl_quirk_packet_padto(tp, skb);
42428c2ecf20Sopenharmony_ci
42438c2ecf20Sopenharmony_ci		/* skb_padto would free the skb on error */
42448c2ecf20Sopenharmony_ci		return !__skb_put_padto(skb, padto, false);
42458c2ecf20Sopenharmony_ci	}
42468c2ecf20Sopenharmony_ci
42478c2ecf20Sopenharmony_ci	return true;
42488c2ecf20Sopenharmony_ci}
42498c2ecf20Sopenharmony_ci
42508c2ecf20Sopenharmony_cistatic bool rtl_tx_slots_avail(struct rtl8169_private *tp,
42518c2ecf20Sopenharmony_ci			       unsigned int nr_frags)
42528c2ecf20Sopenharmony_ci{
42538c2ecf20Sopenharmony_ci	unsigned int slots_avail = tp->dirty_tx + NUM_TX_DESC - tp->cur_tx;
42548c2ecf20Sopenharmony_ci
42558c2ecf20Sopenharmony_ci	/* A skbuff with nr_frags needs nr_frags+1 entries in the tx queue */
42568c2ecf20Sopenharmony_ci	return slots_avail > nr_frags;
42578c2ecf20Sopenharmony_ci}
42588c2ecf20Sopenharmony_ci
42598c2ecf20Sopenharmony_ci/* Versions RTL8102e and from RTL8168c onwards support csum_v2 */
42608c2ecf20Sopenharmony_cistatic bool rtl_chip_supports_csum_v2(struct rtl8169_private *tp)
42618c2ecf20Sopenharmony_ci{
42628c2ecf20Sopenharmony_ci	switch (tp->mac_version) {
42638c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06:
42648c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_10 ... RTL_GIGA_MAC_VER_17:
42658c2ecf20Sopenharmony_ci		return false;
42668c2ecf20Sopenharmony_ci	default:
42678c2ecf20Sopenharmony_ci		return true;
42688c2ecf20Sopenharmony_ci	}
42698c2ecf20Sopenharmony_ci}
42708c2ecf20Sopenharmony_ci
42718c2ecf20Sopenharmony_cistatic void rtl8169_doorbell(struct rtl8169_private *tp)
42728c2ecf20Sopenharmony_ci{
42738c2ecf20Sopenharmony_ci	if (rtl_is_8125(tp))
42748c2ecf20Sopenharmony_ci		RTL_W16(tp, TxPoll_8125, BIT(0));
42758c2ecf20Sopenharmony_ci	else
42768c2ecf20Sopenharmony_ci		RTL_W8(tp, TxPoll, NPQ);
42778c2ecf20Sopenharmony_ci}
42788c2ecf20Sopenharmony_ci
42798c2ecf20Sopenharmony_cistatic netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
42808c2ecf20Sopenharmony_ci				      struct net_device *dev)
42818c2ecf20Sopenharmony_ci{
42828c2ecf20Sopenharmony_ci	unsigned int frags = skb_shinfo(skb)->nr_frags;
42838c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = netdev_priv(dev);
42848c2ecf20Sopenharmony_ci	unsigned int entry = tp->cur_tx % NUM_TX_DESC;
42858c2ecf20Sopenharmony_ci	struct TxDesc *txd_first, *txd_last;
42868c2ecf20Sopenharmony_ci	bool stop_queue, door_bell;
42878c2ecf20Sopenharmony_ci	u32 opts[2];
42888c2ecf20Sopenharmony_ci
42898c2ecf20Sopenharmony_ci	txd_first = tp->TxDescArray + entry;
42908c2ecf20Sopenharmony_ci
42918c2ecf20Sopenharmony_ci	if (unlikely(!rtl_tx_slots_avail(tp, frags))) {
42928c2ecf20Sopenharmony_ci		if (net_ratelimit())
42938c2ecf20Sopenharmony_ci			netdev_err(dev, "BUG! Tx Ring full when queue awake!\n");
42948c2ecf20Sopenharmony_ci		goto err_stop_0;
42958c2ecf20Sopenharmony_ci	}
42968c2ecf20Sopenharmony_ci
42978c2ecf20Sopenharmony_ci	if (unlikely(le32_to_cpu(txd_first->opts1) & DescOwn))
42988c2ecf20Sopenharmony_ci		goto err_stop_0;
42998c2ecf20Sopenharmony_ci
43008c2ecf20Sopenharmony_ci	opts[1] = rtl8169_tx_vlan_tag(skb);
43018c2ecf20Sopenharmony_ci	opts[0] = 0;
43028c2ecf20Sopenharmony_ci
43038c2ecf20Sopenharmony_ci	if (!rtl_chip_supports_csum_v2(tp))
43048c2ecf20Sopenharmony_ci		rtl8169_tso_csum_v1(skb, opts);
43058c2ecf20Sopenharmony_ci	else if (!rtl8169_tso_csum_v2(tp, skb, opts))
43068c2ecf20Sopenharmony_ci		goto err_dma_0;
43078c2ecf20Sopenharmony_ci
43088c2ecf20Sopenharmony_ci	if (unlikely(rtl8169_tx_map(tp, opts, skb_headlen(skb), skb->data,
43098c2ecf20Sopenharmony_ci				    entry, false)))
43108c2ecf20Sopenharmony_ci		goto err_dma_0;
43118c2ecf20Sopenharmony_ci
43128c2ecf20Sopenharmony_ci	if (frags) {
43138c2ecf20Sopenharmony_ci		if (rtl8169_xmit_frags(tp, skb, opts, entry))
43148c2ecf20Sopenharmony_ci			goto err_dma_1;
43158c2ecf20Sopenharmony_ci		entry = (entry + frags) % NUM_TX_DESC;
43168c2ecf20Sopenharmony_ci	}
43178c2ecf20Sopenharmony_ci
43188c2ecf20Sopenharmony_ci	txd_last = tp->TxDescArray + entry;
43198c2ecf20Sopenharmony_ci	txd_last->opts1 |= cpu_to_le32(LastFrag);
43208c2ecf20Sopenharmony_ci	tp->tx_skb[entry].skb = skb;
43218c2ecf20Sopenharmony_ci
43228c2ecf20Sopenharmony_ci	skb_tx_timestamp(skb);
43238c2ecf20Sopenharmony_ci
43248c2ecf20Sopenharmony_ci	/* Force memory writes to complete before releasing descriptor */
43258c2ecf20Sopenharmony_ci	dma_wmb();
43268c2ecf20Sopenharmony_ci
43278c2ecf20Sopenharmony_ci	door_bell = __netdev_sent_queue(dev, skb->len, netdev_xmit_more());
43288c2ecf20Sopenharmony_ci
43298c2ecf20Sopenharmony_ci	txd_first->opts1 |= cpu_to_le32(DescOwn | FirstFrag);
43308c2ecf20Sopenharmony_ci
43318c2ecf20Sopenharmony_ci	/* rtl_tx needs to see descriptor changes before updated tp->cur_tx */
43328c2ecf20Sopenharmony_ci	smp_wmb();
43338c2ecf20Sopenharmony_ci
43348c2ecf20Sopenharmony_ci	tp->cur_tx += frags + 1;
43358c2ecf20Sopenharmony_ci
43368c2ecf20Sopenharmony_ci	stop_queue = !rtl_tx_slots_avail(tp, MAX_SKB_FRAGS);
43378c2ecf20Sopenharmony_ci	if (unlikely(stop_queue)) {
43388c2ecf20Sopenharmony_ci		/* Avoid wrongly optimistic queue wake-up: rtl_tx thread must
43398c2ecf20Sopenharmony_ci		 * not miss a ring update when it notices a stopped queue.
43408c2ecf20Sopenharmony_ci		 */
43418c2ecf20Sopenharmony_ci		smp_wmb();
43428c2ecf20Sopenharmony_ci		netif_stop_queue(dev);
43438c2ecf20Sopenharmony_ci		door_bell = true;
43448c2ecf20Sopenharmony_ci	}
43458c2ecf20Sopenharmony_ci
43468c2ecf20Sopenharmony_ci	if (door_bell)
43478c2ecf20Sopenharmony_ci		rtl8169_doorbell(tp);
43488c2ecf20Sopenharmony_ci
43498c2ecf20Sopenharmony_ci	if (unlikely(stop_queue)) {
43508c2ecf20Sopenharmony_ci		/* Sync with rtl_tx:
43518c2ecf20Sopenharmony_ci		 * - publish queue status and cur_tx ring index (write barrier)
43528c2ecf20Sopenharmony_ci		 * - refresh dirty_tx ring index (read barrier).
43538c2ecf20Sopenharmony_ci		 * May the current thread have a pessimistic view of the ring
43548c2ecf20Sopenharmony_ci		 * status and forget to wake up queue, a racing rtl_tx thread
43558c2ecf20Sopenharmony_ci		 * can't.
43568c2ecf20Sopenharmony_ci		 */
43578c2ecf20Sopenharmony_ci		smp_mb();
43588c2ecf20Sopenharmony_ci		if (rtl_tx_slots_avail(tp, MAX_SKB_FRAGS))
43598c2ecf20Sopenharmony_ci			netif_start_queue(dev);
43608c2ecf20Sopenharmony_ci	}
43618c2ecf20Sopenharmony_ci
43628c2ecf20Sopenharmony_ci	return NETDEV_TX_OK;
43638c2ecf20Sopenharmony_ci
43648c2ecf20Sopenharmony_cierr_dma_1:
43658c2ecf20Sopenharmony_ci	rtl8169_unmap_tx_skb(tp, entry);
43668c2ecf20Sopenharmony_cierr_dma_0:
43678c2ecf20Sopenharmony_ci	dev_kfree_skb_any(skb);
43688c2ecf20Sopenharmony_ci	dev->stats.tx_dropped++;
43698c2ecf20Sopenharmony_ci	return NETDEV_TX_OK;
43708c2ecf20Sopenharmony_ci
43718c2ecf20Sopenharmony_cierr_stop_0:
43728c2ecf20Sopenharmony_ci	netif_stop_queue(dev);
43738c2ecf20Sopenharmony_ci	dev->stats.tx_dropped++;
43748c2ecf20Sopenharmony_ci	return NETDEV_TX_BUSY;
43758c2ecf20Sopenharmony_ci}
43768c2ecf20Sopenharmony_ci
43778c2ecf20Sopenharmony_cistatic unsigned int rtl_last_frag_len(struct sk_buff *skb)
43788c2ecf20Sopenharmony_ci{
43798c2ecf20Sopenharmony_ci	struct skb_shared_info *info = skb_shinfo(skb);
43808c2ecf20Sopenharmony_ci	unsigned int nr_frags = info->nr_frags;
43818c2ecf20Sopenharmony_ci
43828c2ecf20Sopenharmony_ci	if (!nr_frags)
43838c2ecf20Sopenharmony_ci		return UINT_MAX;
43848c2ecf20Sopenharmony_ci
43858c2ecf20Sopenharmony_ci	return skb_frag_size(info->frags + nr_frags - 1);
43868c2ecf20Sopenharmony_ci}
43878c2ecf20Sopenharmony_ci
43888c2ecf20Sopenharmony_ci/* Workaround for hw issues with TSO on RTL8168evl */
43898c2ecf20Sopenharmony_cistatic netdev_features_t rtl8168evl_fix_tso(struct sk_buff *skb,
43908c2ecf20Sopenharmony_ci					    netdev_features_t features)
43918c2ecf20Sopenharmony_ci{
43928c2ecf20Sopenharmony_ci	/* IPv4 header has options field */
43938c2ecf20Sopenharmony_ci	if (vlan_get_protocol(skb) == htons(ETH_P_IP) &&
43948c2ecf20Sopenharmony_ci	    ip_hdrlen(skb) > sizeof(struct iphdr))
43958c2ecf20Sopenharmony_ci		features &= ~NETIF_F_ALL_TSO;
43968c2ecf20Sopenharmony_ci
43978c2ecf20Sopenharmony_ci	/* IPv4 TCP header has options field */
43988c2ecf20Sopenharmony_ci	else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4 &&
43998c2ecf20Sopenharmony_ci		 tcp_hdrlen(skb) > sizeof(struct tcphdr))
44008c2ecf20Sopenharmony_ci		features &= ~NETIF_F_ALL_TSO;
44018c2ecf20Sopenharmony_ci
44028c2ecf20Sopenharmony_ci	else if (rtl_last_frag_len(skb) <= 6)
44038c2ecf20Sopenharmony_ci		features &= ~NETIF_F_ALL_TSO;
44048c2ecf20Sopenharmony_ci
44058c2ecf20Sopenharmony_ci	return features;
44068c2ecf20Sopenharmony_ci}
44078c2ecf20Sopenharmony_ci
44088c2ecf20Sopenharmony_cistatic netdev_features_t rtl8169_features_check(struct sk_buff *skb,
44098c2ecf20Sopenharmony_ci						struct net_device *dev,
44108c2ecf20Sopenharmony_ci						netdev_features_t features)
44118c2ecf20Sopenharmony_ci{
44128c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = netdev_priv(dev);
44138c2ecf20Sopenharmony_ci
44148c2ecf20Sopenharmony_ci	if (skb_is_gso(skb)) {
44158c2ecf20Sopenharmony_ci		if (tp->mac_version == RTL_GIGA_MAC_VER_34)
44168c2ecf20Sopenharmony_ci			features = rtl8168evl_fix_tso(skb, features);
44178c2ecf20Sopenharmony_ci
44188c2ecf20Sopenharmony_ci		if (skb_transport_offset(skb) > GTTCPHO_MAX &&
44198c2ecf20Sopenharmony_ci		    rtl_chip_supports_csum_v2(tp))
44208c2ecf20Sopenharmony_ci			features &= ~NETIF_F_ALL_TSO;
44218c2ecf20Sopenharmony_ci	} else if (skb->ip_summed == CHECKSUM_PARTIAL) {
44228c2ecf20Sopenharmony_ci		/* work around hw bug on some chip versions */
44238c2ecf20Sopenharmony_ci		if (skb->len < ETH_ZLEN)
44248c2ecf20Sopenharmony_ci			features &= ~NETIF_F_CSUM_MASK;
44258c2ecf20Sopenharmony_ci
44268c2ecf20Sopenharmony_ci		if (rtl_quirk_packet_padto(tp, skb))
44278c2ecf20Sopenharmony_ci			features &= ~NETIF_F_CSUM_MASK;
44288c2ecf20Sopenharmony_ci
44298c2ecf20Sopenharmony_ci		if (skb_transport_offset(skb) > TCPHO_MAX &&
44308c2ecf20Sopenharmony_ci		    rtl_chip_supports_csum_v2(tp))
44318c2ecf20Sopenharmony_ci			features &= ~NETIF_F_CSUM_MASK;
44328c2ecf20Sopenharmony_ci	}
44338c2ecf20Sopenharmony_ci
44348c2ecf20Sopenharmony_ci	return vlan_features_check(skb, features);
44358c2ecf20Sopenharmony_ci}
44368c2ecf20Sopenharmony_ci
44378c2ecf20Sopenharmony_cistatic void rtl8169_pcierr_interrupt(struct net_device *dev)
44388c2ecf20Sopenharmony_ci{
44398c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = netdev_priv(dev);
44408c2ecf20Sopenharmony_ci	struct pci_dev *pdev = tp->pci_dev;
44418c2ecf20Sopenharmony_ci	int pci_status_errs;
44428c2ecf20Sopenharmony_ci	u16 pci_cmd;
44438c2ecf20Sopenharmony_ci
44448c2ecf20Sopenharmony_ci	pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd);
44458c2ecf20Sopenharmony_ci
44468c2ecf20Sopenharmony_ci	pci_status_errs = pci_status_get_and_clear_errors(pdev);
44478c2ecf20Sopenharmony_ci
44488c2ecf20Sopenharmony_ci	if (net_ratelimit())
44498c2ecf20Sopenharmony_ci		netdev_err(dev, "PCI error (cmd = 0x%04x, status_errs = 0x%04x)\n",
44508c2ecf20Sopenharmony_ci			   pci_cmd, pci_status_errs);
44518c2ecf20Sopenharmony_ci	/*
44528c2ecf20Sopenharmony_ci	 * The recovery sequence below admits a very elaborated explanation:
44538c2ecf20Sopenharmony_ci	 * - it seems to work;
44548c2ecf20Sopenharmony_ci	 * - I did not see what else could be done;
44558c2ecf20Sopenharmony_ci	 * - it makes iop3xx happy.
44568c2ecf20Sopenharmony_ci	 *
44578c2ecf20Sopenharmony_ci	 * Feel free to adjust to your needs.
44588c2ecf20Sopenharmony_ci	 */
44598c2ecf20Sopenharmony_ci	if (pdev->broken_parity_status)
44608c2ecf20Sopenharmony_ci		pci_cmd &= ~PCI_COMMAND_PARITY;
44618c2ecf20Sopenharmony_ci	else
44628c2ecf20Sopenharmony_ci		pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY;
44638c2ecf20Sopenharmony_ci
44648c2ecf20Sopenharmony_ci	pci_write_config_word(pdev, PCI_COMMAND, pci_cmd);
44658c2ecf20Sopenharmony_ci
44668c2ecf20Sopenharmony_ci	rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
44678c2ecf20Sopenharmony_ci}
44688c2ecf20Sopenharmony_ci
44698c2ecf20Sopenharmony_cistatic void rtl_tx(struct net_device *dev, struct rtl8169_private *tp,
44708c2ecf20Sopenharmony_ci		   int budget)
44718c2ecf20Sopenharmony_ci{
44728c2ecf20Sopenharmony_ci	unsigned int dirty_tx, tx_left, bytes_compl = 0, pkts_compl = 0;
44738c2ecf20Sopenharmony_ci
44748c2ecf20Sopenharmony_ci	dirty_tx = tp->dirty_tx;
44758c2ecf20Sopenharmony_ci	smp_rmb();
44768c2ecf20Sopenharmony_ci
44778c2ecf20Sopenharmony_ci	for (tx_left = tp->cur_tx - dirty_tx; tx_left > 0; tx_left--) {
44788c2ecf20Sopenharmony_ci		unsigned int entry = dirty_tx % NUM_TX_DESC;
44798c2ecf20Sopenharmony_ci		struct sk_buff *skb = tp->tx_skb[entry].skb;
44808c2ecf20Sopenharmony_ci		u32 status;
44818c2ecf20Sopenharmony_ci
44828c2ecf20Sopenharmony_ci		status = le32_to_cpu(READ_ONCE(tp->TxDescArray[entry].opts1));
44838c2ecf20Sopenharmony_ci		if (status & DescOwn)
44848c2ecf20Sopenharmony_ci			break;
44858c2ecf20Sopenharmony_ci
44868c2ecf20Sopenharmony_ci		rtl8169_unmap_tx_skb(tp, entry);
44878c2ecf20Sopenharmony_ci
44888c2ecf20Sopenharmony_ci		if (skb) {
44898c2ecf20Sopenharmony_ci			pkts_compl++;
44908c2ecf20Sopenharmony_ci			bytes_compl += skb->len;
44918c2ecf20Sopenharmony_ci			napi_consume_skb(skb, budget);
44928c2ecf20Sopenharmony_ci		}
44938c2ecf20Sopenharmony_ci		dirty_tx++;
44948c2ecf20Sopenharmony_ci	}
44958c2ecf20Sopenharmony_ci
44968c2ecf20Sopenharmony_ci	if (tp->dirty_tx != dirty_tx) {
44978c2ecf20Sopenharmony_ci		netdev_completed_queue(dev, pkts_compl, bytes_compl);
44988c2ecf20Sopenharmony_ci
44998c2ecf20Sopenharmony_ci		rtl_inc_priv_stats(&tp->tx_stats, pkts_compl, bytes_compl);
45008c2ecf20Sopenharmony_ci
45018c2ecf20Sopenharmony_ci		tp->dirty_tx = dirty_tx;
45028c2ecf20Sopenharmony_ci		/* Sync with rtl8169_start_xmit:
45038c2ecf20Sopenharmony_ci		 * - publish dirty_tx ring index (write barrier)
45048c2ecf20Sopenharmony_ci		 * - refresh cur_tx ring index and queue status (read barrier)
45058c2ecf20Sopenharmony_ci		 * May the current thread miss the stopped queue condition,
45068c2ecf20Sopenharmony_ci		 * a racing xmit thread can only have a right view of the
45078c2ecf20Sopenharmony_ci		 * ring status.
45088c2ecf20Sopenharmony_ci		 */
45098c2ecf20Sopenharmony_ci		smp_mb();
45108c2ecf20Sopenharmony_ci		if (netif_queue_stopped(dev) &&
45118c2ecf20Sopenharmony_ci		    rtl_tx_slots_avail(tp, MAX_SKB_FRAGS)) {
45128c2ecf20Sopenharmony_ci			netif_wake_queue(dev);
45138c2ecf20Sopenharmony_ci		}
45148c2ecf20Sopenharmony_ci		/*
45158c2ecf20Sopenharmony_ci		 * 8168 hack: TxPoll requests are lost when the Tx packets are
45168c2ecf20Sopenharmony_ci		 * too close. Let's kick an extra TxPoll request when a burst
45178c2ecf20Sopenharmony_ci		 * of start_xmit activity is detected (if it is not detected,
45188c2ecf20Sopenharmony_ci		 * it is slow enough). -- FR
45198c2ecf20Sopenharmony_ci		 */
45208c2ecf20Sopenharmony_ci		if (tp->cur_tx != dirty_tx)
45218c2ecf20Sopenharmony_ci			rtl8169_doorbell(tp);
45228c2ecf20Sopenharmony_ci	}
45238c2ecf20Sopenharmony_ci}
45248c2ecf20Sopenharmony_ci
45258c2ecf20Sopenharmony_cistatic inline int rtl8169_fragmented_frame(u32 status)
45268c2ecf20Sopenharmony_ci{
45278c2ecf20Sopenharmony_ci	return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag);
45288c2ecf20Sopenharmony_ci}
45298c2ecf20Sopenharmony_ci
45308c2ecf20Sopenharmony_cistatic inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1)
45318c2ecf20Sopenharmony_ci{
45328c2ecf20Sopenharmony_ci	u32 status = opts1 & RxProtoMask;
45338c2ecf20Sopenharmony_ci
45348c2ecf20Sopenharmony_ci	if (((status == RxProtoTCP) && !(opts1 & TCPFail)) ||
45358c2ecf20Sopenharmony_ci	    ((status == RxProtoUDP) && !(opts1 & UDPFail)))
45368c2ecf20Sopenharmony_ci		skb->ip_summed = CHECKSUM_UNNECESSARY;
45378c2ecf20Sopenharmony_ci	else
45388c2ecf20Sopenharmony_ci		skb_checksum_none_assert(skb);
45398c2ecf20Sopenharmony_ci}
45408c2ecf20Sopenharmony_ci
45418c2ecf20Sopenharmony_cistatic int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget)
45428c2ecf20Sopenharmony_ci{
45438c2ecf20Sopenharmony_ci	unsigned int cur_rx, rx_left, count;
45448c2ecf20Sopenharmony_ci	struct device *d = tp_to_dev(tp);
45458c2ecf20Sopenharmony_ci
45468c2ecf20Sopenharmony_ci	cur_rx = tp->cur_rx;
45478c2ecf20Sopenharmony_ci
45488c2ecf20Sopenharmony_ci	for (rx_left = min(budget, NUM_RX_DESC); rx_left > 0; rx_left--, cur_rx++) {
45498c2ecf20Sopenharmony_ci		unsigned int pkt_size, entry = cur_rx % NUM_RX_DESC;
45508c2ecf20Sopenharmony_ci		struct RxDesc *desc = tp->RxDescArray + entry;
45518c2ecf20Sopenharmony_ci		struct sk_buff *skb;
45528c2ecf20Sopenharmony_ci		const void *rx_buf;
45538c2ecf20Sopenharmony_ci		dma_addr_t addr;
45548c2ecf20Sopenharmony_ci		u32 status;
45558c2ecf20Sopenharmony_ci
45568c2ecf20Sopenharmony_ci		status = le32_to_cpu(READ_ONCE(desc->opts1));
45578c2ecf20Sopenharmony_ci		if (status & DescOwn)
45588c2ecf20Sopenharmony_ci			break;
45598c2ecf20Sopenharmony_ci
45608c2ecf20Sopenharmony_ci		/* This barrier is needed to keep us from reading
45618c2ecf20Sopenharmony_ci		 * any other fields out of the Rx descriptor until
45628c2ecf20Sopenharmony_ci		 * we know the status of DescOwn
45638c2ecf20Sopenharmony_ci		 */
45648c2ecf20Sopenharmony_ci		dma_rmb();
45658c2ecf20Sopenharmony_ci
45668c2ecf20Sopenharmony_ci		if (unlikely(status & RxRES)) {
45678c2ecf20Sopenharmony_ci			if (net_ratelimit())
45688c2ecf20Sopenharmony_ci				netdev_warn(dev, "Rx ERROR. status = %08x\n",
45698c2ecf20Sopenharmony_ci					    status);
45708c2ecf20Sopenharmony_ci			dev->stats.rx_errors++;
45718c2ecf20Sopenharmony_ci			if (status & (RxRWT | RxRUNT))
45728c2ecf20Sopenharmony_ci				dev->stats.rx_length_errors++;
45738c2ecf20Sopenharmony_ci			if (status & RxCRC)
45748c2ecf20Sopenharmony_ci				dev->stats.rx_crc_errors++;
45758c2ecf20Sopenharmony_ci
45768c2ecf20Sopenharmony_ci			if (!(dev->features & NETIF_F_RXALL))
45778c2ecf20Sopenharmony_ci				goto release_descriptor;
45788c2ecf20Sopenharmony_ci			else if (status & RxRWT || !(status & (RxRUNT | RxCRC)))
45798c2ecf20Sopenharmony_ci				goto release_descriptor;
45808c2ecf20Sopenharmony_ci		}
45818c2ecf20Sopenharmony_ci
45828c2ecf20Sopenharmony_ci		pkt_size = status & GENMASK(13, 0);
45838c2ecf20Sopenharmony_ci		if (likely(!(dev->features & NETIF_F_RXFCS)))
45848c2ecf20Sopenharmony_ci			pkt_size -= ETH_FCS_LEN;
45858c2ecf20Sopenharmony_ci
45868c2ecf20Sopenharmony_ci		/* The driver does not support incoming fragmented frames.
45878c2ecf20Sopenharmony_ci		 * They are seen as a symptom of over-mtu sized frames.
45888c2ecf20Sopenharmony_ci		 */
45898c2ecf20Sopenharmony_ci		if (unlikely(rtl8169_fragmented_frame(status))) {
45908c2ecf20Sopenharmony_ci			dev->stats.rx_dropped++;
45918c2ecf20Sopenharmony_ci			dev->stats.rx_length_errors++;
45928c2ecf20Sopenharmony_ci			goto release_descriptor;
45938c2ecf20Sopenharmony_ci		}
45948c2ecf20Sopenharmony_ci
45958c2ecf20Sopenharmony_ci		skb = napi_alloc_skb(&tp->napi, pkt_size);
45968c2ecf20Sopenharmony_ci		if (unlikely(!skb)) {
45978c2ecf20Sopenharmony_ci			dev->stats.rx_dropped++;
45988c2ecf20Sopenharmony_ci			goto release_descriptor;
45998c2ecf20Sopenharmony_ci		}
46008c2ecf20Sopenharmony_ci
46018c2ecf20Sopenharmony_ci		addr = le64_to_cpu(desc->addr);
46028c2ecf20Sopenharmony_ci		rx_buf = page_address(tp->Rx_databuff[entry]);
46038c2ecf20Sopenharmony_ci
46048c2ecf20Sopenharmony_ci		dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE);
46058c2ecf20Sopenharmony_ci		prefetch(rx_buf);
46068c2ecf20Sopenharmony_ci		skb_copy_to_linear_data(skb, rx_buf, pkt_size);
46078c2ecf20Sopenharmony_ci		skb->tail += pkt_size;
46088c2ecf20Sopenharmony_ci		skb->len = pkt_size;
46098c2ecf20Sopenharmony_ci		dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE);
46108c2ecf20Sopenharmony_ci
46118c2ecf20Sopenharmony_ci		rtl8169_rx_csum(skb, status);
46128c2ecf20Sopenharmony_ci		skb->protocol = eth_type_trans(skb, dev);
46138c2ecf20Sopenharmony_ci
46148c2ecf20Sopenharmony_ci		rtl8169_rx_vlan_tag(desc, skb);
46158c2ecf20Sopenharmony_ci
46168c2ecf20Sopenharmony_ci		if (skb->pkt_type == PACKET_MULTICAST)
46178c2ecf20Sopenharmony_ci			dev->stats.multicast++;
46188c2ecf20Sopenharmony_ci
46198c2ecf20Sopenharmony_ci		napi_gro_receive(&tp->napi, skb);
46208c2ecf20Sopenharmony_ci
46218c2ecf20Sopenharmony_ci		rtl_inc_priv_stats(&tp->rx_stats, 1, pkt_size);
46228c2ecf20Sopenharmony_cirelease_descriptor:
46238c2ecf20Sopenharmony_ci		rtl8169_mark_to_asic(desc);
46248c2ecf20Sopenharmony_ci	}
46258c2ecf20Sopenharmony_ci
46268c2ecf20Sopenharmony_ci	count = cur_rx - tp->cur_rx;
46278c2ecf20Sopenharmony_ci	tp->cur_rx = cur_rx;
46288c2ecf20Sopenharmony_ci
46298c2ecf20Sopenharmony_ci	return count;
46308c2ecf20Sopenharmony_ci}
46318c2ecf20Sopenharmony_ci
46328c2ecf20Sopenharmony_cistatic irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
46338c2ecf20Sopenharmony_ci{
46348c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = dev_instance;
46358c2ecf20Sopenharmony_ci	u32 status = rtl_get_events(tp);
46368c2ecf20Sopenharmony_ci
46378c2ecf20Sopenharmony_ci	if ((status & 0xffff) == 0xffff || !(status & tp->irq_mask))
46388c2ecf20Sopenharmony_ci		return IRQ_NONE;
46398c2ecf20Sopenharmony_ci
46408c2ecf20Sopenharmony_ci	if (unlikely(status & SYSErr)) {
46418c2ecf20Sopenharmony_ci		rtl8169_pcierr_interrupt(tp->dev);
46428c2ecf20Sopenharmony_ci		goto out;
46438c2ecf20Sopenharmony_ci	}
46448c2ecf20Sopenharmony_ci
46458c2ecf20Sopenharmony_ci	if (status & LinkChg)
46468c2ecf20Sopenharmony_ci		phy_mac_interrupt(tp->phydev);
46478c2ecf20Sopenharmony_ci
46488c2ecf20Sopenharmony_ci	if (unlikely(status & RxFIFOOver &&
46498c2ecf20Sopenharmony_ci	    tp->mac_version == RTL_GIGA_MAC_VER_11)) {
46508c2ecf20Sopenharmony_ci		netif_stop_queue(tp->dev);
46518c2ecf20Sopenharmony_ci		rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING);
46528c2ecf20Sopenharmony_ci	}
46538c2ecf20Sopenharmony_ci
46548c2ecf20Sopenharmony_ci	rtl_irq_disable(tp);
46558c2ecf20Sopenharmony_ci	napi_schedule(&tp->napi);
46568c2ecf20Sopenharmony_ciout:
46578c2ecf20Sopenharmony_ci	rtl_ack_events(tp, status);
46588c2ecf20Sopenharmony_ci
46598c2ecf20Sopenharmony_ci	return IRQ_HANDLED;
46608c2ecf20Sopenharmony_ci}
46618c2ecf20Sopenharmony_ci
46628c2ecf20Sopenharmony_cistatic void rtl_task(struct work_struct *work)
46638c2ecf20Sopenharmony_ci{
46648c2ecf20Sopenharmony_ci	struct rtl8169_private *tp =
46658c2ecf20Sopenharmony_ci		container_of(work, struct rtl8169_private, wk.work);
46668c2ecf20Sopenharmony_ci	int ret;
46678c2ecf20Sopenharmony_ci
46688c2ecf20Sopenharmony_ci	rtnl_lock();
46698c2ecf20Sopenharmony_ci
46708c2ecf20Sopenharmony_ci	if (!netif_running(tp->dev) ||
46718c2ecf20Sopenharmony_ci	    !test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags))
46728c2ecf20Sopenharmony_ci		goto out_unlock;
46738c2ecf20Sopenharmony_ci
46748c2ecf20Sopenharmony_ci	if (test_and_clear_bit(RTL_FLAG_TASK_TX_TIMEOUT, tp->wk.flags)) {
46758c2ecf20Sopenharmony_ci		/* ASPM compatibility issues are a typical reason for tx timeouts */
46768c2ecf20Sopenharmony_ci		ret = pci_disable_link_state(tp->pci_dev, PCIE_LINK_STATE_L1 |
46778c2ecf20Sopenharmony_ci							  PCIE_LINK_STATE_L0S);
46788c2ecf20Sopenharmony_ci		if (!ret)
46798c2ecf20Sopenharmony_ci			netdev_warn_once(tp->dev, "ASPM disabled on Tx timeout\n");
46808c2ecf20Sopenharmony_ci		goto reset;
46818c2ecf20Sopenharmony_ci	}
46828c2ecf20Sopenharmony_ci
46838c2ecf20Sopenharmony_ci	if (test_and_clear_bit(RTL_FLAG_TASK_RESET_PENDING, tp->wk.flags)) {
46848c2ecf20Sopenharmony_cireset:
46858c2ecf20Sopenharmony_ci		rtl_reset_work(tp);
46868c2ecf20Sopenharmony_ci		netif_wake_queue(tp->dev);
46878c2ecf20Sopenharmony_ci	} else if (test_and_clear_bit(RTL_FLAG_TASK_RESET_NO_QUEUE_WAKE, tp->wk.flags)) {
46888c2ecf20Sopenharmony_ci		rtl_reset_work(tp);
46898c2ecf20Sopenharmony_ci	}
46908c2ecf20Sopenharmony_ciout_unlock:
46918c2ecf20Sopenharmony_ci	rtnl_unlock();
46928c2ecf20Sopenharmony_ci}
46938c2ecf20Sopenharmony_ci
46948c2ecf20Sopenharmony_cistatic int rtl8169_poll(struct napi_struct *napi, int budget)
46958c2ecf20Sopenharmony_ci{
46968c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi);
46978c2ecf20Sopenharmony_ci	struct net_device *dev = tp->dev;
46988c2ecf20Sopenharmony_ci	int work_done;
46998c2ecf20Sopenharmony_ci
47008c2ecf20Sopenharmony_ci	work_done = rtl_rx(dev, tp, (u32) budget);
47018c2ecf20Sopenharmony_ci
47028c2ecf20Sopenharmony_ci	rtl_tx(dev, tp, budget);
47038c2ecf20Sopenharmony_ci
47048c2ecf20Sopenharmony_ci	if (work_done < budget && napi_complete_done(napi, work_done))
47058c2ecf20Sopenharmony_ci		rtl_irq_enable(tp);
47068c2ecf20Sopenharmony_ci
47078c2ecf20Sopenharmony_ci	return work_done;
47088c2ecf20Sopenharmony_ci}
47098c2ecf20Sopenharmony_ci
47108c2ecf20Sopenharmony_cistatic void r8169_phylink_handler(struct net_device *ndev)
47118c2ecf20Sopenharmony_ci{
47128c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = netdev_priv(ndev);
47138c2ecf20Sopenharmony_ci	struct device *d = tp_to_dev(tp);
47148c2ecf20Sopenharmony_ci
47158c2ecf20Sopenharmony_ci	if (netif_carrier_ok(ndev)) {
47168c2ecf20Sopenharmony_ci		rtl_link_chg_patch(tp);
47178c2ecf20Sopenharmony_ci		pm_request_resume(d);
47188c2ecf20Sopenharmony_ci		netif_wake_queue(tp->dev);
47198c2ecf20Sopenharmony_ci	} else {
47208c2ecf20Sopenharmony_ci		/* In few cases rx is broken after link-down otherwise */
47218c2ecf20Sopenharmony_ci		if (rtl_is_8125(tp))
47228c2ecf20Sopenharmony_ci			rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_NO_QUEUE_WAKE);
47238c2ecf20Sopenharmony_ci		pm_runtime_idle(d);
47248c2ecf20Sopenharmony_ci	}
47258c2ecf20Sopenharmony_ci
47268c2ecf20Sopenharmony_ci	if (net_ratelimit())
47278c2ecf20Sopenharmony_ci		phy_print_status(tp->phydev);
47288c2ecf20Sopenharmony_ci}
47298c2ecf20Sopenharmony_ci
47308c2ecf20Sopenharmony_cistatic int r8169_phy_connect(struct rtl8169_private *tp)
47318c2ecf20Sopenharmony_ci{
47328c2ecf20Sopenharmony_ci	struct phy_device *phydev = tp->phydev;
47338c2ecf20Sopenharmony_ci	phy_interface_t phy_mode;
47348c2ecf20Sopenharmony_ci	int ret;
47358c2ecf20Sopenharmony_ci
47368c2ecf20Sopenharmony_ci	phy_mode = tp->supports_gmii ? PHY_INTERFACE_MODE_GMII :
47378c2ecf20Sopenharmony_ci		   PHY_INTERFACE_MODE_MII;
47388c2ecf20Sopenharmony_ci
47398c2ecf20Sopenharmony_ci	ret = phy_connect_direct(tp->dev, phydev, r8169_phylink_handler,
47408c2ecf20Sopenharmony_ci				 phy_mode);
47418c2ecf20Sopenharmony_ci	if (ret)
47428c2ecf20Sopenharmony_ci		return ret;
47438c2ecf20Sopenharmony_ci
47448c2ecf20Sopenharmony_ci	if (!tp->supports_gmii)
47458c2ecf20Sopenharmony_ci		phy_set_max_speed(phydev, SPEED_100);
47468c2ecf20Sopenharmony_ci
47478c2ecf20Sopenharmony_ci	phy_attached_info(phydev);
47488c2ecf20Sopenharmony_ci
47498c2ecf20Sopenharmony_ci	return 0;
47508c2ecf20Sopenharmony_ci}
47518c2ecf20Sopenharmony_ci
47528c2ecf20Sopenharmony_cistatic void rtl8169_down(struct rtl8169_private *tp)
47538c2ecf20Sopenharmony_ci{
47548c2ecf20Sopenharmony_ci	/* Clear all task flags */
47558c2ecf20Sopenharmony_ci	bitmap_zero(tp->wk.flags, RTL_FLAG_MAX);
47568c2ecf20Sopenharmony_ci
47578c2ecf20Sopenharmony_ci	phy_stop(tp->phydev);
47588c2ecf20Sopenharmony_ci
47598c2ecf20Sopenharmony_ci	rtl8169_update_counters(tp);
47608c2ecf20Sopenharmony_ci
47618c2ecf20Sopenharmony_ci	pci_clear_master(tp->pci_dev);
47628c2ecf20Sopenharmony_ci	rtl_pci_commit(tp);
47638c2ecf20Sopenharmony_ci
47648c2ecf20Sopenharmony_ci	rtl8169_cleanup(tp, true);
47658c2ecf20Sopenharmony_ci
47668c2ecf20Sopenharmony_ci	rtl_pll_power_down(tp);
47678c2ecf20Sopenharmony_ci}
47688c2ecf20Sopenharmony_ci
47698c2ecf20Sopenharmony_cistatic void rtl8169_up(struct rtl8169_private *tp)
47708c2ecf20Sopenharmony_ci{
47718c2ecf20Sopenharmony_ci	pci_set_master(tp->pci_dev);
47728c2ecf20Sopenharmony_ci	rtl_pll_power_up(tp);
47738c2ecf20Sopenharmony_ci	rtl8169_init_phy(tp);
47748c2ecf20Sopenharmony_ci	napi_enable(&tp->napi);
47758c2ecf20Sopenharmony_ci	set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags);
47768c2ecf20Sopenharmony_ci	rtl_reset_work(tp);
47778c2ecf20Sopenharmony_ci
47788c2ecf20Sopenharmony_ci	phy_start(tp->phydev);
47798c2ecf20Sopenharmony_ci}
47808c2ecf20Sopenharmony_ci
47818c2ecf20Sopenharmony_cistatic int rtl8169_close(struct net_device *dev)
47828c2ecf20Sopenharmony_ci{
47838c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = netdev_priv(dev);
47848c2ecf20Sopenharmony_ci	struct pci_dev *pdev = tp->pci_dev;
47858c2ecf20Sopenharmony_ci
47868c2ecf20Sopenharmony_ci	pm_runtime_get_sync(&pdev->dev);
47878c2ecf20Sopenharmony_ci
47888c2ecf20Sopenharmony_ci	netif_stop_queue(dev);
47898c2ecf20Sopenharmony_ci	rtl8169_down(tp);
47908c2ecf20Sopenharmony_ci	rtl8169_rx_clear(tp);
47918c2ecf20Sopenharmony_ci
47928c2ecf20Sopenharmony_ci	cancel_work(&tp->wk.work);
47938c2ecf20Sopenharmony_ci
47948c2ecf20Sopenharmony_ci	free_irq(pci_irq_vector(pdev, 0), tp);
47958c2ecf20Sopenharmony_ci
47968c2ecf20Sopenharmony_ci	phy_disconnect(tp->phydev);
47978c2ecf20Sopenharmony_ci
47988c2ecf20Sopenharmony_ci	dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
47998c2ecf20Sopenharmony_ci			  tp->RxPhyAddr);
48008c2ecf20Sopenharmony_ci	dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
48018c2ecf20Sopenharmony_ci			  tp->TxPhyAddr);
48028c2ecf20Sopenharmony_ci	tp->TxDescArray = NULL;
48038c2ecf20Sopenharmony_ci	tp->RxDescArray = NULL;
48048c2ecf20Sopenharmony_ci
48058c2ecf20Sopenharmony_ci	pm_runtime_put_sync(&pdev->dev);
48068c2ecf20Sopenharmony_ci
48078c2ecf20Sopenharmony_ci	return 0;
48088c2ecf20Sopenharmony_ci}
48098c2ecf20Sopenharmony_ci
48108c2ecf20Sopenharmony_ci#ifdef CONFIG_NET_POLL_CONTROLLER
48118c2ecf20Sopenharmony_cistatic void rtl8169_netpoll(struct net_device *dev)
48128c2ecf20Sopenharmony_ci{
48138c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = netdev_priv(dev);
48148c2ecf20Sopenharmony_ci
48158c2ecf20Sopenharmony_ci	rtl8169_interrupt(pci_irq_vector(tp->pci_dev, 0), tp);
48168c2ecf20Sopenharmony_ci}
48178c2ecf20Sopenharmony_ci#endif
48188c2ecf20Sopenharmony_ci
48198c2ecf20Sopenharmony_cistatic int rtl_open(struct net_device *dev)
48208c2ecf20Sopenharmony_ci{
48218c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = netdev_priv(dev);
48228c2ecf20Sopenharmony_ci	struct pci_dev *pdev = tp->pci_dev;
48238c2ecf20Sopenharmony_ci	int retval = -ENOMEM;
48248c2ecf20Sopenharmony_ci
48258c2ecf20Sopenharmony_ci	pm_runtime_get_sync(&pdev->dev);
48268c2ecf20Sopenharmony_ci
48278c2ecf20Sopenharmony_ci	/*
48288c2ecf20Sopenharmony_ci	 * Rx and Tx descriptors needs 256 bytes alignment.
48298c2ecf20Sopenharmony_ci	 * dma_alloc_coherent provides more.
48308c2ecf20Sopenharmony_ci	 */
48318c2ecf20Sopenharmony_ci	tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES,
48328c2ecf20Sopenharmony_ci					     &tp->TxPhyAddr, GFP_KERNEL);
48338c2ecf20Sopenharmony_ci	if (!tp->TxDescArray)
48348c2ecf20Sopenharmony_ci		goto err_pm_runtime_put;
48358c2ecf20Sopenharmony_ci
48368c2ecf20Sopenharmony_ci	tp->RxDescArray = dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES,
48378c2ecf20Sopenharmony_ci					     &tp->RxPhyAddr, GFP_KERNEL);
48388c2ecf20Sopenharmony_ci	if (!tp->RxDescArray)
48398c2ecf20Sopenharmony_ci		goto err_free_tx_0;
48408c2ecf20Sopenharmony_ci
48418c2ecf20Sopenharmony_ci	retval = rtl8169_init_ring(tp);
48428c2ecf20Sopenharmony_ci	if (retval < 0)
48438c2ecf20Sopenharmony_ci		goto err_free_rx_1;
48448c2ecf20Sopenharmony_ci
48458c2ecf20Sopenharmony_ci	rtl_request_firmware(tp);
48468c2ecf20Sopenharmony_ci
48478c2ecf20Sopenharmony_ci	retval = request_irq(pci_irq_vector(pdev, 0), rtl8169_interrupt,
48488c2ecf20Sopenharmony_ci			     IRQF_SHARED, dev->name, tp);
48498c2ecf20Sopenharmony_ci	if (retval < 0)
48508c2ecf20Sopenharmony_ci		goto err_release_fw_2;
48518c2ecf20Sopenharmony_ci
48528c2ecf20Sopenharmony_ci	retval = r8169_phy_connect(tp);
48538c2ecf20Sopenharmony_ci	if (retval)
48548c2ecf20Sopenharmony_ci		goto err_free_irq;
48558c2ecf20Sopenharmony_ci
48568c2ecf20Sopenharmony_ci	rtl8169_up(tp);
48578c2ecf20Sopenharmony_ci	rtl8169_init_counter_offsets(tp);
48588c2ecf20Sopenharmony_ci	netif_start_queue(dev);
48598c2ecf20Sopenharmony_ci
48608c2ecf20Sopenharmony_ci	pm_runtime_put_sync(&pdev->dev);
48618c2ecf20Sopenharmony_ciout:
48628c2ecf20Sopenharmony_ci	return retval;
48638c2ecf20Sopenharmony_ci
48648c2ecf20Sopenharmony_cierr_free_irq:
48658c2ecf20Sopenharmony_ci	free_irq(pci_irq_vector(pdev, 0), tp);
48668c2ecf20Sopenharmony_cierr_release_fw_2:
48678c2ecf20Sopenharmony_ci	rtl_release_firmware(tp);
48688c2ecf20Sopenharmony_ci	rtl8169_rx_clear(tp);
48698c2ecf20Sopenharmony_cierr_free_rx_1:
48708c2ecf20Sopenharmony_ci	dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
48718c2ecf20Sopenharmony_ci			  tp->RxPhyAddr);
48728c2ecf20Sopenharmony_ci	tp->RxDescArray = NULL;
48738c2ecf20Sopenharmony_cierr_free_tx_0:
48748c2ecf20Sopenharmony_ci	dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray,
48758c2ecf20Sopenharmony_ci			  tp->TxPhyAddr);
48768c2ecf20Sopenharmony_ci	tp->TxDescArray = NULL;
48778c2ecf20Sopenharmony_cierr_pm_runtime_put:
48788c2ecf20Sopenharmony_ci	pm_runtime_put_noidle(&pdev->dev);
48798c2ecf20Sopenharmony_ci	goto out;
48808c2ecf20Sopenharmony_ci}
48818c2ecf20Sopenharmony_ci
48828c2ecf20Sopenharmony_cistatic void
48838c2ecf20Sopenharmony_cirtl8169_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats)
48848c2ecf20Sopenharmony_ci{
48858c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = netdev_priv(dev);
48868c2ecf20Sopenharmony_ci	struct pci_dev *pdev = tp->pci_dev;
48878c2ecf20Sopenharmony_ci	struct rtl8169_counters *counters = tp->counters;
48888c2ecf20Sopenharmony_ci
48898c2ecf20Sopenharmony_ci	pm_runtime_get_noresume(&pdev->dev);
48908c2ecf20Sopenharmony_ci
48918c2ecf20Sopenharmony_ci	netdev_stats_to_stats64(stats, &dev->stats);
48928c2ecf20Sopenharmony_ci
48938c2ecf20Sopenharmony_ci	rtl_get_priv_stats(&tp->rx_stats, &stats->rx_packets, &stats->rx_bytes);
48948c2ecf20Sopenharmony_ci	rtl_get_priv_stats(&tp->tx_stats, &stats->tx_packets, &stats->tx_bytes);
48958c2ecf20Sopenharmony_ci
48968c2ecf20Sopenharmony_ci	/*
48978c2ecf20Sopenharmony_ci	 * Fetch additional counter values missing in stats collected by driver
48988c2ecf20Sopenharmony_ci	 * from tally counters.
48998c2ecf20Sopenharmony_ci	 */
49008c2ecf20Sopenharmony_ci	if (pm_runtime_active(&pdev->dev))
49018c2ecf20Sopenharmony_ci		rtl8169_update_counters(tp);
49028c2ecf20Sopenharmony_ci
49038c2ecf20Sopenharmony_ci	/*
49048c2ecf20Sopenharmony_ci	 * Subtract values fetched during initalization.
49058c2ecf20Sopenharmony_ci	 * See rtl8169_init_counter_offsets for a description why we do that.
49068c2ecf20Sopenharmony_ci	 */
49078c2ecf20Sopenharmony_ci	stats->tx_errors = le64_to_cpu(counters->tx_errors) -
49088c2ecf20Sopenharmony_ci		le64_to_cpu(tp->tc_offset.tx_errors);
49098c2ecf20Sopenharmony_ci	stats->collisions = le32_to_cpu(counters->tx_multi_collision) -
49108c2ecf20Sopenharmony_ci		le32_to_cpu(tp->tc_offset.tx_multi_collision);
49118c2ecf20Sopenharmony_ci	stats->tx_aborted_errors = le16_to_cpu(counters->tx_aborted) -
49128c2ecf20Sopenharmony_ci		le16_to_cpu(tp->tc_offset.tx_aborted);
49138c2ecf20Sopenharmony_ci	stats->rx_missed_errors = le16_to_cpu(counters->rx_missed) -
49148c2ecf20Sopenharmony_ci		le16_to_cpu(tp->tc_offset.rx_missed);
49158c2ecf20Sopenharmony_ci
49168c2ecf20Sopenharmony_ci	pm_runtime_put_noidle(&pdev->dev);
49178c2ecf20Sopenharmony_ci}
49188c2ecf20Sopenharmony_ci
49198c2ecf20Sopenharmony_cistatic void rtl8169_net_suspend(struct rtl8169_private *tp)
49208c2ecf20Sopenharmony_ci{
49218c2ecf20Sopenharmony_ci	netif_device_detach(tp->dev);
49228c2ecf20Sopenharmony_ci
49238c2ecf20Sopenharmony_ci	if (netif_running(tp->dev))
49248c2ecf20Sopenharmony_ci		rtl8169_down(tp);
49258c2ecf20Sopenharmony_ci}
49268c2ecf20Sopenharmony_ci
49278c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
49288c2ecf20Sopenharmony_ci
49298c2ecf20Sopenharmony_cistatic int rtl8169_net_resume(struct rtl8169_private *tp)
49308c2ecf20Sopenharmony_ci{
49318c2ecf20Sopenharmony_ci	rtl_rar_set(tp, tp->dev->dev_addr);
49328c2ecf20Sopenharmony_ci
49338c2ecf20Sopenharmony_ci	if (tp->TxDescArray)
49348c2ecf20Sopenharmony_ci		rtl8169_up(tp);
49358c2ecf20Sopenharmony_ci
49368c2ecf20Sopenharmony_ci	netif_device_attach(tp->dev);
49378c2ecf20Sopenharmony_ci
49388c2ecf20Sopenharmony_ci	return 0;
49398c2ecf20Sopenharmony_ci}
49408c2ecf20Sopenharmony_ci
49418c2ecf20Sopenharmony_cistatic int __maybe_unused rtl8169_suspend(struct device *device)
49428c2ecf20Sopenharmony_ci{
49438c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = dev_get_drvdata(device);
49448c2ecf20Sopenharmony_ci
49458c2ecf20Sopenharmony_ci	rtnl_lock();
49468c2ecf20Sopenharmony_ci	rtl8169_net_suspend(tp);
49478c2ecf20Sopenharmony_ci	if (!device_may_wakeup(tp_to_dev(tp)))
49488c2ecf20Sopenharmony_ci		clk_disable_unprepare(tp->clk);
49498c2ecf20Sopenharmony_ci	rtnl_unlock();
49508c2ecf20Sopenharmony_ci
49518c2ecf20Sopenharmony_ci	return 0;
49528c2ecf20Sopenharmony_ci}
49538c2ecf20Sopenharmony_ci
49548c2ecf20Sopenharmony_cistatic int __maybe_unused rtl8169_resume(struct device *device)
49558c2ecf20Sopenharmony_ci{
49568c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = dev_get_drvdata(device);
49578c2ecf20Sopenharmony_ci
49588c2ecf20Sopenharmony_ci	if (!device_may_wakeup(tp_to_dev(tp)))
49598c2ecf20Sopenharmony_ci		clk_prepare_enable(tp->clk);
49608c2ecf20Sopenharmony_ci
49618c2ecf20Sopenharmony_ci	/* Reportedly at least Asus X453MA truncates packets otherwise */
49628c2ecf20Sopenharmony_ci	if (tp->mac_version == RTL_GIGA_MAC_VER_37)
49638c2ecf20Sopenharmony_ci		rtl_init_rxcfg(tp);
49648c2ecf20Sopenharmony_ci
49658c2ecf20Sopenharmony_ci	return rtl8169_net_resume(tp);
49668c2ecf20Sopenharmony_ci}
49678c2ecf20Sopenharmony_ci
49688c2ecf20Sopenharmony_cistatic int rtl8169_runtime_suspend(struct device *device)
49698c2ecf20Sopenharmony_ci{
49708c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = dev_get_drvdata(device);
49718c2ecf20Sopenharmony_ci
49728c2ecf20Sopenharmony_ci	if (!tp->TxDescArray) {
49738c2ecf20Sopenharmony_ci		netif_device_detach(tp->dev);
49748c2ecf20Sopenharmony_ci		return 0;
49758c2ecf20Sopenharmony_ci	}
49768c2ecf20Sopenharmony_ci
49778c2ecf20Sopenharmony_ci	rtnl_lock();
49788c2ecf20Sopenharmony_ci	__rtl8169_set_wol(tp, WAKE_PHY);
49798c2ecf20Sopenharmony_ci	rtl8169_net_suspend(tp);
49808c2ecf20Sopenharmony_ci	rtnl_unlock();
49818c2ecf20Sopenharmony_ci
49828c2ecf20Sopenharmony_ci	return 0;
49838c2ecf20Sopenharmony_ci}
49848c2ecf20Sopenharmony_ci
49858c2ecf20Sopenharmony_cistatic int rtl8169_runtime_resume(struct device *device)
49868c2ecf20Sopenharmony_ci{
49878c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = dev_get_drvdata(device);
49888c2ecf20Sopenharmony_ci
49898c2ecf20Sopenharmony_ci	__rtl8169_set_wol(tp, tp->saved_wolopts);
49908c2ecf20Sopenharmony_ci
49918c2ecf20Sopenharmony_ci	return rtl8169_net_resume(tp);
49928c2ecf20Sopenharmony_ci}
49938c2ecf20Sopenharmony_ci
49948c2ecf20Sopenharmony_cistatic int rtl8169_runtime_idle(struct device *device)
49958c2ecf20Sopenharmony_ci{
49968c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = dev_get_drvdata(device);
49978c2ecf20Sopenharmony_ci
49988c2ecf20Sopenharmony_ci	if (!netif_running(tp->dev) || !netif_carrier_ok(tp->dev))
49998c2ecf20Sopenharmony_ci		pm_schedule_suspend(device, 10000);
50008c2ecf20Sopenharmony_ci
50018c2ecf20Sopenharmony_ci	return -EBUSY;
50028c2ecf20Sopenharmony_ci}
50038c2ecf20Sopenharmony_ci
50048c2ecf20Sopenharmony_cistatic const struct dev_pm_ops rtl8169_pm_ops = {
50058c2ecf20Sopenharmony_ci	SET_SYSTEM_SLEEP_PM_OPS(rtl8169_suspend, rtl8169_resume)
50068c2ecf20Sopenharmony_ci	SET_RUNTIME_PM_OPS(rtl8169_runtime_suspend, rtl8169_runtime_resume,
50078c2ecf20Sopenharmony_ci			   rtl8169_runtime_idle)
50088c2ecf20Sopenharmony_ci};
50098c2ecf20Sopenharmony_ci
50108c2ecf20Sopenharmony_ci#endif /* CONFIG_PM */
50118c2ecf20Sopenharmony_ci
50128c2ecf20Sopenharmony_cistatic void rtl_wol_shutdown_quirk(struct rtl8169_private *tp)
50138c2ecf20Sopenharmony_ci{
50148c2ecf20Sopenharmony_ci	/* WoL fails with 8168b when the receiver is disabled. */
50158c2ecf20Sopenharmony_ci	switch (tp->mac_version) {
50168c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_11:
50178c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_12:
50188c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_17:
50198c2ecf20Sopenharmony_ci		pci_clear_master(tp->pci_dev);
50208c2ecf20Sopenharmony_ci
50218c2ecf20Sopenharmony_ci		RTL_W8(tp, ChipCmd, CmdRxEnb);
50228c2ecf20Sopenharmony_ci		rtl_pci_commit(tp);
50238c2ecf20Sopenharmony_ci		break;
50248c2ecf20Sopenharmony_ci	default:
50258c2ecf20Sopenharmony_ci		break;
50268c2ecf20Sopenharmony_ci	}
50278c2ecf20Sopenharmony_ci}
50288c2ecf20Sopenharmony_ci
50298c2ecf20Sopenharmony_cistatic void rtl_shutdown(struct pci_dev *pdev)
50308c2ecf20Sopenharmony_ci{
50318c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = pci_get_drvdata(pdev);
50328c2ecf20Sopenharmony_ci
50338c2ecf20Sopenharmony_ci	rtnl_lock();
50348c2ecf20Sopenharmony_ci	rtl8169_net_suspend(tp);
50358c2ecf20Sopenharmony_ci	rtnl_unlock();
50368c2ecf20Sopenharmony_ci
50378c2ecf20Sopenharmony_ci	/* Restore original MAC address */
50388c2ecf20Sopenharmony_ci	rtl_rar_set(tp, tp->dev->perm_addr);
50398c2ecf20Sopenharmony_ci
50408c2ecf20Sopenharmony_ci	if (system_state == SYSTEM_POWER_OFF) {
50418c2ecf20Sopenharmony_ci		if (tp->saved_wolopts) {
50428c2ecf20Sopenharmony_ci			rtl_wol_suspend_quirk(tp);
50438c2ecf20Sopenharmony_ci			rtl_wol_shutdown_quirk(tp);
50448c2ecf20Sopenharmony_ci		}
50458c2ecf20Sopenharmony_ci
50468c2ecf20Sopenharmony_ci		pci_wake_from_d3(pdev, true);
50478c2ecf20Sopenharmony_ci		pci_set_power_state(pdev, PCI_D3hot);
50488c2ecf20Sopenharmony_ci	}
50498c2ecf20Sopenharmony_ci}
50508c2ecf20Sopenharmony_ci
50518c2ecf20Sopenharmony_cistatic void rtl_remove_one(struct pci_dev *pdev)
50528c2ecf20Sopenharmony_ci{
50538c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = pci_get_drvdata(pdev);
50548c2ecf20Sopenharmony_ci
50558c2ecf20Sopenharmony_ci	if (pci_dev_run_wake(pdev))
50568c2ecf20Sopenharmony_ci		pm_runtime_get_noresume(&pdev->dev);
50578c2ecf20Sopenharmony_ci
50588c2ecf20Sopenharmony_ci	cancel_work_sync(&tp->wk.work);
50598c2ecf20Sopenharmony_ci
50608c2ecf20Sopenharmony_ci	unregister_netdev(tp->dev);
50618c2ecf20Sopenharmony_ci
50628c2ecf20Sopenharmony_ci	if (r8168_check_dash(tp))
50638c2ecf20Sopenharmony_ci		rtl8168_driver_stop(tp);
50648c2ecf20Sopenharmony_ci
50658c2ecf20Sopenharmony_ci	rtl_release_firmware(tp);
50668c2ecf20Sopenharmony_ci
50678c2ecf20Sopenharmony_ci	/* restore original MAC address */
50688c2ecf20Sopenharmony_ci	rtl_rar_set(tp, tp->dev->perm_addr);
50698c2ecf20Sopenharmony_ci}
50708c2ecf20Sopenharmony_ci
50718c2ecf20Sopenharmony_cistatic const struct net_device_ops rtl_netdev_ops = {
50728c2ecf20Sopenharmony_ci	.ndo_open		= rtl_open,
50738c2ecf20Sopenharmony_ci	.ndo_stop		= rtl8169_close,
50748c2ecf20Sopenharmony_ci	.ndo_get_stats64	= rtl8169_get_stats64,
50758c2ecf20Sopenharmony_ci	.ndo_start_xmit		= rtl8169_start_xmit,
50768c2ecf20Sopenharmony_ci	.ndo_features_check	= rtl8169_features_check,
50778c2ecf20Sopenharmony_ci	.ndo_tx_timeout		= rtl8169_tx_timeout,
50788c2ecf20Sopenharmony_ci	.ndo_validate_addr	= eth_validate_addr,
50798c2ecf20Sopenharmony_ci	.ndo_change_mtu		= rtl8169_change_mtu,
50808c2ecf20Sopenharmony_ci	.ndo_fix_features	= rtl8169_fix_features,
50818c2ecf20Sopenharmony_ci	.ndo_set_features	= rtl8169_set_features,
50828c2ecf20Sopenharmony_ci	.ndo_set_mac_address	= rtl_set_mac_address,
50838c2ecf20Sopenharmony_ci	.ndo_do_ioctl		= phy_do_ioctl_running,
50848c2ecf20Sopenharmony_ci	.ndo_set_rx_mode	= rtl_set_rx_mode,
50858c2ecf20Sopenharmony_ci#ifdef CONFIG_NET_POLL_CONTROLLER
50868c2ecf20Sopenharmony_ci	.ndo_poll_controller	= rtl8169_netpoll,
50878c2ecf20Sopenharmony_ci#endif
50888c2ecf20Sopenharmony_ci
50898c2ecf20Sopenharmony_ci};
50908c2ecf20Sopenharmony_ci
50918c2ecf20Sopenharmony_cistatic void rtl_set_irq_mask(struct rtl8169_private *tp)
50928c2ecf20Sopenharmony_ci{
50938c2ecf20Sopenharmony_ci	tp->irq_mask = RxOK | RxErr | TxOK | TxErr | LinkChg;
50948c2ecf20Sopenharmony_ci
50958c2ecf20Sopenharmony_ci	if (tp->mac_version <= RTL_GIGA_MAC_VER_06)
50968c2ecf20Sopenharmony_ci		tp->irq_mask |= SYSErr | RxOverflow | RxFIFOOver;
50978c2ecf20Sopenharmony_ci	else if (tp->mac_version == RTL_GIGA_MAC_VER_11)
50988c2ecf20Sopenharmony_ci		/* special workaround needed */
50998c2ecf20Sopenharmony_ci		tp->irq_mask |= RxFIFOOver;
51008c2ecf20Sopenharmony_ci	else
51018c2ecf20Sopenharmony_ci		tp->irq_mask |= RxOverflow;
51028c2ecf20Sopenharmony_ci}
51038c2ecf20Sopenharmony_ci
51048c2ecf20Sopenharmony_cistatic int rtl_alloc_irq(struct rtl8169_private *tp)
51058c2ecf20Sopenharmony_ci{
51068c2ecf20Sopenharmony_ci	unsigned int flags;
51078c2ecf20Sopenharmony_ci
51088c2ecf20Sopenharmony_ci	switch (tp->mac_version) {
51098c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06:
51108c2ecf20Sopenharmony_ci		rtl_unlock_config_regs(tp);
51118c2ecf20Sopenharmony_ci		RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~MSIEnable);
51128c2ecf20Sopenharmony_ci		rtl_lock_config_regs(tp);
51138c2ecf20Sopenharmony_ci		fallthrough;
51148c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_07 ... RTL_GIGA_MAC_VER_17:
51158c2ecf20Sopenharmony_ci		flags = PCI_IRQ_LEGACY;
51168c2ecf20Sopenharmony_ci		break;
51178c2ecf20Sopenharmony_ci	default:
51188c2ecf20Sopenharmony_ci		flags = PCI_IRQ_ALL_TYPES;
51198c2ecf20Sopenharmony_ci		break;
51208c2ecf20Sopenharmony_ci	}
51218c2ecf20Sopenharmony_ci
51228c2ecf20Sopenharmony_ci	return pci_alloc_irq_vectors(tp->pci_dev, 1, 1, flags);
51238c2ecf20Sopenharmony_ci}
51248c2ecf20Sopenharmony_ci
51258c2ecf20Sopenharmony_cistatic void rtl_read_mac_address(struct rtl8169_private *tp,
51268c2ecf20Sopenharmony_ci				 u8 mac_addr[ETH_ALEN])
51278c2ecf20Sopenharmony_ci{
51288c2ecf20Sopenharmony_ci	/* Get MAC address */
51298c2ecf20Sopenharmony_ci	if (rtl_is_8168evl_up(tp) && tp->mac_version != RTL_GIGA_MAC_VER_34) {
51308c2ecf20Sopenharmony_ci		u32 value = rtl_eri_read(tp, 0xe0);
51318c2ecf20Sopenharmony_ci
51328c2ecf20Sopenharmony_ci		mac_addr[0] = (value >>  0) & 0xff;
51338c2ecf20Sopenharmony_ci		mac_addr[1] = (value >>  8) & 0xff;
51348c2ecf20Sopenharmony_ci		mac_addr[2] = (value >> 16) & 0xff;
51358c2ecf20Sopenharmony_ci		mac_addr[3] = (value >> 24) & 0xff;
51368c2ecf20Sopenharmony_ci
51378c2ecf20Sopenharmony_ci		value = rtl_eri_read(tp, 0xe4);
51388c2ecf20Sopenharmony_ci		mac_addr[4] = (value >>  0) & 0xff;
51398c2ecf20Sopenharmony_ci		mac_addr[5] = (value >>  8) & 0xff;
51408c2ecf20Sopenharmony_ci	} else if (rtl_is_8125(tp)) {
51418c2ecf20Sopenharmony_ci		rtl_read_mac_from_reg(tp, mac_addr, MAC0_BKP);
51428c2ecf20Sopenharmony_ci	}
51438c2ecf20Sopenharmony_ci}
51448c2ecf20Sopenharmony_ci
51458c2ecf20Sopenharmony_ciDECLARE_RTL_COND(rtl_link_list_ready_cond)
51468c2ecf20Sopenharmony_ci{
51478c2ecf20Sopenharmony_ci	return RTL_R8(tp, MCU) & LINK_LIST_RDY;
51488c2ecf20Sopenharmony_ci}
51498c2ecf20Sopenharmony_ci
51508c2ecf20Sopenharmony_cistatic void r8168g_wait_ll_share_fifo_ready(struct rtl8169_private *tp)
51518c2ecf20Sopenharmony_ci{
51528c2ecf20Sopenharmony_ci	rtl_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42);
51538c2ecf20Sopenharmony_ci}
51548c2ecf20Sopenharmony_ci
51558c2ecf20Sopenharmony_cistatic int r8169_mdio_read_reg(struct mii_bus *mii_bus, int phyaddr, int phyreg)
51568c2ecf20Sopenharmony_ci{
51578c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = mii_bus->priv;
51588c2ecf20Sopenharmony_ci
51598c2ecf20Sopenharmony_ci	if (phyaddr > 0)
51608c2ecf20Sopenharmony_ci		return -ENODEV;
51618c2ecf20Sopenharmony_ci
51628c2ecf20Sopenharmony_ci	return rtl_readphy(tp, phyreg);
51638c2ecf20Sopenharmony_ci}
51648c2ecf20Sopenharmony_ci
51658c2ecf20Sopenharmony_cistatic int r8169_mdio_write_reg(struct mii_bus *mii_bus, int phyaddr,
51668c2ecf20Sopenharmony_ci				int phyreg, u16 val)
51678c2ecf20Sopenharmony_ci{
51688c2ecf20Sopenharmony_ci	struct rtl8169_private *tp = mii_bus->priv;
51698c2ecf20Sopenharmony_ci
51708c2ecf20Sopenharmony_ci	if (phyaddr > 0)
51718c2ecf20Sopenharmony_ci		return -ENODEV;
51728c2ecf20Sopenharmony_ci
51738c2ecf20Sopenharmony_ci	rtl_writephy(tp, phyreg, val);
51748c2ecf20Sopenharmony_ci
51758c2ecf20Sopenharmony_ci	return 0;
51768c2ecf20Sopenharmony_ci}
51778c2ecf20Sopenharmony_ci
51788c2ecf20Sopenharmony_cistatic int r8169_mdio_register(struct rtl8169_private *tp)
51798c2ecf20Sopenharmony_ci{
51808c2ecf20Sopenharmony_ci	struct pci_dev *pdev = tp->pci_dev;
51818c2ecf20Sopenharmony_ci	struct mii_bus *new_bus;
51828c2ecf20Sopenharmony_ci	int ret;
51838c2ecf20Sopenharmony_ci
51848c2ecf20Sopenharmony_ci	new_bus = devm_mdiobus_alloc(&pdev->dev);
51858c2ecf20Sopenharmony_ci	if (!new_bus)
51868c2ecf20Sopenharmony_ci		return -ENOMEM;
51878c2ecf20Sopenharmony_ci
51888c2ecf20Sopenharmony_ci	new_bus->name = "r8169";
51898c2ecf20Sopenharmony_ci	new_bus->priv = tp;
51908c2ecf20Sopenharmony_ci	new_bus->parent = &pdev->dev;
51918c2ecf20Sopenharmony_ci	new_bus->irq[0] = PHY_IGNORE_INTERRUPT;
51928c2ecf20Sopenharmony_ci	snprintf(new_bus->id, MII_BUS_ID_SIZE, "r8169-%x-%x",
51938c2ecf20Sopenharmony_ci		 pci_domain_nr(pdev->bus), pci_dev_id(pdev));
51948c2ecf20Sopenharmony_ci
51958c2ecf20Sopenharmony_ci	new_bus->read = r8169_mdio_read_reg;
51968c2ecf20Sopenharmony_ci	new_bus->write = r8169_mdio_write_reg;
51978c2ecf20Sopenharmony_ci
51988c2ecf20Sopenharmony_ci	ret = devm_mdiobus_register(&pdev->dev, new_bus);
51998c2ecf20Sopenharmony_ci	if (ret)
52008c2ecf20Sopenharmony_ci		return ret;
52018c2ecf20Sopenharmony_ci
52028c2ecf20Sopenharmony_ci	tp->phydev = mdiobus_get_phy(new_bus, 0);
52038c2ecf20Sopenharmony_ci	if (!tp->phydev) {
52048c2ecf20Sopenharmony_ci		return -ENODEV;
52058c2ecf20Sopenharmony_ci	} else if (!tp->phydev->drv) {
52068c2ecf20Sopenharmony_ci		/* Most chip versions fail with the genphy driver.
52078c2ecf20Sopenharmony_ci		 * Therefore ensure that the dedicated PHY driver is loaded.
52088c2ecf20Sopenharmony_ci		 */
52098c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "no dedicated PHY driver found for PHY ID 0x%08x, maybe realtek.ko needs to be added to initramfs?\n",
52108c2ecf20Sopenharmony_ci			tp->phydev->phy_id);
52118c2ecf20Sopenharmony_ci		return -EUNATCH;
52128c2ecf20Sopenharmony_ci	}
52138c2ecf20Sopenharmony_ci
52148c2ecf20Sopenharmony_ci	/* PHY will be woken up in rtl_open() */
52158c2ecf20Sopenharmony_ci	phy_suspend(tp->phydev);
52168c2ecf20Sopenharmony_ci
52178c2ecf20Sopenharmony_ci	return 0;
52188c2ecf20Sopenharmony_ci}
52198c2ecf20Sopenharmony_ci
52208c2ecf20Sopenharmony_cistatic void rtl_hw_init_8168g(struct rtl8169_private *tp)
52218c2ecf20Sopenharmony_ci{
52228c2ecf20Sopenharmony_ci	rtl_enable_rxdvgate(tp);
52238c2ecf20Sopenharmony_ci
52248c2ecf20Sopenharmony_ci	RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) & ~(CmdTxEnb | CmdRxEnb));
52258c2ecf20Sopenharmony_ci	msleep(1);
52268c2ecf20Sopenharmony_ci	RTL_W8(tp, MCU, RTL_R8(tp, MCU) & ~NOW_IS_OOB);
52278c2ecf20Sopenharmony_ci
52288c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xe8de, BIT(14), 0);
52298c2ecf20Sopenharmony_ci	r8168g_wait_ll_share_fifo_ready(tp);
52308c2ecf20Sopenharmony_ci
52318c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xe8de, 0, BIT(15));
52328c2ecf20Sopenharmony_ci	r8168g_wait_ll_share_fifo_ready(tp);
52338c2ecf20Sopenharmony_ci}
52348c2ecf20Sopenharmony_ci
52358c2ecf20Sopenharmony_cistatic void rtl_hw_init_8125(struct rtl8169_private *tp)
52368c2ecf20Sopenharmony_ci{
52378c2ecf20Sopenharmony_ci	rtl_enable_rxdvgate(tp);
52388c2ecf20Sopenharmony_ci
52398c2ecf20Sopenharmony_ci	RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) & ~(CmdTxEnb | CmdRxEnb));
52408c2ecf20Sopenharmony_ci	msleep(1);
52418c2ecf20Sopenharmony_ci	RTL_W8(tp, MCU, RTL_R8(tp, MCU) & ~NOW_IS_OOB);
52428c2ecf20Sopenharmony_ci
52438c2ecf20Sopenharmony_ci	r8168_mac_ocp_modify(tp, 0xe8de, BIT(14), 0);
52448c2ecf20Sopenharmony_ci	r8168g_wait_ll_share_fifo_ready(tp);
52458c2ecf20Sopenharmony_ci
52468c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xc0aa, 0x07d0);
52478c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xc0a6, 0x0150);
52488c2ecf20Sopenharmony_ci	r8168_mac_ocp_write(tp, 0xc01e, 0x5555);
52498c2ecf20Sopenharmony_ci	r8168g_wait_ll_share_fifo_ready(tp);
52508c2ecf20Sopenharmony_ci}
52518c2ecf20Sopenharmony_ci
52528c2ecf20Sopenharmony_cistatic void rtl_hw_initialize(struct rtl8169_private *tp)
52538c2ecf20Sopenharmony_ci{
52548c2ecf20Sopenharmony_ci	switch (tp->mac_version) {
52558c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_49 ... RTL_GIGA_MAC_VER_52:
52568c2ecf20Sopenharmony_ci		rtl8168ep_stop_cmac(tp);
52578c2ecf20Sopenharmony_ci		fallthrough;
52588c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_48:
52598c2ecf20Sopenharmony_ci		rtl_hw_init_8168g(tp);
52608c2ecf20Sopenharmony_ci		break;
52618c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_60 ... RTL_GIGA_MAC_VER_63:
52628c2ecf20Sopenharmony_ci		rtl_hw_init_8125(tp);
52638c2ecf20Sopenharmony_ci		break;
52648c2ecf20Sopenharmony_ci	default:
52658c2ecf20Sopenharmony_ci		break;
52668c2ecf20Sopenharmony_ci	}
52678c2ecf20Sopenharmony_ci}
52688c2ecf20Sopenharmony_ci
52698c2ecf20Sopenharmony_cistatic int rtl_jumbo_max(struct rtl8169_private *tp)
52708c2ecf20Sopenharmony_ci{
52718c2ecf20Sopenharmony_ci	/* Non-GBit versions don't support jumbo frames */
52728c2ecf20Sopenharmony_ci	if (!tp->supports_gmii)
52738c2ecf20Sopenharmony_ci		return 0;
52748c2ecf20Sopenharmony_ci
52758c2ecf20Sopenharmony_ci	switch (tp->mac_version) {
52768c2ecf20Sopenharmony_ci	/* RTL8169 */
52778c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_02 ... RTL_GIGA_MAC_VER_06:
52788c2ecf20Sopenharmony_ci		return JUMBO_7K;
52798c2ecf20Sopenharmony_ci	/* RTL8168b */
52808c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_11:
52818c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_12:
52828c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_17:
52838c2ecf20Sopenharmony_ci		return JUMBO_4K;
52848c2ecf20Sopenharmony_ci	/* RTL8168c */
52858c2ecf20Sopenharmony_ci	case RTL_GIGA_MAC_VER_18 ... RTL_GIGA_MAC_VER_24:
52868c2ecf20Sopenharmony_ci		return JUMBO_6K;
52878c2ecf20Sopenharmony_ci	default:
52888c2ecf20Sopenharmony_ci		return JUMBO_9K;
52898c2ecf20Sopenharmony_ci	}
52908c2ecf20Sopenharmony_ci}
52918c2ecf20Sopenharmony_ci
52928c2ecf20Sopenharmony_cistatic void rtl_disable_clk(void *data)
52938c2ecf20Sopenharmony_ci{
52948c2ecf20Sopenharmony_ci	clk_disable_unprepare(data);
52958c2ecf20Sopenharmony_ci}
52968c2ecf20Sopenharmony_ci
52978c2ecf20Sopenharmony_cistatic int rtl_get_ether_clk(struct rtl8169_private *tp)
52988c2ecf20Sopenharmony_ci{
52998c2ecf20Sopenharmony_ci	struct device *d = tp_to_dev(tp);
53008c2ecf20Sopenharmony_ci	struct clk *clk;
53018c2ecf20Sopenharmony_ci	int rc;
53028c2ecf20Sopenharmony_ci
53038c2ecf20Sopenharmony_ci	clk = devm_clk_get(d, "ether_clk");
53048c2ecf20Sopenharmony_ci	if (IS_ERR(clk)) {
53058c2ecf20Sopenharmony_ci		rc = PTR_ERR(clk);
53068c2ecf20Sopenharmony_ci		if (rc == -ENOENT)
53078c2ecf20Sopenharmony_ci			/* clk-core allows NULL (for suspend / resume) */
53088c2ecf20Sopenharmony_ci			rc = 0;
53098c2ecf20Sopenharmony_ci		else if (rc != -EPROBE_DEFER)
53108c2ecf20Sopenharmony_ci			dev_err(d, "failed to get clk: %d\n", rc);
53118c2ecf20Sopenharmony_ci	} else {
53128c2ecf20Sopenharmony_ci		tp->clk = clk;
53138c2ecf20Sopenharmony_ci		rc = clk_prepare_enable(clk);
53148c2ecf20Sopenharmony_ci		if (rc)
53158c2ecf20Sopenharmony_ci			dev_err(d, "failed to enable clk: %d\n", rc);
53168c2ecf20Sopenharmony_ci		else
53178c2ecf20Sopenharmony_ci			rc = devm_add_action_or_reset(d, rtl_disable_clk, clk);
53188c2ecf20Sopenharmony_ci	}
53198c2ecf20Sopenharmony_ci
53208c2ecf20Sopenharmony_ci	return rc;
53218c2ecf20Sopenharmony_ci}
53228c2ecf20Sopenharmony_ci
53238c2ecf20Sopenharmony_cistatic void rtl_init_mac_address(struct rtl8169_private *tp)
53248c2ecf20Sopenharmony_ci{
53258c2ecf20Sopenharmony_ci	struct net_device *dev = tp->dev;
53268c2ecf20Sopenharmony_ci	u8 *mac_addr = dev->dev_addr;
53278c2ecf20Sopenharmony_ci	int rc;
53288c2ecf20Sopenharmony_ci
53298c2ecf20Sopenharmony_ci	rc = eth_platform_get_mac_address(tp_to_dev(tp), mac_addr);
53308c2ecf20Sopenharmony_ci	if (!rc)
53318c2ecf20Sopenharmony_ci		goto done;
53328c2ecf20Sopenharmony_ci
53338c2ecf20Sopenharmony_ci	rtl_read_mac_address(tp, mac_addr);
53348c2ecf20Sopenharmony_ci	if (is_valid_ether_addr(mac_addr))
53358c2ecf20Sopenharmony_ci		goto done;
53368c2ecf20Sopenharmony_ci
53378c2ecf20Sopenharmony_ci	rtl_read_mac_from_reg(tp, mac_addr, MAC0);
53388c2ecf20Sopenharmony_ci	if (is_valid_ether_addr(mac_addr))
53398c2ecf20Sopenharmony_ci		goto done;
53408c2ecf20Sopenharmony_ci
53418c2ecf20Sopenharmony_ci	eth_hw_addr_random(dev);
53428c2ecf20Sopenharmony_ci	dev_warn(tp_to_dev(tp), "can't read MAC address, setting random one\n");
53438c2ecf20Sopenharmony_cidone:
53448c2ecf20Sopenharmony_ci	rtl_rar_set(tp, mac_addr);
53458c2ecf20Sopenharmony_ci}
53468c2ecf20Sopenharmony_ci
53478c2ecf20Sopenharmony_cistatic int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
53488c2ecf20Sopenharmony_ci{
53498c2ecf20Sopenharmony_ci	struct rtl8169_private *tp;
53508c2ecf20Sopenharmony_ci	int jumbo_max, region, rc;
53518c2ecf20Sopenharmony_ci	enum mac_version chipset;
53528c2ecf20Sopenharmony_ci	struct net_device *dev;
53538c2ecf20Sopenharmony_ci	u16 xid;
53548c2ecf20Sopenharmony_ci
53558c2ecf20Sopenharmony_ci	dev = devm_alloc_etherdev(&pdev->dev, sizeof (*tp));
53568c2ecf20Sopenharmony_ci	if (!dev)
53578c2ecf20Sopenharmony_ci		return -ENOMEM;
53588c2ecf20Sopenharmony_ci
53598c2ecf20Sopenharmony_ci	SET_NETDEV_DEV(dev, &pdev->dev);
53608c2ecf20Sopenharmony_ci	dev->netdev_ops = &rtl_netdev_ops;
53618c2ecf20Sopenharmony_ci	tp = netdev_priv(dev);
53628c2ecf20Sopenharmony_ci	tp->dev = dev;
53638c2ecf20Sopenharmony_ci	tp->pci_dev = pdev;
53648c2ecf20Sopenharmony_ci	tp->supports_gmii = ent->driver_data == RTL_CFG_NO_GBIT ? 0 : 1;
53658c2ecf20Sopenharmony_ci	tp->eee_adv = -1;
53668c2ecf20Sopenharmony_ci	tp->ocp_base = OCP_STD_PHY_BASE;
53678c2ecf20Sopenharmony_ci
53688c2ecf20Sopenharmony_ci	/* Get the *optional* external "ether_clk" used on some boards */
53698c2ecf20Sopenharmony_ci	rc = rtl_get_ether_clk(tp);
53708c2ecf20Sopenharmony_ci	if (rc)
53718c2ecf20Sopenharmony_ci		return rc;
53728c2ecf20Sopenharmony_ci
53738c2ecf20Sopenharmony_ci	/* Disable ASPM completely as that cause random device stop working
53748c2ecf20Sopenharmony_ci	 * problems as well as full system hangs for some PCIe devices users.
53758c2ecf20Sopenharmony_ci	 */
53768c2ecf20Sopenharmony_ci	rc = pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S |
53778c2ecf20Sopenharmony_ci					  PCIE_LINK_STATE_L1);
53788c2ecf20Sopenharmony_ci	tp->aspm_manageable = !rc;
53798c2ecf20Sopenharmony_ci
53808c2ecf20Sopenharmony_ci	/* enable device (incl. PCI PM wakeup and hotplug setup) */
53818c2ecf20Sopenharmony_ci	rc = pcim_enable_device(pdev);
53828c2ecf20Sopenharmony_ci	if (rc < 0) {
53838c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "enable failure\n");
53848c2ecf20Sopenharmony_ci		return rc;
53858c2ecf20Sopenharmony_ci	}
53868c2ecf20Sopenharmony_ci
53878c2ecf20Sopenharmony_ci	if (pcim_set_mwi(pdev) < 0)
53888c2ecf20Sopenharmony_ci		dev_info(&pdev->dev, "Mem-Wr-Inval unavailable\n");
53898c2ecf20Sopenharmony_ci
53908c2ecf20Sopenharmony_ci	/* use first MMIO region */
53918c2ecf20Sopenharmony_ci	region = ffs(pci_select_bars(pdev, IORESOURCE_MEM)) - 1;
53928c2ecf20Sopenharmony_ci	if (region < 0) {
53938c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "no MMIO resource found\n");
53948c2ecf20Sopenharmony_ci		return -ENODEV;
53958c2ecf20Sopenharmony_ci	}
53968c2ecf20Sopenharmony_ci
53978c2ecf20Sopenharmony_ci	/* check for weird/broken PCI region reporting */
53988c2ecf20Sopenharmony_ci	if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) {
53998c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "Invalid PCI region size(s), aborting\n");
54008c2ecf20Sopenharmony_ci		return -ENODEV;
54018c2ecf20Sopenharmony_ci	}
54028c2ecf20Sopenharmony_ci
54038c2ecf20Sopenharmony_ci	rc = pcim_iomap_regions(pdev, BIT(region), MODULENAME);
54048c2ecf20Sopenharmony_ci	if (rc < 0) {
54058c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "cannot remap MMIO, aborting\n");
54068c2ecf20Sopenharmony_ci		return rc;
54078c2ecf20Sopenharmony_ci	}
54088c2ecf20Sopenharmony_ci
54098c2ecf20Sopenharmony_ci	tp->mmio_addr = pcim_iomap_table(pdev)[region];
54108c2ecf20Sopenharmony_ci
54118c2ecf20Sopenharmony_ci	xid = (RTL_R32(tp, TxConfig) >> 20) & 0xfcf;
54128c2ecf20Sopenharmony_ci
54138c2ecf20Sopenharmony_ci	/* Identify chip attached to board */
54148c2ecf20Sopenharmony_ci	chipset = rtl8169_get_mac_version(xid, tp->supports_gmii);
54158c2ecf20Sopenharmony_ci	if (chipset == RTL_GIGA_MAC_NONE) {
54168c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "unknown chip XID %03x\n", xid);
54178c2ecf20Sopenharmony_ci		return -ENODEV;
54188c2ecf20Sopenharmony_ci	}
54198c2ecf20Sopenharmony_ci
54208c2ecf20Sopenharmony_ci	tp->mac_version = chipset;
54218c2ecf20Sopenharmony_ci
54228c2ecf20Sopenharmony_ci	tp->cp_cmd = RTL_R16(tp, CPlusCmd) & CPCMD_MASK;
54238c2ecf20Sopenharmony_ci
54248c2ecf20Sopenharmony_ci	if (sizeof(dma_addr_t) > 4 && tp->mac_version >= RTL_GIGA_MAC_VER_18 &&
54258c2ecf20Sopenharmony_ci	    !dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)))
54268c2ecf20Sopenharmony_ci		dev->features |= NETIF_F_HIGHDMA;
54278c2ecf20Sopenharmony_ci
54288c2ecf20Sopenharmony_ci	rtl_init_rxcfg(tp);
54298c2ecf20Sopenharmony_ci
54308c2ecf20Sopenharmony_ci	rtl8169_irq_mask_and_ack(tp);
54318c2ecf20Sopenharmony_ci
54328c2ecf20Sopenharmony_ci	rtl_hw_initialize(tp);
54338c2ecf20Sopenharmony_ci
54348c2ecf20Sopenharmony_ci	rtl_hw_reset(tp);
54358c2ecf20Sopenharmony_ci
54368c2ecf20Sopenharmony_ci	rc = rtl_alloc_irq(tp);
54378c2ecf20Sopenharmony_ci	if (rc < 0) {
54388c2ecf20Sopenharmony_ci		dev_err(&pdev->dev, "Can't allocate interrupt\n");
54398c2ecf20Sopenharmony_ci		return rc;
54408c2ecf20Sopenharmony_ci	}
54418c2ecf20Sopenharmony_ci
54428c2ecf20Sopenharmony_ci	INIT_WORK(&tp->wk.work, rtl_task);
54438c2ecf20Sopenharmony_ci	u64_stats_init(&tp->rx_stats.syncp);
54448c2ecf20Sopenharmony_ci	u64_stats_init(&tp->tx_stats.syncp);
54458c2ecf20Sopenharmony_ci
54468c2ecf20Sopenharmony_ci	rtl_init_mac_address(tp);
54478c2ecf20Sopenharmony_ci
54488c2ecf20Sopenharmony_ci	dev->ethtool_ops = &rtl8169_ethtool_ops;
54498c2ecf20Sopenharmony_ci
54508c2ecf20Sopenharmony_ci	netif_napi_add(dev, &tp->napi, rtl8169_poll, NAPI_POLL_WEIGHT);
54518c2ecf20Sopenharmony_ci
54528c2ecf20Sopenharmony_ci	dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
54538c2ecf20Sopenharmony_ci			   NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX;
54548c2ecf20Sopenharmony_ci	dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO;
54558c2ecf20Sopenharmony_ci	dev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
54568c2ecf20Sopenharmony_ci
54578c2ecf20Sopenharmony_ci	/*
54588c2ecf20Sopenharmony_ci	 * Pretend we are using VLANs; This bypasses a nasty bug where
54598c2ecf20Sopenharmony_ci	 * Interrupts stop flowing on high load on 8110SCd controllers.
54608c2ecf20Sopenharmony_ci	 */
54618c2ecf20Sopenharmony_ci	if (tp->mac_version == RTL_GIGA_MAC_VER_05)
54628c2ecf20Sopenharmony_ci		/* Disallow toggling */
54638c2ecf20Sopenharmony_ci		dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX;
54648c2ecf20Sopenharmony_ci
54658c2ecf20Sopenharmony_ci	if (rtl_chip_supports_csum_v2(tp))
54668c2ecf20Sopenharmony_ci		dev->hw_features |= NETIF_F_IPV6_CSUM;
54678c2ecf20Sopenharmony_ci
54688c2ecf20Sopenharmony_ci	dev->features |= dev->hw_features;
54698c2ecf20Sopenharmony_ci
54708c2ecf20Sopenharmony_ci	/* There has been a number of reports that using SG/TSO results in
54718c2ecf20Sopenharmony_ci	 * tx timeouts. However for a lot of people SG/TSO works fine.
54728c2ecf20Sopenharmony_ci	 * Therefore disable both features by default, but allow users to
54738c2ecf20Sopenharmony_ci	 * enable them. Use at own risk!
54748c2ecf20Sopenharmony_ci	 */
54758c2ecf20Sopenharmony_ci	if (rtl_chip_supports_csum_v2(tp)) {
54768c2ecf20Sopenharmony_ci		dev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6;
54778c2ecf20Sopenharmony_ci		dev->gso_max_size = RTL_GSO_MAX_SIZE_V2;
54788c2ecf20Sopenharmony_ci		dev->gso_max_segs = RTL_GSO_MAX_SEGS_V2;
54798c2ecf20Sopenharmony_ci	} else {
54808c2ecf20Sopenharmony_ci		dev->hw_features |= NETIF_F_SG | NETIF_F_TSO;
54818c2ecf20Sopenharmony_ci		dev->gso_max_size = RTL_GSO_MAX_SIZE_V1;
54828c2ecf20Sopenharmony_ci		dev->gso_max_segs = RTL_GSO_MAX_SEGS_V1;
54838c2ecf20Sopenharmony_ci	}
54848c2ecf20Sopenharmony_ci
54858c2ecf20Sopenharmony_ci	dev->hw_features |= NETIF_F_RXALL;
54868c2ecf20Sopenharmony_ci	dev->hw_features |= NETIF_F_RXFCS;
54878c2ecf20Sopenharmony_ci
54888c2ecf20Sopenharmony_ci	/* configure chip for default features */
54898c2ecf20Sopenharmony_ci	rtl8169_set_features(dev, dev->features);
54908c2ecf20Sopenharmony_ci
54918c2ecf20Sopenharmony_ci	jumbo_max = rtl_jumbo_max(tp);
54928c2ecf20Sopenharmony_ci	if (jumbo_max)
54938c2ecf20Sopenharmony_ci		dev->max_mtu = jumbo_max;
54948c2ecf20Sopenharmony_ci
54958c2ecf20Sopenharmony_ci	rtl_set_irq_mask(tp);
54968c2ecf20Sopenharmony_ci
54978c2ecf20Sopenharmony_ci	tp->fw_name = rtl_chip_infos[chipset].fw_name;
54988c2ecf20Sopenharmony_ci
54998c2ecf20Sopenharmony_ci	tp->counters = dmam_alloc_coherent (&pdev->dev, sizeof(*tp->counters),
55008c2ecf20Sopenharmony_ci					    &tp->counters_phys_addr,
55018c2ecf20Sopenharmony_ci					    GFP_KERNEL);
55028c2ecf20Sopenharmony_ci	if (!tp->counters)
55038c2ecf20Sopenharmony_ci		return -ENOMEM;
55048c2ecf20Sopenharmony_ci
55058c2ecf20Sopenharmony_ci	pci_set_drvdata(pdev, tp);
55068c2ecf20Sopenharmony_ci
55078c2ecf20Sopenharmony_ci	rc = r8169_mdio_register(tp);
55088c2ecf20Sopenharmony_ci	if (rc)
55098c2ecf20Sopenharmony_ci		return rc;
55108c2ecf20Sopenharmony_ci
55118c2ecf20Sopenharmony_ci	/* chip gets powered up in rtl_open() */
55128c2ecf20Sopenharmony_ci	rtl_pll_power_down(tp);
55138c2ecf20Sopenharmony_ci
55148c2ecf20Sopenharmony_ci	rc = register_netdev(dev);
55158c2ecf20Sopenharmony_ci	if (rc)
55168c2ecf20Sopenharmony_ci		return rc;
55178c2ecf20Sopenharmony_ci
55188c2ecf20Sopenharmony_ci	netdev_info(dev, "%s, %pM, XID %03x, IRQ %d\n",
55198c2ecf20Sopenharmony_ci		    rtl_chip_infos[chipset].name, dev->dev_addr, xid,
55208c2ecf20Sopenharmony_ci		    pci_irq_vector(pdev, 0));
55218c2ecf20Sopenharmony_ci
55228c2ecf20Sopenharmony_ci	if (jumbo_max)
55238c2ecf20Sopenharmony_ci		netdev_info(dev, "jumbo features [frames: %d bytes, tx checksumming: %s]\n",
55248c2ecf20Sopenharmony_ci			    jumbo_max, tp->mac_version <= RTL_GIGA_MAC_VER_06 ?
55258c2ecf20Sopenharmony_ci			    "ok" : "ko");
55268c2ecf20Sopenharmony_ci
55278c2ecf20Sopenharmony_ci	if (r8168_check_dash(tp)) {
55288c2ecf20Sopenharmony_ci		netdev_info(dev, "DASH enabled\n");
55298c2ecf20Sopenharmony_ci		rtl8168_driver_start(tp);
55308c2ecf20Sopenharmony_ci	}
55318c2ecf20Sopenharmony_ci
55328c2ecf20Sopenharmony_ci	if (pci_dev_run_wake(pdev))
55338c2ecf20Sopenharmony_ci		pm_runtime_put_sync(&pdev->dev);
55348c2ecf20Sopenharmony_ci
55358c2ecf20Sopenharmony_ci	return 0;
55368c2ecf20Sopenharmony_ci}
55378c2ecf20Sopenharmony_ci
55388c2ecf20Sopenharmony_cistatic struct pci_driver rtl8169_pci_driver = {
55398c2ecf20Sopenharmony_ci	.name		= MODULENAME,
55408c2ecf20Sopenharmony_ci	.id_table	= rtl8169_pci_tbl,
55418c2ecf20Sopenharmony_ci	.probe		= rtl_init_one,
55428c2ecf20Sopenharmony_ci	.remove		= rtl_remove_one,
55438c2ecf20Sopenharmony_ci	.shutdown	= rtl_shutdown,
55448c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
55458c2ecf20Sopenharmony_ci	.driver.pm	= &rtl8169_pm_ops,
55468c2ecf20Sopenharmony_ci#endif
55478c2ecf20Sopenharmony_ci};
55488c2ecf20Sopenharmony_ci
55498c2ecf20Sopenharmony_cimodule_pci_driver(rtl8169_pci_driver);
5550