162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0+ */
262306a36Sopenharmony_ci/* Copyright (C) 2018 Microchip Technology Inc. */
362306a36Sopenharmony_ci
462306a36Sopenharmony_ci#include <linux/netdevice.h>
562306a36Sopenharmony_ci#include <linux/net_tstamp.h>
662306a36Sopenharmony_ci#include <linux/pci.h>
762306a36Sopenharmony_ci#include <linux/phy.h>
862306a36Sopenharmony_ci#include "lan743x_main.h"
962306a36Sopenharmony_ci#include "lan743x_ethtool.h"
1062306a36Sopenharmony_ci#include <linux/sched.h>
1162306a36Sopenharmony_ci#include <linux/iopoll.h>
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci/* eeprom */
1462306a36Sopenharmony_ci#define LAN743X_EEPROM_MAGIC		    (0x74A5)
1562306a36Sopenharmony_ci#define LAN743X_OTP_MAGIC		    (0x74F3)
1662306a36Sopenharmony_ci#define EEPROM_INDICATOR_1		    (0xA5)
1762306a36Sopenharmony_ci#define EEPROM_INDICATOR_2		    (0xAA)
1862306a36Sopenharmony_ci#define EEPROM_MAC_OFFSET		    (0x01)
1962306a36Sopenharmony_ci#define MAX_EEPROM_SIZE			    (512)
2062306a36Sopenharmony_ci#define MAX_OTP_SIZE			    (1024)
2162306a36Sopenharmony_ci#define OTP_INDICATOR_1			    (0xF3)
2262306a36Sopenharmony_ci#define OTP_INDICATOR_2			    (0xF7)
2362306a36Sopenharmony_ci
2462306a36Sopenharmony_ci#define LOCK_TIMEOUT_MAX_CNT		    (100) // 1 sec (10 msce * 100)
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#define LAN743X_CSR_READ_OP(offset)	     lan743x_csr_read(adapter, offset)
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_cistatic int lan743x_otp_power_up(struct lan743x_adapter *adapter)
2962306a36Sopenharmony_ci{
3062306a36Sopenharmony_ci	u32 reg_value;
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci	reg_value = lan743x_csr_read(adapter, OTP_PWR_DN);
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	if (reg_value & OTP_PWR_DN_PWRDN_N_) {
3562306a36Sopenharmony_ci		/* clear it and wait to be cleared */
3662306a36Sopenharmony_ci		reg_value &= ~OTP_PWR_DN_PWRDN_N_;
3762306a36Sopenharmony_ci		lan743x_csr_write(adapter, OTP_PWR_DN, reg_value);
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci		usleep_range(100, 20000);
4062306a36Sopenharmony_ci	}
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	return 0;
4362306a36Sopenharmony_ci}
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_cistatic void lan743x_otp_power_down(struct lan743x_adapter *adapter)
4662306a36Sopenharmony_ci{
4762306a36Sopenharmony_ci	u32 reg_value;
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_ci	reg_value = lan743x_csr_read(adapter, OTP_PWR_DN);
5062306a36Sopenharmony_ci	if (!(reg_value & OTP_PWR_DN_PWRDN_N_)) {
5162306a36Sopenharmony_ci		/* set power down bit */
5262306a36Sopenharmony_ci		reg_value |= OTP_PWR_DN_PWRDN_N_;
5362306a36Sopenharmony_ci		lan743x_csr_write(adapter, OTP_PWR_DN, reg_value);
5462306a36Sopenharmony_ci	}
5562306a36Sopenharmony_ci}
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_cistatic void lan743x_otp_set_address(struct lan743x_adapter *adapter,
5862306a36Sopenharmony_ci				    u32 address)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	lan743x_csr_write(adapter, OTP_ADDR_HIGH, (address >> 8) & 0x03);
6162306a36Sopenharmony_ci	lan743x_csr_write(adapter, OTP_ADDR_LOW, address & 0xFF);
6262306a36Sopenharmony_ci}
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_cistatic void lan743x_otp_read_go(struct lan743x_adapter *adapter)
6562306a36Sopenharmony_ci{
6662306a36Sopenharmony_ci	lan743x_csr_write(adapter, OTP_FUNC_CMD, OTP_FUNC_CMD_READ_);
6762306a36Sopenharmony_ci	lan743x_csr_write(adapter, OTP_CMD_GO, OTP_CMD_GO_GO_);
6862306a36Sopenharmony_ci}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_cistatic int lan743x_otp_wait_till_not_busy(struct lan743x_adapter *adapter)
7162306a36Sopenharmony_ci{
7262306a36Sopenharmony_ci	unsigned long timeout;
7362306a36Sopenharmony_ci	u32 reg_val;
7462306a36Sopenharmony_ci
7562306a36Sopenharmony_ci	timeout = jiffies + HZ;
7662306a36Sopenharmony_ci	do {
7762306a36Sopenharmony_ci		if (time_after(jiffies, timeout)) {
7862306a36Sopenharmony_ci			netif_warn(adapter, drv, adapter->netdev,
7962306a36Sopenharmony_ci				   "Timeout on OTP_STATUS completion\n");
8062306a36Sopenharmony_ci			return -EIO;
8162306a36Sopenharmony_ci		}
8262306a36Sopenharmony_ci		udelay(1);
8362306a36Sopenharmony_ci		reg_val = lan743x_csr_read(adapter, OTP_STATUS);
8462306a36Sopenharmony_ci	} while (reg_val & OTP_STATUS_BUSY_);
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci	return 0;
8762306a36Sopenharmony_ci}
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cistatic int lan743x_otp_read(struct lan743x_adapter *adapter, u32 offset,
9062306a36Sopenharmony_ci			    u32 length, u8 *data)
9162306a36Sopenharmony_ci{
9262306a36Sopenharmony_ci	int ret;
9362306a36Sopenharmony_ci	int i;
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	if (offset + length > MAX_OTP_SIZE)
9662306a36Sopenharmony_ci		return -EINVAL;
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_ci	ret = lan743x_otp_power_up(adapter);
9962306a36Sopenharmony_ci	if (ret < 0)
10062306a36Sopenharmony_ci		return ret;
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci	ret = lan743x_otp_wait_till_not_busy(adapter);
10362306a36Sopenharmony_ci	if (ret < 0)
10462306a36Sopenharmony_ci		return ret;
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	for (i = 0; i < length; i++) {
10762306a36Sopenharmony_ci		lan743x_otp_set_address(adapter, offset + i);
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci		lan743x_otp_read_go(adapter);
11062306a36Sopenharmony_ci		ret = lan743x_otp_wait_till_not_busy(adapter);
11162306a36Sopenharmony_ci		if (ret < 0)
11262306a36Sopenharmony_ci			return ret;
11362306a36Sopenharmony_ci		data[i] = lan743x_csr_read(adapter, OTP_READ_DATA);
11462306a36Sopenharmony_ci	}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	lan743x_otp_power_down(adapter);
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	return 0;
11962306a36Sopenharmony_ci}
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_cistatic int lan743x_otp_write(struct lan743x_adapter *adapter, u32 offset,
12262306a36Sopenharmony_ci			     u32 length, u8 *data)
12362306a36Sopenharmony_ci{
12462306a36Sopenharmony_ci	int ret;
12562306a36Sopenharmony_ci	int i;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	if (offset + length > MAX_OTP_SIZE)
12862306a36Sopenharmony_ci		return -EINVAL;
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	ret = lan743x_otp_power_up(adapter);
13162306a36Sopenharmony_ci	if (ret < 0)
13262306a36Sopenharmony_ci		return ret;
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	ret = lan743x_otp_wait_till_not_busy(adapter);
13562306a36Sopenharmony_ci	if (ret < 0)
13662306a36Sopenharmony_ci		return ret;
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	/* set to BYTE program mode */
13962306a36Sopenharmony_ci	lan743x_csr_write(adapter, OTP_PRGM_MODE, OTP_PRGM_MODE_BYTE_);
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	for (i = 0; i < length; i++) {
14262306a36Sopenharmony_ci		lan743x_otp_set_address(adapter, offset + i);
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci		lan743x_csr_write(adapter, OTP_PRGM_DATA, data[i]);
14562306a36Sopenharmony_ci		lan743x_csr_write(adapter, OTP_TST_CMD, OTP_TST_CMD_PRGVRFY_);
14662306a36Sopenharmony_ci		lan743x_csr_write(adapter, OTP_CMD_GO, OTP_CMD_GO_GO_);
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_ci		ret = lan743x_otp_wait_till_not_busy(adapter);
14962306a36Sopenharmony_ci		if (ret < 0)
15062306a36Sopenharmony_ci			return ret;
15162306a36Sopenharmony_ci	}
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	lan743x_otp_power_down(adapter);
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	return 0;
15662306a36Sopenharmony_ci}
15762306a36Sopenharmony_ci
15862306a36Sopenharmony_ciint lan743x_hs_syslock_acquire(struct lan743x_adapter *adapter,
15962306a36Sopenharmony_ci			       u16 timeout)
16062306a36Sopenharmony_ci{
16162306a36Sopenharmony_ci	u16 timeout_cnt = 0;
16262306a36Sopenharmony_ci	u32 val;
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	do {
16562306a36Sopenharmony_ci		spin_lock(&adapter->eth_syslock_spinlock);
16662306a36Sopenharmony_ci		if (adapter->eth_syslock_acquire_cnt == 0) {
16762306a36Sopenharmony_ci			lan743x_csr_write(adapter, ETH_SYSTEM_SYS_LOCK_REG,
16862306a36Sopenharmony_ci					  SYS_LOCK_REG_ENET_SS_LOCK_);
16962306a36Sopenharmony_ci			val = lan743x_csr_read(adapter,
17062306a36Sopenharmony_ci					       ETH_SYSTEM_SYS_LOCK_REG);
17162306a36Sopenharmony_ci			if (val & SYS_LOCK_REG_ENET_SS_LOCK_) {
17262306a36Sopenharmony_ci				adapter->eth_syslock_acquire_cnt++;
17362306a36Sopenharmony_ci				WARN_ON(adapter->eth_syslock_acquire_cnt == 0);
17462306a36Sopenharmony_ci				spin_unlock(&adapter->eth_syslock_spinlock);
17562306a36Sopenharmony_ci				break;
17662306a36Sopenharmony_ci			}
17762306a36Sopenharmony_ci		} else {
17862306a36Sopenharmony_ci			adapter->eth_syslock_acquire_cnt++;
17962306a36Sopenharmony_ci			WARN_ON(adapter->eth_syslock_acquire_cnt == 0);
18062306a36Sopenharmony_ci			spin_unlock(&adapter->eth_syslock_spinlock);
18162306a36Sopenharmony_ci			break;
18262306a36Sopenharmony_ci		}
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ci		spin_unlock(&adapter->eth_syslock_spinlock);
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci		if (timeout_cnt++ < timeout)
18762306a36Sopenharmony_ci			usleep_range(10000, 11000);
18862306a36Sopenharmony_ci		else
18962306a36Sopenharmony_ci			return -ETIMEDOUT;
19062306a36Sopenharmony_ci	} while (true);
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	return 0;
19362306a36Sopenharmony_ci}
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_civoid lan743x_hs_syslock_release(struct lan743x_adapter *adapter)
19662306a36Sopenharmony_ci{
19762306a36Sopenharmony_ci	u32 val;
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	spin_lock(&adapter->eth_syslock_spinlock);
20062306a36Sopenharmony_ci	WARN_ON(adapter->eth_syslock_acquire_cnt == 0);
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	if (adapter->eth_syslock_acquire_cnt) {
20362306a36Sopenharmony_ci		adapter->eth_syslock_acquire_cnt--;
20462306a36Sopenharmony_ci		if (adapter->eth_syslock_acquire_cnt == 0) {
20562306a36Sopenharmony_ci			lan743x_csr_write(adapter, ETH_SYSTEM_SYS_LOCK_REG, 0);
20662306a36Sopenharmony_ci			val = lan743x_csr_read(adapter,
20762306a36Sopenharmony_ci					       ETH_SYSTEM_SYS_LOCK_REG);
20862306a36Sopenharmony_ci			WARN_ON((val & SYS_LOCK_REG_ENET_SS_LOCK_) != 0);
20962306a36Sopenharmony_ci		}
21062306a36Sopenharmony_ci	}
21162306a36Sopenharmony_ci
21262306a36Sopenharmony_ci	spin_unlock(&adapter->eth_syslock_spinlock);
21362306a36Sopenharmony_ci}
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_cistatic void lan743x_hs_otp_power_up(struct lan743x_adapter *adapter)
21662306a36Sopenharmony_ci{
21762306a36Sopenharmony_ci	u32 reg_value;
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ci	reg_value = lan743x_csr_read(adapter, HS_OTP_PWR_DN);
22062306a36Sopenharmony_ci	if (reg_value & OTP_PWR_DN_PWRDN_N_) {
22162306a36Sopenharmony_ci		reg_value &= ~OTP_PWR_DN_PWRDN_N_;
22262306a36Sopenharmony_ci		lan743x_csr_write(adapter, HS_OTP_PWR_DN, reg_value);
22362306a36Sopenharmony_ci		/* To flush the posted write so the subsequent delay is
22462306a36Sopenharmony_ci		 * guaranteed to happen after the write at the hardware
22562306a36Sopenharmony_ci		 */
22662306a36Sopenharmony_ci		lan743x_csr_read(adapter, HS_OTP_PWR_DN);
22762306a36Sopenharmony_ci		udelay(1);
22862306a36Sopenharmony_ci	}
22962306a36Sopenharmony_ci}
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_cistatic void lan743x_hs_otp_power_down(struct lan743x_adapter *adapter)
23262306a36Sopenharmony_ci{
23362306a36Sopenharmony_ci	u32 reg_value;
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	reg_value = lan743x_csr_read(adapter, HS_OTP_PWR_DN);
23662306a36Sopenharmony_ci	if (!(reg_value & OTP_PWR_DN_PWRDN_N_)) {
23762306a36Sopenharmony_ci		reg_value |= OTP_PWR_DN_PWRDN_N_;
23862306a36Sopenharmony_ci		lan743x_csr_write(adapter, HS_OTP_PWR_DN, reg_value);
23962306a36Sopenharmony_ci		/* To flush the posted write so the subsequent delay is
24062306a36Sopenharmony_ci		 * guaranteed to happen after the write at the hardware
24162306a36Sopenharmony_ci		 */
24262306a36Sopenharmony_ci		lan743x_csr_read(adapter, HS_OTP_PWR_DN);
24362306a36Sopenharmony_ci		udelay(1);
24462306a36Sopenharmony_ci	}
24562306a36Sopenharmony_ci}
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_cistatic void lan743x_hs_otp_set_address(struct lan743x_adapter *adapter,
24862306a36Sopenharmony_ci				       u32 address)
24962306a36Sopenharmony_ci{
25062306a36Sopenharmony_ci	lan743x_csr_write(adapter, HS_OTP_ADDR_HIGH, (address >> 8) & 0x03);
25162306a36Sopenharmony_ci	lan743x_csr_write(adapter, HS_OTP_ADDR_LOW, address & 0xFF);
25262306a36Sopenharmony_ci}
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_cistatic void lan743x_hs_otp_read_go(struct lan743x_adapter *adapter)
25562306a36Sopenharmony_ci{
25662306a36Sopenharmony_ci	lan743x_csr_write(adapter, HS_OTP_FUNC_CMD, OTP_FUNC_CMD_READ_);
25762306a36Sopenharmony_ci	lan743x_csr_write(adapter, HS_OTP_CMD_GO, OTP_CMD_GO_GO_);
25862306a36Sopenharmony_ci}
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_cistatic int lan743x_hs_otp_cmd_cmplt_chk(struct lan743x_adapter *adapter)
26162306a36Sopenharmony_ci{
26262306a36Sopenharmony_ci	u32 val;
26362306a36Sopenharmony_ci
26462306a36Sopenharmony_ci	return readx_poll_timeout(LAN743X_CSR_READ_OP, HS_OTP_STATUS, val,
26562306a36Sopenharmony_ci				  !(val & OTP_STATUS_BUSY_),
26662306a36Sopenharmony_ci				  80, 10000);
26762306a36Sopenharmony_ci}
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_cistatic int lan743x_hs_otp_read(struct lan743x_adapter *adapter, u32 offset,
27062306a36Sopenharmony_ci			       u32 length, u8 *data)
27162306a36Sopenharmony_ci{
27262306a36Sopenharmony_ci	int ret;
27362306a36Sopenharmony_ci	int i;
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci	ret = lan743x_hs_syslock_acquire(adapter, LOCK_TIMEOUT_MAX_CNT);
27662306a36Sopenharmony_ci	if (ret < 0)
27762306a36Sopenharmony_ci		return ret;
27862306a36Sopenharmony_ci
27962306a36Sopenharmony_ci	lan743x_hs_otp_power_up(adapter);
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	ret = lan743x_hs_otp_cmd_cmplt_chk(adapter);
28262306a36Sopenharmony_ci	if (ret < 0)
28362306a36Sopenharmony_ci		goto power_down;
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	lan743x_hs_syslock_release(adapter);
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	for (i = 0; i < length; i++) {
28862306a36Sopenharmony_ci		ret = lan743x_hs_syslock_acquire(adapter,
28962306a36Sopenharmony_ci						 LOCK_TIMEOUT_MAX_CNT);
29062306a36Sopenharmony_ci		if (ret < 0)
29162306a36Sopenharmony_ci			return ret;
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci		lan743x_hs_otp_set_address(adapter, offset + i);
29462306a36Sopenharmony_ci
29562306a36Sopenharmony_ci		lan743x_hs_otp_read_go(adapter);
29662306a36Sopenharmony_ci		ret = lan743x_hs_otp_cmd_cmplt_chk(adapter);
29762306a36Sopenharmony_ci		if (ret < 0)
29862306a36Sopenharmony_ci			goto power_down;
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci		data[i] = lan743x_csr_read(adapter, HS_OTP_READ_DATA);
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci		lan743x_hs_syslock_release(adapter);
30362306a36Sopenharmony_ci	}
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	ret = lan743x_hs_syslock_acquire(adapter,
30662306a36Sopenharmony_ci					 LOCK_TIMEOUT_MAX_CNT);
30762306a36Sopenharmony_ci	if (ret < 0)
30862306a36Sopenharmony_ci		return ret;
30962306a36Sopenharmony_ci
31062306a36Sopenharmony_cipower_down:
31162306a36Sopenharmony_ci	lan743x_hs_otp_power_down(adapter);
31262306a36Sopenharmony_ci	lan743x_hs_syslock_release(adapter);
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci	return ret;
31562306a36Sopenharmony_ci}
31662306a36Sopenharmony_ci
31762306a36Sopenharmony_cistatic int lan743x_hs_otp_write(struct lan743x_adapter *adapter, u32 offset,
31862306a36Sopenharmony_ci				u32 length, u8 *data)
31962306a36Sopenharmony_ci{
32062306a36Sopenharmony_ci	int ret;
32162306a36Sopenharmony_ci	int i;
32262306a36Sopenharmony_ci
32362306a36Sopenharmony_ci	ret = lan743x_hs_syslock_acquire(adapter, LOCK_TIMEOUT_MAX_CNT);
32462306a36Sopenharmony_ci	if (ret < 0)
32562306a36Sopenharmony_ci		return ret;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_ci	lan743x_hs_otp_power_up(adapter);
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci	ret = lan743x_hs_otp_cmd_cmplt_chk(adapter);
33062306a36Sopenharmony_ci	if (ret < 0)
33162306a36Sopenharmony_ci		goto power_down;
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_ci	/* set to BYTE program mode */
33462306a36Sopenharmony_ci	lan743x_csr_write(adapter, HS_OTP_PRGM_MODE, OTP_PRGM_MODE_BYTE_);
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci	lan743x_hs_syslock_release(adapter);
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	for (i = 0; i < length; i++) {
33962306a36Sopenharmony_ci		ret = lan743x_hs_syslock_acquire(adapter,
34062306a36Sopenharmony_ci						 LOCK_TIMEOUT_MAX_CNT);
34162306a36Sopenharmony_ci		if (ret < 0)
34262306a36Sopenharmony_ci			return ret;
34362306a36Sopenharmony_ci
34462306a36Sopenharmony_ci		lan743x_hs_otp_set_address(adapter, offset + i);
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ci		lan743x_csr_write(adapter, HS_OTP_PRGM_DATA, data[i]);
34762306a36Sopenharmony_ci		lan743x_csr_write(adapter, HS_OTP_TST_CMD,
34862306a36Sopenharmony_ci				  OTP_TST_CMD_PRGVRFY_);
34962306a36Sopenharmony_ci		lan743x_csr_write(adapter, HS_OTP_CMD_GO, OTP_CMD_GO_GO_);
35062306a36Sopenharmony_ci
35162306a36Sopenharmony_ci		ret = lan743x_hs_otp_cmd_cmplt_chk(adapter);
35262306a36Sopenharmony_ci		if (ret < 0)
35362306a36Sopenharmony_ci			goto power_down;
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci		lan743x_hs_syslock_release(adapter);
35662306a36Sopenharmony_ci	}
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_ci	ret = lan743x_hs_syslock_acquire(adapter, LOCK_TIMEOUT_MAX_CNT);
35962306a36Sopenharmony_ci	if (ret < 0)
36062306a36Sopenharmony_ci		return ret;
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_cipower_down:
36362306a36Sopenharmony_ci	lan743x_hs_otp_power_down(adapter);
36462306a36Sopenharmony_ci	lan743x_hs_syslock_release(adapter);
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	return ret;
36762306a36Sopenharmony_ci}
36862306a36Sopenharmony_ci
36962306a36Sopenharmony_cistatic int lan743x_eeprom_wait(struct lan743x_adapter *adapter)
37062306a36Sopenharmony_ci{
37162306a36Sopenharmony_ci	unsigned long start_time = jiffies;
37262306a36Sopenharmony_ci	u32 val;
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_ci	do {
37562306a36Sopenharmony_ci		val = lan743x_csr_read(adapter, E2P_CMD);
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci		if (!(val & E2P_CMD_EPC_BUSY_) ||
37862306a36Sopenharmony_ci		    (val & E2P_CMD_EPC_TIMEOUT_))
37962306a36Sopenharmony_ci			break;
38062306a36Sopenharmony_ci		usleep_range(40, 100);
38162306a36Sopenharmony_ci	} while (!time_after(jiffies, start_time + HZ));
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_ci	if (val & (E2P_CMD_EPC_TIMEOUT_ | E2P_CMD_EPC_BUSY_)) {
38462306a36Sopenharmony_ci		netif_warn(adapter, drv, adapter->netdev,
38562306a36Sopenharmony_ci			   "EEPROM read operation timeout\n");
38662306a36Sopenharmony_ci		return -EIO;
38762306a36Sopenharmony_ci	}
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_ci	return 0;
39062306a36Sopenharmony_ci}
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_cistatic int lan743x_eeprom_confirm_not_busy(struct lan743x_adapter *adapter)
39362306a36Sopenharmony_ci{
39462306a36Sopenharmony_ci	unsigned long start_time = jiffies;
39562306a36Sopenharmony_ci	u32 val;
39662306a36Sopenharmony_ci
39762306a36Sopenharmony_ci	do {
39862306a36Sopenharmony_ci		val = lan743x_csr_read(adapter, E2P_CMD);
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci		if (!(val & E2P_CMD_EPC_BUSY_))
40162306a36Sopenharmony_ci			return 0;
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci		usleep_range(40, 100);
40462306a36Sopenharmony_ci	} while (!time_after(jiffies, start_time + HZ));
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci	netif_warn(adapter, drv, adapter->netdev, "EEPROM is busy\n");
40762306a36Sopenharmony_ci	return -EIO;
40862306a36Sopenharmony_ci}
40962306a36Sopenharmony_ci
41062306a36Sopenharmony_cistatic int lan743x_eeprom_read(struct lan743x_adapter *adapter,
41162306a36Sopenharmony_ci			       u32 offset, u32 length, u8 *data)
41262306a36Sopenharmony_ci{
41362306a36Sopenharmony_ci	int retval;
41462306a36Sopenharmony_ci	u32 val;
41562306a36Sopenharmony_ci	int i;
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci	if (offset + length > MAX_EEPROM_SIZE)
41862306a36Sopenharmony_ci		return -EINVAL;
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci	retval = lan743x_eeprom_confirm_not_busy(adapter);
42162306a36Sopenharmony_ci	if (retval)
42262306a36Sopenharmony_ci		return retval;
42362306a36Sopenharmony_ci
42462306a36Sopenharmony_ci	for (i = 0; i < length; i++) {
42562306a36Sopenharmony_ci		val = E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_READ_;
42662306a36Sopenharmony_ci		val |= (offset & E2P_CMD_EPC_ADDR_MASK_);
42762306a36Sopenharmony_ci		lan743x_csr_write(adapter, E2P_CMD, val);
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_ci		retval = lan743x_eeprom_wait(adapter);
43062306a36Sopenharmony_ci		if (retval < 0)
43162306a36Sopenharmony_ci			return retval;
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci		val = lan743x_csr_read(adapter, E2P_DATA);
43462306a36Sopenharmony_ci		data[i] = val & 0xFF;
43562306a36Sopenharmony_ci		offset++;
43662306a36Sopenharmony_ci	}
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci	return 0;
43962306a36Sopenharmony_ci}
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_cistatic int lan743x_eeprom_write(struct lan743x_adapter *adapter,
44262306a36Sopenharmony_ci				u32 offset, u32 length, u8 *data)
44362306a36Sopenharmony_ci{
44462306a36Sopenharmony_ci	int retval;
44562306a36Sopenharmony_ci	u32 val;
44662306a36Sopenharmony_ci	int i;
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci	if (offset + length > MAX_EEPROM_SIZE)
44962306a36Sopenharmony_ci		return -EINVAL;
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci	retval = lan743x_eeprom_confirm_not_busy(adapter);
45262306a36Sopenharmony_ci	if (retval)
45362306a36Sopenharmony_ci		return retval;
45462306a36Sopenharmony_ci
45562306a36Sopenharmony_ci	/* Issue write/erase enable command */
45662306a36Sopenharmony_ci	val = E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_EWEN_;
45762306a36Sopenharmony_ci	lan743x_csr_write(adapter, E2P_CMD, val);
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci	retval = lan743x_eeprom_wait(adapter);
46062306a36Sopenharmony_ci	if (retval < 0)
46162306a36Sopenharmony_ci		return retval;
46262306a36Sopenharmony_ci
46362306a36Sopenharmony_ci	for (i = 0; i < length; i++) {
46462306a36Sopenharmony_ci		/* Fill data register */
46562306a36Sopenharmony_ci		val = data[i];
46662306a36Sopenharmony_ci		lan743x_csr_write(adapter, E2P_DATA, val);
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci		/* Send "write" command */
46962306a36Sopenharmony_ci		val = E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_WRITE_;
47062306a36Sopenharmony_ci		val |= (offset & E2P_CMD_EPC_ADDR_MASK_);
47162306a36Sopenharmony_ci		lan743x_csr_write(adapter, E2P_CMD, val);
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_ci		retval = lan743x_eeprom_wait(adapter);
47462306a36Sopenharmony_ci		if (retval < 0)
47562306a36Sopenharmony_ci			return retval;
47662306a36Sopenharmony_ci
47762306a36Sopenharmony_ci		offset++;
47862306a36Sopenharmony_ci	}
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci	return 0;
48162306a36Sopenharmony_ci}
48262306a36Sopenharmony_ci
48362306a36Sopenharmony_cistatic int lan743x_hs_eeprom_cmd_cmplt_chk(struct lan743x_adapter *adapter)
48462306a36Sopenharmony_ci{
48562306a36Sopenharmony_ci	u32 val;
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_ci	return readx_poll_timeout(LAN743X_CSR_READ_OP, HS_E2P_CMD, val,
48862306a36Sopenharmony_ci				  (!(val & HS_E2P_CMD_EPC_BUSY_) ||
48962306a36Sopenharmony_ci				    (val & HS_E2P_CMD_EPC_TIMEOUT_)),
49062306a36Sopenharmony_ci				  50, 10000);
49162306a36Sopenharmony_ci}
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_cistatic int lan743x_hs_eeprom_read(struct lan743x_adapter *adapter,
49462306a36Sopenharmony_ci				  u32 offset, u32 length, u8 *data)
49562306a36Sopenharmony_ci{
49662306a36Sopenharmony_ci	int retval;
49762306a36Sopenharmony_ci	u32 val;
49862306a36Sopenharmony_ci	int i;
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci	retval = lan743x_hs_syslock_acquire(adapter, LOCK_TIMEOUT_MAX_CNT);
50162306a36Sopenharmony_ci	if (retval < 0)
50262306a36Sopenharmony_ci		return retval;
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	retval = lan743x_hs_eeprom_cmd_cmplt_chk(adapter);
50562306a36Sopenharmony_ci	lan743x_hs_syslock_release(adapter);
50662306a36Sopenharmony_ci	if (retval < 0)
50762306a36Sopenharmony_ci		return retval;
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci	for (i = 0; i < length; i++) {
51062306a36Sopenharmony_ci		retval = lan743x_hs_syslock_acquire(adapter,
51162306a36Sopenharmony_ci						    LOCK_TIMEOUT_MAX_CNT);
51262306a36Sopenharmony_ci		if (retval < 0)
51362306a36Sopenharmony_ci			return retval;
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci		val = HS_E2P_CMD_EPC_BUSY_ | HS_E2P_CMD_EPC_CMD_READ_;
51662306a36Sopenharmony_ci		val |= (offset & HS_E2P_CMD_EPC_ADDR_MASK_);
51762306a36Sopenharmony_ci		lan743x_csr_write(adapter, HS_E2P_CMD, val);
51862306a36Sopenharmony_ci		retval = lan743x_hs_eeprom_cmd_cmplt_chk(adapter);
51962306a36Sopenharmony_ci		if (retval < 0) {
52062306a36Sopenharmony_ci			lan743x_hs_syslock_release(adapter);
52162306a36Sopenharmony_ci			return retval;
52262306a36Sopenharmony_ci		}
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci		val = lan743x_csr_read(adapter, HS_E2P_DATA);
52562306a36Sopenharmony_ci
52662306a36Sopenharmony_ci		lan743x_hs_syslock_release(adapter);
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci		data[i] = val & 0xFF;
52962306a36Sopenharmony_ci		offset++;
53062306a36Sopenharmony_ci	}
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci	return 0;
53362306a36Sopenharmony_ci}
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_cistatic int lan743x_hs_eeprom_write(struct lan743x_adapter *adapter,
53662306a36Sopenharmony_ci				   u32 offset, u32 length, u8 *data)
53762306a36Sopenharmony_ci{
53862306a36Sopenharmony_ci	int retval;
53962306a36Sopenharmony_ci	u32 val;
54062306a36Sopenharmony_ci	int i;
54162306a36Sopenharmony_ci
54262306a36Sopenharmony_ci	retval = lan743x_hs_syslock_acquire(adapter, LOCK_TIMEOUT_MAX_CNT);
54362306a36Sopenharmony_ci	if (retval < 0)
54462306a36Sopenharmony_ci		return retval;
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	retval = lan743x_hs_eeprom_cmd_cmplt_chk(adapter);
54762306a36Sopenharmony_ci	lan743x_hs_syslock_release(adapter);
54862306a36Sopenharmony_ci	if (retval < 0)
54962306a36Sopenharmony_ci		return retval;
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci	for (i = 0; i < length; i++) {
55262306a36Sopenharmony_ci		retval = lan743x_hs_syslock_acquire(adapter,
55362306a36Sopenharmony_ci						    LOCK_TIMEOUT_MAX_CNT);
55462306a36Sopenharmony_ci		if (retval < 0)
55562306a36Sopenharmony_ci			return retval;
55662306a36Sopenharmony_ci
55762306a36Sopenharmony_ci		/* Fill data register */
55862306a36Sopenharmony_ci		val = data[i];
55962306a36Sopenharmony_ci		lan743x_csr_write(adapter, HS_E2P_DATA, val);
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ci		/* Send "write" command */
56262306a36Sopenharmony_ci		val = HS_E2P_CMD_EPC_BUSY_ | HS_E2P_CMD_EPC_CMD_WRITE_;
56362306a36Sopenharmony_ci		val |= (offset & HS_E2P_CMD_EPC_ADDR_MASK_);
56462306a36Sopenharmony_ci		lan743x_csr_write(adapter, HS_E2P_CMD, val);
56562306a36Sopenharmony_ci
56662306a36Sopenharmony_ci		retval = lan743x_hs_eeprom_cmd_cmplt_chk(adapter);
56762306a36Sopenharmony_ci		lan743x_hs_syslock_release(adapter);
56862306a36Sopenharmony_ci		if (retval < 0)
56962306a36Sopenharmony_ci			return retval;
57062306a36Sopenharmony_ci
57162306a36Sopenharmony_ci		offset++;
57262306a36Sopenharmony_ci	}
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ci	return 0;
57562306a36Sopenharmony_ci}
57662306a36Sopenharmony_ci
57762306a36Sopenharmony_cistatic void lan743x_ethtool_get_drvinfo(struct net_device *netdev,
57862306a36Sopenharmony_ci					struct ethtool_drvinfo *info)
57962306a36Sopenharmony_ci{
58062306a36Sopenharmony_ci	struct lan743x_adapter *adapter = netdev_priv(netdev);
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci	strscpy(info->driver, DRIVER_NAME, sizeof(info->driver));
58362306a36Sopenharmony_ci	strscpy(info->bus_info,
58462306a36Sopenharmony_ci		pci_name(adapter->pdev), sizeof(info->bus_info));
58562306a36Sopenharmony_ci}
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_cistatic u32 lan743x_ethtool_get_msglevel(struct net_device *netdev)
58862306a36Sopenharmony_ci{
58962306a36Sopenharmony_ci	struct lan743x_adapter *adapter = netdev_priv(netdev);
59062306a36Sopenharmony_ci
59162306a36Sopenharmony_ci	return adapter->msg_enable;
59262306a36Sopenharmony_ci}
59362306a36Sopenharmony_ci
59462306a36Sopenharmony_cistatic void lan743x_ethtool_set_msglevel(struct net_device *netdev,
59562306a36Sopenharmony_ci					 u32 msglevel)
59662306a36Sopenharmony_ci{
59762306a36Sopenharmony_ci	struct lan743x_adapter *adapter = netdev_priv(netdev);
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_ci	adapter->msg_enable = msglevel;
60062306a36Sopenharmony_ci}
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_cistatic int lan743x_ethtool_get_eeprom_len(struct net_device *netdev)
60362306a36Sopenharmony_ci{
60462306a36Sopenharmony_ci	struct lan743x_adapter *adapter = netdev_priv(netdev);
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_ci	if (adapter->flags & LAN743X_ADAPTER_FLAG_OTP)
60762306a36Sopenharmony_ci		return MAX_OTP_SIZE;
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci	return MAX_EEPROM_SIZE;
61062306a36Sopenharmony_ci}
61162306a36Sopenharmony_ci
61262306a36Sopenharmony_cistatic int lan743x_ethtool_get_eeprom(struct net_device *netdev,
61362306a36Sopenharmony_ci				      struct ethtool_eeprom *ee, u8 *data)
61462306a36Sopenharmony_ci{
61562306a36Sopenharmony_ci	struct lan743x_adapter *adapter = netdev_priv(netdev);
61662306a36Sopenharmony_ci	int ret = 0;
61762306a36Sopenharmony_ci
61862306a36Sopenharmony_ci	if (adapter->flags & LAN743X_ADAPTER_FLAG_OTP) {
61962306a36Sopenharmony_ci		if (adapter->is_pci11x1x)
62062306a36Sopenharmony_ci			ret = lan743x_hs_otp_read(adapter, ee->offset,
62162306a36Sopenharmony_ci						  ee->len, data);
62262306a36Sopenharmony_ci		else
62362306a36Sopenharmony_ci			ret = lan743x_otp_read(adapter, ee->offset,
62462306a36Sopenharmony_ci					       ee->len, data);
62562306a36Sopenharmony_ci	} else {
62662306a36Sopenharmony_ci		if (adapter->is_pci11x1x)
62762306a36Sopenharmony_ci			ret = lan743x_hs_eeprom_read(adapter, ee->offset,
62862306a36Sopenharmony_ci						     ee->len, data);
62962306a36Sopenharmony_ci		else
63062306a36Sopenharmony_ci			ret = lan743x_eeprom_read(adapter, ee->offset,
63162306a36Sopenharmony_ci						  ee->len, data);
63262306a36Sopenharmony_ci	}
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci	return ret;
63562306a36Sopenharmony_ci}
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_cistatic int lan743x_ethtool_set_eeprom(struct net_device *netdev,
63862306a36Sopenharmony_ci				      struct ethtool_eeprom *ee, u8 *data)
63962306a36Sopenharmony_ci{
64062306a36Sopenharmony_ci	struct lan743x_adapter *adapter = netdev_priv(netdev);
64162306a36Sopenharmony_ci	int ret = -EINVAL;
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci	if (adapter->flags & LAN743X_ADAPTER_FLAG_OTP) {
64462306a36Sopenharmony_ci		/* Beware!  OTP is One Time Programming ONLY! */
64562306a36Sopenharmony_ci		if (ee->magic == LAN743X_OTP_MAGIC) {
64662306a36Sopenharmony_ci			if (adapter->is_pci11x1x)
64762306a36Sopenharmony_ci				ret = lan743x_hs_otp_write(adapter, ee->offset,
64862306a36Sopenharmony_ci							   ee->len, data);
64962306a36Sopenharmony_ci			else
65062306a36Sopenharmony_ci				ret = lan743x_otp_write(adapter, ee->offset,
65162306a36Sopenharmony_ci							ee->len, data);
65262306a36Sopenharmony_ci		}
65362306a36Sopenharmony_ci	} else {
65462306a36Sopenharmony_ci		if (ee->magic == LAN743X_EEPROM_MAGIC) {
65562306a36Sopenharmony_ci			if (adapter->is_pci11x1x)
65662306a36Sopenharmony_ci				ret = lan743x_hs_eeprom_write(adapter,
65762306a36Sopenharmony_ci							      ee->offset,
65862306a36Sopenharmony_ci							      ee->len, data);
65962306a36Sopenharmony_ci			else
66062306a36Sopenharmony_ci				ret = lan743x_eeprom_write(adapter, ee->offset,
66162306a36Sopenharmony_ci							   ee->len, data);
66262306a36Sopenharmony_ci		}
66362306a36Sopenharmony_ci	}
66462306a36Sopenharmony_ci
66562306a36Sopenharmony_ci	return ret;
66662306a36Sopenharmony_ci}
66762306a36Sopenharmony_ci
66862306a36Sopenharmony_cistatic const char lan743x_set0_hw_cnt_strings[][ETH_GSTRING_LEN] = {
66962306a36Sopenharmony_ci	"RX FCS Errors",
67062306a36Sopenharmony_ci	"RX Alignment Errors",
67162306a36Sopenharmony_ci	"Rx Fragment Errors",
67262306a36Sopenharmony_ci	"RX Jabber Errors",
67362306a36Sopenharmony_ci	"RX Undersize Frame Errors",
67462306a36Sopenharmony_ci	"RX Oversize Frame Errors",
67562306a36Sopenharmony_ci	"RX Dropped Frames",
67662306a36Sopenharmony_ci	"RX Unicast Byte Count",
67762306a36Sopenharmony_ci	"RX Broadcast Byte Count",
67862306a36Sopenharmony_ci	"RX Multicast Byte Count",
67962306a36Sopenharmony_ci	"RX Unicast Frames",
68062306a36Sopenharmony_ci	"RX Broadcast Frames",
68162306a36Sopenharmony_ci	"RX Multicast Frames",
68262306a36Sopenharmony_ci	"RX Pause Frames",
68362306a36Sopenharmony_ci	"RX 64 Byte Frames",
68462306a36Sopenharmony_ci	"RX 65 - 127 Byte Frames",
68562306a36Sopenharmony_ci	"RX 128 - 255 Byte Frames",
68662306a36Sopenharmony_ci	"RX 256 - 511 Bytes Frames",
68762306a36Sopenharmony_ci	"RX 512 - 1023 Byte Frames",
68862306a36Sopenharmony_ci	"RX 1024 - 1518 Byte Frames",
68962306a36Sopenharmony_ci	"RX Greater 1518 Byte Frames",
69062306a36Sopenharmony_ci};
69162306a36Sopenharmony_ci
69262306a36Sopenharmony_cistatic const char lan743x_set1_sw_cnt_strings[][ETH_GSTRING_LEN] = {
69362306a36Sopenharmony_ci	"RX Queue 0 Frames",
69462306a36Sopenharmony_ci	"RX Queue 1 Frames",
69562306a36Sopenharmony_ci	"RX Queue 2 Frames",
69662306a36Sopenharmony_ci	"RX Queue 3 Frames",
69762306a36Sopenharmony_ci};
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_cistatic const char lan743x_tx_queue_cnt_strings[][ETH_GSTRING_LEN] = {
70062306a36Sopenharmony_ci	"TX Queue 0 Frames",
70162306a36Sopenharmony_ci	"TX Queue 1 Frames",
70262306a36Sopenharmony_ci	"TX Queue 2 Frames",
70362306a36Sopenharmony_ci	"TX Queue 3 Frames",
70462306a36Sopenharmony_ci	"TX Total Queue Frames",
70562306a36Sopenharmony_ci};
70662306a36Sopenharmony_ci
70762306a36Sopenharmony_cistatic const char lan743x_set2_hw_cnt_strings[][ETH_GSTRING_LEN] = {
70862306a36Sopenharmony_ci	"RX Total Frames",
70962306a36Sopenharmony_ci	"EEE RX LPI Transitions",
71062306a36Sopenharmony_ci	"EEE RX LPI Time",
71162306a36Sopenharmony_ci	"RX Counter Rollover Status",
71262306a36Sopenharmony_ci	"TX FCS Errors",
71362306a36Sopenharmony_ci	"TX Excess Deferral Errors",
71462306a36Sopenharmony_ci	"TX Carrier Errors",
71562306a36Sopenharmony_ci	"TX Bad Byte Count",
71662306a36Sopenharmony_ci	"TX Single Collisions",
71762306a36Sopenharmony_ci	"TX Multiple Collisions",
71862306a36Sopenharmony_ci	"TX Excessive Collision",
71962306a36Sopenharmony_ci	"TX Late Collisions",
72062306a36Sopenharmony_ci	"TX Unicast Byte Count",
72162306a36Sopenharmony_ci	"TX Broadcast Byte Count",
72262306a36Sopenharmony_ci	"TX Multicast Byte Count",
72362306a36Sopenharmony_ci	"TX Unicast Frames",
72462306a36Sopenharmony_ci	"TX Broadcast Frames",
72562306a36Sopenharmony_ci	"TX Multicast Frames",
72662306a36Sopenharmony_ci	"TX Pause Frames",
72762306a36Sopenharmony_ci	"TX 64 Byte Frames",
72862306a36Sopenharmony_ci	"TX 65 - 127 Byte Frames",
72962306a36Sopenharmony_ci	"TX 128 - 255 Byte Frames",
73062306a36Sopenharmony_ci	"TX 256 - 511 Bytes Frames",
73162306a36Sopenharmony_ci	"TX 512 - 1023 Byte Frames",
73262306a36Sopenharmony_ci	"TX 1024 - 1518 Byte Frames",
73362306a36Sopenharmony_ci	"TX Greater 1518 Byte Frames",
73462306a36Sopenharmony_ci	"TX Total Frames",
73562306a36Sopenharmony_ci	"EEE TX LPI Transitions",
73662306a36Sopenharmony_ci	"EEE TX LPI Time",
73762306a36Sopenharmony_ci	"TX Counter Rollover Status",
73862306a36Sopenharmony_ci};
73962306a36Sopenharmony_ci
74062306a36Sopenharmony_cistatic const u32 lan743x_set0_hw_cnt_addr[] = {
74162306a36Sopenharmony_ci	STAT_RX_FCS_ERRORS,
74262306a36Sopenharmony_ci	STAT_RX_ALIGNMENT_ERRORS,
74362306a36Sopenharmony_ci	STAT_RX_FRAGMENT_ERRORS,
74462306a36Sopenharmony_ci	STAT_RX_JABBER_ERRORS,
74562306a36Sopenharmony_ci	STAT_RX_UNDERSIZE_FRAME_ERRORS,
74662306a36Sopenharmony_ci	STAT_RX_OVERSIZE_FRAME_ERRORS,
74762306a36Sopenharmony_ci	STAT_RX_DROPPED_FRAMES,
74862306a36Sopenharmony_ci	STAT_RX_UNICAST_BYTE_COUNT,
74962306a36Sopenharmony_ci	STAT_RX_BROADCAST_BYTE_COUNT,
75062306a36Sopenharmony_ci	STAT_RX_MULTICAST_BYTE_COUNT,
75162306a36Sopenharmony_ci	STAT_RX_UNICAST_FRAMES,
75262306a36Sopenharmony_ci	STAT_RX_BROADCAST_FRAMES,
75362306a36Sopenharmony_ci	STAT_RX_MULTICAST_FRAMES,
75462306a36Sopenharmony_ci	STAT_RX_PAUSE_FRAMES,
75562306a36Sopenharmony_ci	STAT_RX_64_BYTE_FRAMES,
75662306a36Sopenharmony_ci	STAT_RX_65_127_BYTE_FRAMES,
75762306a36Sopenharmony_ci	STAT_RX_128_255_BYTE_FRAMES,
75862306a36Sopenharmony_ci	STAT_RX_256_511_BYTES_FRAMES,
75962306a36Sopenharmony_ci	STAT_RX_512_1023_BYTE_FRAMES,
76062306a36Sopenharmony_ci	STAT_RX_1024_1518_BYTE_FRAMES,
76162306a36Sopenharmony_ci	STAT_RX_GREATER_1518_BYTE_FRAMES,
76262306a36Sopenharmony_ci};
76362306a36Sopenharmony_ci
76462306a36Sopenharmony_cistatic const u32 lan743x_set2_hw_cnt_addr[] = {
76562306a36Sopenharmony_ci	STAT_RX_TOTAL_FRAMES,
76662306a36Sopenharmony_ci	STAT_EEE_RX_LPI_TRANSITIONS,
76762306a36Sopenharmony_ci	STAT_EEE_RX_LPI_TIME,
76862306a36Sopenharmony_ci	STAT_RX_COUNTER_ROLLOVER_STATUS,
76962306a36Sopenharmony_ci	STAT_TX_FCS_ERRORS,
77062306a36Sopenharmony_ci	STAT_TX_EXCESS_DEFERRAL_ERRORS,
77162306a36Sopenharmony_ci	STAT_TX_CARRIER_ERRORS,
77262306a36Sopenharmony_ci	STAT_TX_BAD_BYTE_COUNT,
77362306a36Sopenharmony_ci	STAT_TX_SINGLE_COLLISIONS,
77462306a36Sopenharmony_ci	STAT_TX_MULTIPLE_COLLISIONS,
77562306a36Sopenharmony_ci	STAT_TX_EXCESSIVE_COLLISION,
77662306a36Sopenharmony_ci	STAT_TX_LATE_COLLISIONS,
77762306a36Sopenharmony_ci	STAT_TX_UNICAST_BYTE_COUNT,
77862306a36Sopenharmony_ci	STAT_TX_BROADCAST_BYTE_COUNT,
77962306a36Sopenharmony_ci	STAT_TX_MULTICAST_BYTE_COUNT,
78062306a36Sopenharmony_ci	STAT_TX_UNICAST_FRAMES,
78162306a36Sopenharmony_ci	STAT_TX_BROADCAST_FRAMES,
78262306a36Sopenharmony_ci	STAT_TX_MULTICAST_FRAMES,
78362306a36Sopenharmony_ci	STAT_TX_PAUSE_FRAMES,
78462306a36Sopenharmony_ci	STAT_TX_64_BYTE_FRAMES,
78562306a36Sopenharmony_ci	STAT_TX_65_127_BYTE_FRAMES,
78662306a36Sopenharmony_ci	STAT_TX_128_255_BYTE_FRAMES,
78762306a36Sopenharmony_ci	STAT_TX_256_511_BYTES_FRAMES,
78862306a36Sopenharmony_ci	STAT_TX_512_1023_BYTE_FRAMES,
78962306a36Sopenharmony_ci	STAT_TX_1024_1518_BYTE_FRAMES,
79062306a36Sopenharmony_ci	STAT_TX_GREATER_1518_BYTE_FRAMES,
79162306a36Sopenharmony_ci	STAT_TX_TOTAL_FRAMES,
79262306a36Sopenharmony_ci	STAT_EEE_TX_LPI_TRANSITIONS,
79362306a36Sopenharmony_ci	STAT_EEE_TX_LPI_TIME,
79462306a36Sopenharmony_ci	STAT_TX_COUNTER_ROLLOVER_STATUS
79562306a36Sopenharmony_ci};
79662306a36Sopenharmony_ci
79762306a36Sopenharmony_cistatic const char lan743x_priv_flags_strings[][ETH_GSTRING_LEN] = {
79862306a36Sopenharmony_ci	"OTP_ACCESS",
79962306a36Sopenharmony_ci};
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_cistatic void lan743x_ethtool_get_strings(struct net_device *netdev,
80262306a36Sopenharmony_ci					u32 stringset, u8 *data)
80362306a36Sopenharmony_ci{
80462306a36Sopenharmony_ci	struct lan743x_adapter *adapter = netdev_priv(netdev);
80562306a36Sopenharmony_ci
80662306a36Sopenharmony_ci	switch (stringset) {
80762306a36Sopenharmony_ci	case ETH_SS_STATS:
80862306a36Sopenharmony_ci		memcpy(data, lan743x_set0_hw_cnt_strings,
80962306a36Sopenharmony_ci		       sizeof(lan743x_set0_hw_cnt_strings));
81062306a36Sopenharmony_ci		memcpy(&data[sizeof(lan743x_set0_hw_cnt_strings)],
81162306a36Sopenharmony_ci		       lan743x_set1_sw_cnt_strings,
81262306a36Sopenharmony_ci		       sizeof(lan743x_set1_sw_cnt_strings));
81362306a36Sopenharmony_ci		memcpy(&data[sizeof(lan743x_set0_hw_cnt_strings) +
81462306a36Sopenharmony_ci		       sizeof(lan743x_set1_sw_cnt_strings)],
81562306a36Sopenharmony_ci		       lan743x_set2_hw_cnt_strings,
81662306a36Sopenharmony_ci		       sizeof(lan743x_set2_hw_cnt_strings));
81762306a36Sopenharmony_ci		if (adapter->is_pci11x1x) {
81862306a36Sopenharmony_ci			memcpy(&data[sizeof(lan743x_set0_hw_cnt_strings) +
81962306a36Sopenharmony_ci			       sizeof(lan743x_set1_sw_cnt_strings) +
82062306a36Sopenharmony_ci			       sizeof(lan743x_set2_hw_cnt_strings)],
82162306a36Sopenharmony_ci			       lan743x_tx_queue_cnt_strings,
82262306a36Sopenharmony_ci			       sizeof(lan743x_tx_queue_cnt_strings));
82362306a36Sopenharmony_ci		}
82462306a36Sopenharmony_ci		break;
82562306a36Sopenharmony_ci	case ETH_SS_PRIV_FLAGS:
82662306a36Sopenharmony_ci		memcpy(data, lan743x_priv_flags_strings,
82762306a36Sopenharmony_ci		       sizeof(lan743x_priv_flags_strings));
82862306a36Sopenharmony_ci		break;
82962306a36Sopenharmony_ci	}
83062306a36Sopenharmony_ci}
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_cistatic void lan743x_ethtool_get_ethtool_stats(struct net_device *netdev,
83362306a36Sopenharmony_ci					      struct ethtool_stats *stats,
83462306a36Sopenharmony_ci					      u64 *data)
83562306a36Sopenharmony_ci{
83662306a36Sopenharmony_ci	struct lan743x_adapter *adapter = netdev_priv(netdev);
83762306a36Sopenharmony_ci	u64 total_queue_count = 0;
83862306a36Sopenharmony_ci	int data_index = 0;
83962306a36Sopenharmony_ci	u64 pkt_cnt;
84062306a36Sopenharmony_ci	u32 buf;
84162306a36Sopenharmony_ci	int i;
84262306a36Sopenharmony_ci
84362306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(lan743x_set0_hw_cnt_addr); i++) {
84462306a36Sopenharmony_ci		buf = lan743x_csr_read(adapter, lan743x_set0_hw_cnt_addr[i]);
84562306a36Sopenharmony_ci		data[data_index++] = (u64)buf;
84662306a36Sopenharmony_ci	}
84762306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(adapter->rx); i++)
84862306a36Sopenharmony_ci		data[data_index++] = (u64)(adapter->rx[i].frame_count);
84962306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(lan743x_set2_hw_cnt_addr); i++) {
85062306a36Sopenharmony_ci		buf = lan743x_csr_read(adapter, lan743x_set2_hw_cnt_addr[i]);
85162306a36Sopenharmony_ci		data[data_index++] = (u64)buf;
85262306a36Sopenharmony_ci	}
85362306a36Sopenharmony_ci	if (adapter->is_pci11x1x) {
85462306a36Sopenharmony_ci		for (i = 0; i < ARRAY_SIZE(adapter->tx); i++) {
85562306a36Sopenharmony_ci			pkt_cnt = (u64)(adapter->tx[i].frame_count);
85662306a36Sopenharmony_ci			data[data_index++] = pkt_cnt;
85762306a36Sopenharmony_ci			total_queue_count += pkt_cnt;
85862306a36Sopenharmony_ci		}
85962306a36Sopenharmony_ci		data[data_index++] = total_queue_count;
86062306a36Sopenharmony_ci	}
86162306a36Sopenharmony_ci}
86262306a36Sopenharmony_ci
86362306a36Sopenharmony_cistatic u32 lan743x_ethtool_get_priv_flags(struct net_device *netdev)
86462306a36Sopenharmony_ci{
86562306a36Sopenharmony_ci	struct lan743x_adapter *adapter = netdev_priv(netdev);
86662306a36Sopenharmony_ci
86762306a36Sopenharmony_ci	return adapter->flags;
86862306a36Sopenharmony_ci}
86962306a36Sopenharmony_ci
87062306a36Sopenharmony_cistatic int lan743x_ethtool_set_priv_flags(struct net_device *netdev, u32 flags)
87162306a36Sopenharmony_ci{
87262306a36Sopenharmony_ci	struct lan743x_adapter *adapter = netdev_priv(netdev);
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_ci	adapter->flags = flags;
87562306a36Sopenharmony_ci
87662306a36Sopenharmony_ci	return 0;
87762306a36Sopenharmony_ci}
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_cistatic int lan743x_ethtool_get_sset_count(struct net_device *netdev, int sset)
88062306a36Sopenharmony_ci{
88162306a36Sopenharmony_ci	struct lan743x_adapter *adapter = netdev_priv(netdev);
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_ci	switch (sset) {
88462306a36Sopenharmony_ci	case ETH_SS_STATS:
88562306a36Sopenharmony_ci	{
88662306a36Sopenharmony_ci		int ret;
88762306a36Sopenharmony_ci
88862306a36Sopenharmony_ci		ret = ARRAY_SIZE(lan743x_set0_hw_cnt_strings);
88962306a36Sopenharmony_ci		ret += ARRAY_SIZE(lan743x_set1_sw_cnt_strings);
89062306a36Sopenharmony_ci		ret += ARRAY_SIZE(lan743x_set2_hw_cnt_strings);
89162306a36Sopenharmony_ci		if (adapter->is_pci11x1x)
89262306a36Sopenharmony_ci			ret += ARRAY_SIZE(lan743x_tx_queue_cnt_strings);
89362306a36Sopenharmony_ci		return ret;
89462306a36Sopenharmony_ci	}
89562306a36Sopenharmony_ci	case ETH_SS_PRIV_FLAGS:
89662306a36Sopenharmony_ci		return ARRAY_SIZE(lan743x_priv_flags_strings);
89762306a36Sopenharmony_ci	default:
89862306a36Sopenharmony_ci		return -EOPNOTSUPP;
89962306a36Sopenharmony_ci	}
90062306a36Sopenharmony_ci}
90162306a36Sopenharmony_ci
90262306a36Sopenharmony_cistatic int lan743x_ethtool_get_rxnfc(struct net_device *netdev,
90362306a36Sopenharmony_ci				     struct ethtool_rxnfc *rxnfc,
90462306a36Sopenharmony_ci				     u32 *rule_locs)
90562306a36Sopenharmony_ci{
90662306a36Sopenharmony_ci	switch (rxnfc->cmd) {
90762306a36Sopenharmony_ci	case ETHTOOL_GRXFH:
90862306a36Sopenharmony_ci		rxnfc->data = 0;
90962306a36Sopenharmony_ci		switch (rxnfc->flow_type) {
91062306a36Sopenharmony_ci		case TCP_V4_FLOW:case UDP_V4_FLOW:
91162306a36Sopenharmony_ci		case TCP_V6_FLOW:case UDP_V6_FLOW:
91262306a36Sopenharmony_ci			rxnfc->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
91362306a36Sopenharmony_ci			fallthrough;
91462306a36Sopenharmony_ci		case IPV4_FLOW: case IPV6_FLOW:
91562306a36Sopenharmony_ci			rxnfc->data |= RXH_IP_SRC | RXH_IP_DST;
91662306a36Sopenharmony_ci			return 0;
91762306a36Sopenharmony_ci		}
91862306a36Sopenharmony_ci		break;
91962306a36Sopenharmony_ci	case ETHTOOL_GRXRINGS:
92062306a36Sopenharmony_ci		rxnfc->data = LAN743X_USED_RX_CHANNELS;
92162306a36Sopenharmony_ci		return 0;
92262306a36Sopenharmony_ci	}
92362306a36Sopenharmony_ci	return -EOPNOTSUPP;
92462306a36Sopenharmony_ci}
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_cistatic u32 lan743x_ethtool_get_rxfh_key_size(struct net_device *netdev)
92762306a36Sopenharmony_ci{
92862306a36Sopenharmony_ci	return 40;
92962306a36Sopenharmony_ci}
93062306a36Sopenharmony_ci
93162306a36Sopenharmony_cistatic u32 lan743x_ethtool_get_rxfh_indir_size(struct net_device *netdev)
93262306a36Sopenharmony_ci{
93362306a36Sopenharmony_ci	return 128;
93462306a36Sopenharmony_ci}
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_cistatic int lan743x_ethtool_get_rxfh(struct net_device *netdev,
93762306a36Sopenharmony_ci				    u32 *indir, u8 *key, u8 *hfunc)
93862306a36Sopenharmony_ci{
93962306a36Sopenharmony_ci	struct lan743x_adapter *adapter = netdev_priv(netdev);
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_ci	if (indir) {
94262306a36Sopenharmony_ci		int dw_index;
94362306a36Sopenharmony_ci		int byte_index = 0;
94462306a36Sopenharmony_ci
94562306a36Sopenharmony_ci		for (dw_index = 0; dw_index < 32; dw_index++) {
94662306a36Sopenharmony_ci			u32 four_entries =
94762306a36Sopenharmony_ci				lan743x_csr_read(adapter, RFE_INDX(dw_index));
94862306a36Sopenharmony_ci
94962306a36Sopenharmony_ci			byte_index = dw_index << 2;
95062306a36Sopenharmony_ci			indir[byte_index + 0] =
95162306a36Sopenharmony_ci				((four_entries >> 0) & 0x000000FF);
95262306a36Sopenharmony_ci			indir[byte_index + 1] =
95362306a36Sopenharmony_ci				((four_entries >> 8) & 0x000000FF);
95462306a36Sopenharmony_ci			indir[byte_index + 2] =
95562306a36Sopenharmony_ci				((four_entries >> 16) & 0x000000FF);
95662306a36Sopenharmony_ci			indir[byte_index + 3] =
95762306a36Sopenharmony_ci				((four_entries >> 24) & 0x000000FF);
95862306a36Sopenharmony_ci		}
95962306a36Sopenharmony_ci	}
96062306a36Sopenharmony_ci	if (key) {
96162306a36Sopenharmony_ci		int dword_index;
96262306a36Sopenharmony_ci		int byte_index = 0;
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_ci		for (dword_index = 0; dword_index < 10; dword_index++) {
96562306a36Sopenharmony_ci			u32 four_entries =
96662306a36Sopenharmony_ci				lan743x_csr_read(adapter,
96762306a36Sopenharmony_ci						 RFE_HASH_KEY(dword_index));
96862306a36Sopenharmony_ci
96962306a36Sopenharmony_ci			byte_index = dword_index << 2;
97062306a36Sopenharmony_ci			key[byte_index + 0] =
97162306a36Sopenharmony_ci				((four_entries >> 0) & 0x000000FF);
97262306a36Sopenharmony_ci			key[byte_index + 1] =
97362306a36Sopenharmony_ci				((four_entries >> 8) & 0x000000FF);
97462306a36Sopenharmony_ci			key[byte_index + 2] =
97562306a36Sopenharmony_ci				((four_entries >> 16) & 0x000000FF);
97662306a36Sopenharmony_ci			key[byte_index + 3] =
97762306a36Sopenharmony_ci				((four_entries >> 24) & 0x000000FF);
97862306a36Sopenharmony_ci		}
97962306a36Sopenharmony_ci	}
98062306a36Sopenharmony_ci	if (hfunc)
98162306a36Sopenharmony_ci		(*hfunc) = ETH_RSS_HASH_TOP;
98262306a36Sopenharmony_ci	return 0;
98362306a36Sopenharmony_ci}
98462306a36Sopenharmony_ci
98562306a36Sopenharmony_cistatic int lan743x_ethtool_set_rxfh(struct net_device *netdev,
98662306a36Sopenharmony_ci				    const u32 *indir, const u8 *key,
98762306a36Sopenharmony_ci				    const u8 hfunc)
98862306a36Sopenharmony_ci{
98962306a36Sopenharmony_ci	struct lan743x_adapter *adapter = netdev_priv(netdev);
99062306a36Sopenharmony_ci
99162306a36Sopenharmony_ci	if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
99262306a36Sopenharmony_ci		return -EOPNOTSUPP;
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_ci	if (indir) {
99562306a36Sopenharmony_ci		u32 indir_value = 0;
99662306a36Sopenharmony_ci		int dword_index = 0;
99762306a36Sopenharmony_ci		int byte_index = 0;
99862306a36Sopenharmony_ci
99962306a36Sopenharmony_ci		for (dword_index = 0; dword_index < 32; dword_index++) {
100062306a36Sopenharmony_ci			byte_index = dword_index << 2;
100162306a36Sopenharmony_ci			indir_value =
100262306a36Sopenharmony_ci				(((indir[byte_index + 0] & 0x000000FF) << 0) |
100362306a36Sopenharmony_ci				((indir[byte_index + 1] & 0x000000FF) << 8) |
100462306a36Sopenharmony_ci				((indir[byte_index + 2] & 0x000000FF) << 16) |
100562306a36Sopenharmony_ci				((indir[byte_index + 3] & 0x000000FF) << 24));
100662306a36Sopenharmony_ci			lan743x_csr_write(adapter, RFE_INDX(dword_index),
100762306a36Sopenharmony_ci					  indir_value);
100862306a36Sopenharmony_ci		}
100962306a36Sopenharmony_ci	}
101062306a36Sopenharmony_ci	if (key) {
101162306a36Sopenharmony_ci		int dword_index = 0;
101262306a36Sopenharmony_ci		int byte_index = 0;
101362306a36Sopenharmony_ci		u32 key_value = 0;
101462306a36Sopenharmony_ci
101562306a36Sopenharmony_ci		for (dword_index = 0; dword_index < 10; dword_index++) {
101662306a36Sopenharmony_ci			byte_index = dword_index << 2;
101762306a36Sopenharmony_ci			key_value =
101862306a36Sopenharmony_ci				((((u32)(key[byte_index + 0])) << 0) |
101962306a36Sopenharmony_ci				(((u32)(key[byte_index + 1])) << 8) |
102062306a36Sopenharmony_ci				(((u32)(key[byte_index + 2])) << 16) |
102162306a36Sopenharmony_ci				(((u32)(key[byte_index + 3])) << 24));
102262306a36Sopenharmony_ci			lan743x_csr_write(adapter, RFE_HASH_KEY(dword_index),
102362306a36Sopenharmony_ci					  key_value);
102462306a36Sopenharmony_ci		}
102562306a36Sopenharmony_ci	}
102662306a36Sopenharmony_ci	return 0;
102762306a36Sopenharmony_ci}
102862306a36Sopenharmony_ci
102962306a36Sopenharmony_cistatic int lan743x_ethtool_get_ts_info(struct net_device *netdev,
103062306a36Sopenharmony_ci				       struct ethtool_ts_info *ts_info)
103162306a36Sopenharmony_ci{
103262306a36Sopenharmony_ci	struct lan743x_adapter *adapter = netdev_priv(netdev);
103362306a36Sopenharmony_ci
103462306a36Sopenharmony_ci	ts_info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
103562306a36Sopenharmony_ci				   SOF_TIMESTAMPING_RX_SOFTWARE |
103662306a36Sopenharmony_ci				   SOF_TIMESTAMPING_SOFTWARE |
103762306a36Sopenharmony_ci				   SOF_TIMESTAMPING_TX_HARDWARE |
103862306a36Sopenharmony_ci				   SOF_TIMESTAMPING_RX_HARDWARE |
103962306a36Sopenharmony_ci				   SOF_TIMESTAMPING_RAW_HARDWARE;
104062306a36Sopenharmony_ci
104162306a36Sopenharmony_ci	if (adapter->ptp.ptp_clock)
104262306a36Sopenharmony_ci		ts_info->phc_index = ptp_clock_index(adapter->ptp.ptp_clock);
104362306a36Sopenharmony_ci	else
104462306a36Sopenharmony_ci		ts_info->phc_index = -1;
104562306a36Sopenharmony_ci
104662306a36Sopenharmony_ci	ts_info->tx_types = BIT(HWTSTAMP_TX_OFF) |
104762306a36Sopenharmony_ci			    BIT(HWTSTAMP_TX_ON) |
104862306a36Sopenharmony_ci			    BIT(HWTSTAMP_TX_ONESTEP_SYNC);
104962306a36Sopenharmony_ci	ts_info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
105062306a36Sopenharmony_ci			      BIT(HWTSTAMP_FILTER_ALL);
105162306a36Sopenharmony_ci	return 0;
105262306a36Sopenharmony_ci}
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_cistatic int lan743x_ethtool_get_eee(struct net_device *netdev,
105562306a36Sopenharmony_ci				   struct ethtool_eee *eee)
105662306a36Sopenharmony_ci{
105762306a36Sopenharmony_ci	struct lan743x_adapter *adapter = netdev_priv(netdev);
105862306a36Sopenharmony_ci	struct phy_device *phydev = netdev->phydev;
105962306a36Sopenharmony_ci	u32 buf;
106062306a36Sopenharmony_ci	int ret;
106162306a36Sopenharmony_ci
106262306a36Sopenharmony_ci	if (!phydev)
106362306a36Sopenharmony_ci		return -EIO;
106462306a36Sopenharmony_ci	if (!phydev->drv) {
106562306a36Sopenharmony_ci		netif_err(adapter, drv, adapter->netdev,
106662306a36Sopenharmony_ci			  "Missing PHY Driver\n");
106762306a36Sopenharmony_ci		return -EIO;
106862306a36Sopenharmony_ci	}
106962306a36Sopenharmony_ci
107062306a36Sopenharmony_ci	ret = phy_ethtool_get_eee(phydev, eee);
107162306a36Sopenharmony_ci	if (ret < 0)
107262306a36Sopenharmony_ci		return ret;
107362306a36Sopenharmony_ci
107462306a36Sopenharmony_ci	buf = lan743x_csr_read(adapter, MAC_CR);
107562306a36Sopenharmony_ci	if (buf & MAC_CR_EEE_EN_) {
107662306a36Sopenharmony_ci		eee->eee_enabled = true;
107762306a36Sopenharmony_ci		eee->eee_active = !!(eee->advertised & eee->lp_advertised);
107862306a36Sopenharmony_ci		eee->tx_lpi_enabled = true;
107962306a36Sopenharmony_ci		/* EEE_TX_LPI_REQ_DLY & tx_lpi_timer are same uSec unit */
108062306a36Sopenharmony_ci		buf = lan743x_csr_read(adapter, MAC_EEE_TX_LPI_REQ_DLY_CNT);
108162306a36Sopenharmony_ci		eee->tx_lpi_timer = buf;
108262306a36Sopenharmony_ci	} else {
108362306a36Sopenharmony_ci		eee->eee_enabled = false;
108462306a36Sopenharmony_ci		eee->eee_active = false;
108562306a36Sopenharmony_ci		eee->tx_lpi_enabled = false;
108662306a36Sopenharmony_ci		eee->tx_lpi_timer = 0;
108762306a36Sopenharmony_ci	}
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_ci	return 0;
109062306a36Sopenharmony_ci}
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_cistatic int lan743x_ethtool_set_eee(struct net_device *netdev,
109362306a36Sopenharmony_ci				   struct ethtool_eee *eee)
109462306a36Sopenharmony_ci{
109562306a36Sopenharmony_ci	struct lan743x_adapter *adapter;
109662306a36Sopenharmony_ci	struct phy_device *phydev;
109762306a36Sopenharmony_ci	u32 buf = 0;
109862306a36Sopenharmony_ci	int ret = 0;
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci	if (!netdev)
110162306a36Sopenharmony_ci		return -EINVAL;
110262306a36Sopenharmony_ci	adapter = netdev_priv(netdev);
110362306a36Sopenharmony_ci	if (!adapter)
110462306a36Sopenharmony_ci		return -EINVAL;
110562306a36Sopenharmony_ci	phydev = netdev->phydev;
110662306a36Sopenharmony_ci	if (!phydev)
110762306a36Sopenharmony_ci		return -EIO;
110862306a36Sopenharmony_ci	if (!phydev->drv) {
110962306a36Sopenharmony_ci		netif_err(adapter, drv, adapter->netdev,
111062306a36Sopenharmony_ci			  "Missing PHY Driver\n");
111162306a36Sopenharmony_ci		return -EIO;
111262306a36Sopenharmony_ci	}
111362306a36Sopenharmony_ci
111462306a36Sopenharmony_ci	if (eee->eee_enabled) {
111562306a36Sopenharmony_ci		ret = phy_init_eee(phydev, false);
111662306a36Sopenharmony_ci		if (ret) {
111762306a36Sopenharmony_ci			netif_err(adapter, drv, adapter->netdev,
111862306a36Sopenharmony_ci				  "EEE initialization failed\n");
111962306a36Sopenharmony_ci			return ret;
112062306a36Sopenharmony_ci		}
112162306a36Sopenharmony_ci
112262306a36Sopenharmony_ci		buf = (u32)eee->tx_lpi_timer;
112362306a36Sopenharmony_ci		lan743x_csr_write(adapter, MAC_EEE_TX_LPI_REQ_DLY_CNT, buf);
112462306a36Sopenharmony_ci
112562306a36Sopenharmony_ci		buf = lan743x_csr_read(adapter, MAC_CR);
112662306a36Sopenharmony_ci		buf |= MAC_CR_EEE_EN_;
112762306a36Sopenharmony_ci		lan743x_csr_write(adapter, MAC_CR, buf);
112862306a36Sopenharmony_ci	} else {
112962306a36Sopenharmony_ci		buf = lan743x_csr_read(adapter, MAC_CR);
113062306a36Sopenharmony_ci		buf &= ~MAC_CR_EEE_EN_;
113162306a36Sopenharmony_ci		lan743x_csr_write(adapter, MAC_CR, buf);
113262306a36Sopenharmony_ci	}
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci	return phy_ethtool_set_eee(phydev, eee);
113562306a36Sopenharmony_ci}
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ci#ifdef CONFIG_PM
113862306a36Sopenharmony_cistatic void lan743x_ethtool_get_wol(struct net_device *netdev,
113962306a36Sopenharmony_ci				    struct ethtool_wolinfo *wol)
114062306a36Sopenharmony_ci{
114162306a36Sopenharmony_ci	struct lan743x_adapter *adapter = netdev_priv(netdev);
114262306a36Sopenharmony_ci
114362306a36Sopenharmony_ci	wol->supported = 0;
114462306a36Sopenharmony_ci	wol->wolopts = 0;
114562306a36Sopenharmony_ci
114662306a36Sopenharmony_ci	if (netdev->phydev)
114762306a36Sopenharmony_ci		phy_ethtool_get_wol(netdev->phydev, wol);
114862306a36Sopenharmony_ci
114962306a36Sopenharmony_ci	wol->supported |= WAKE_BCAST | WAKE_UCAST | WAKE_MCAST |
115062306a36Sopenharmony_ci		WAKE_MAGIC | WAKE_PHY | WAKE_ARP;
115162306a36Sopenharmony_ci
115262306a36Sopenharmony_ci	if (adapter->is_pci11x1x)
115362306a36Sopenharmony_ci		wol->supported |= WAKE_MAGICSECURE;
115462306a36Sopenharmony_ci
115562306a36Sopenharmony_ci	wol->wolopts |= adapter->wolopts;
115662306a36Sopenharmony_ci	if (adapter->wolopts & WAKE_MAGICSECURE)
115762306a36Sopenharmony_ci		memcpy(wol->sopass, adapter->sopass, sizeof(wol->sopass));
115862306a36Sopenharmony_ci}
115962306a36Sopenharmony_ci
116062306a36Sopenharmony_cistatic int lan743x_ethtool_set_wol(struct net_device *netdev,
116162306a36Sopenharmony_ci				   struct ethtool_wolinfo *wol)
116262306a36Sopenharmony_ci{
116362306a36Sopenharmony_ci	struct lan743x_adapter *adapter = netdev_priv(netdev);
116462306a36Sopenharmony_ci
116562306a36Sopenharmony_ci	adapter->wolopts = 0;
116662306a36Sopenharmony_ci	if (wol->wolopts & WAKE_UCAST)
116762306a36Sopenharmony_ci		adapter->wolopts |= WAKE_UCAST;
116862306a36Sopenharmony_ci	if (wol->wolopts & WAKE_MCAST)
116962306a36Sopenharmony_ci		adapter->wolopts |= WAKE_MCAST;
117062306a36Sopenharmony_ci	if (wol->wolopts & WAKE_BCAST)
117162306a36Sopenharmony_ci		adapter->wolopts |= WAKE_BCAST;
117262306a36Sopenharmony_ci	if (wol->wolopts & WAKE_MAGIC)
117362306a36Sopenharmony_ci		adapter->wolopts |= WAKE_MAGIC;
117462306a36Sopenharmony_ci	if (wol->wolopts & WAKE_PHY)
117562306a36Sopenharmony_ci		adapter->wolopts |= WAKE_PHY;
117662306a36Sopenharmony_ci	if (wol->wolopts & WAKE_ARP)
117762306a36Sopenharmony_ci		adapter->wolopts |= WAKE_ARP;
117862306a36Sopenharmony_ci	if (wol->wolopts & WAKE_MAGICSECURE &&
117962306a36Sopenharmony_ci	    wol->wolopts & WAKE_MAGIC) {
118062306a36Sopenharmony_ci		memcpy(adapter->sopass, wol->sopass, sizeof(wol->sopass));
118162306a36Sopenharmony_ci		adapter->wolopts |= WAKE_MAGICSECURE;
118262306a36Sopenharmony_ci	} else {
118362306a36Sopenharmony_ci		memset(adapter->sopass, 0, sizeof(u8) * SOPASS_MAX);
118462306a36Sopenharmony_ci	}
118562306a36Sopenharmony_ci
118662306a36Sopenharmony_ci	device_set_wakeup_enable(&adapter->pdev->dev, (bool)wol->wolopts);
118762306a36Sopenharmony_ci
118862306a36Sopenharmony_ci	return netdev->phydev ? phy_ethtool_set_wol(netdev->phydev, wol)
118962306a36Sopenharmony_ci			: -ENETDOWN;
119062306a36Sopenharmony_ci}
119162306a36Sopenharmony_ci#endif /* CONFIG_PM */
119262306a36Sopenharmony_ci
119362306a36Sopenharmony_cistatic void lan743x_common_regs(struct net_device *dev, void *p)
119462306a36Sopenharmony_ci{
119562306a36Sopenharmony_ci	struct lan743x_adapter *adapter = netdev_priv(dev);
119662306a36Sopenharmony_ci	u32 *rb = p;
119762306a36Sopenharmony_ci
119862306a36Sopenharmony_ci	memset(p, 0, (MAX_LAN743X_ETH_COMMON_REGS * sizeof(u32)));
119962306a36Sopenharmony_ci
120062306a36Sopenharmony_ci	rb[ETH_PRIV_FLAGS] = adapter->flags;
120162306a36Sopenharmony_ci	rb[ETH_ID_REV]     = lan743x_csr_read(adapter, ID_REV);
120262306a36Sopenharmony_ci	rb[ETH_FPGA_REV]   = lan743x_csr_read(adapter, FPGA_REV);
120362306a36Sopenharmony_ci	rb[ETH_STRAP_READ] = lan743x_csr_read(adapter, STRAP_READ);
120462306a36Sopenharmony_ci	rb[ETH_INT_STS]    = lan743x_csr_read(adapter, INT_STS);
120562306a36Sopenharmony_ci	rb[ETH_HW_CFG]     = lan743x_csr_read(adapter, HW_CFG);
120662306a36Sopenharmony_ci	rb[ETH_PMT_CTL]    = lan743x_csr_read(adapter, PMT_CTL);
120762306a36Sopenharmony_ci	rb[ETH_E2P_CMD]    = lan743x_csr_read(adapter, E2P_CMD);
120862306a36Sopenharmony_ci	rb[ETH_E2P_DATA]   = lan743x_csr_read(adapter, E2P_DATA);
120962306a36Sopenharmony_ci	rb[ETH_MAC_CR]     = lan743x_csr_read(adapter, MAC_CR);
121062306a36Sopenharmony_ci	rb[ETH_MAC_RX]     = lan743x_csr_read(adapter, MAC_RX);
121162306a36Sopenharmony_ci	rb[ETH_MAC_TX]     = lan743x_csr_read(adapter, MAC_TX);
121262306a36Sopenharmony_ci	rb[ETH_FLOW]       = lan743x_csr_read(adapter, MAC_FLOW);
121362306a36Sopenharmony_ci	rb[ETH_MII_ACC]    = lan743x_csr_read(adapter, MAC_MII_ACC);
121462306a36Sopenharmony_ci	rb[ETH_MII_DATA]   = lan743x_csr_read(adapter, MAC_MII_DATA);
121562306a36Sopenharmony_ci	rb[ETH_EEE_TX_LPI_REQ_DLY]  = lan743x_csr_read(adapter,
121662306a36Sopenharmony_ci						       MAC_EEE_TX_LPI_REQ_DLY_CNT);
121762306a36Sopenharmony_ci	rb[ETH_WUCSR]      = lan743x_csr_read(adapter, MAC_WUCSR);
121862306a36Sopenharmony_ci	rb[ETH_WK_SRC]     = lan743x_csr_read(adapter, MAC_WK_SRC);
121962306a36Sopenharmony_ci}
122062306a36Sopenharmony_ci
122162306a36Sopenharmony_cistatic void lan743x_sgmii_regs(struct net_device *dev, void *p)
122262306a36Sopenharmony_ci{
122362306a36Sopenharmony_ci	struct lan743x_adapter *adp = netdev_priv(dev);
122462306a36Sopenharmony_ci	u32 *rb = p;
122562306a36Sopenharmony_ci	u16 idx;
122662306a36Sopenharmony_ci	int val;
122762306a36Sopenharmony_ci	struct {
122862306a36Sopenharmony_ci		u8 id;
122962306a36Sopenharmony_ci		u8 dev;
123062306a36Sopenharmony_ci		u16 addr;
123162306a36Sopenharmony_ci	} regs[] = {
123262306a36Sopenharmony_ci		{ ETH_SR_VSMMD_DEV_ID1,                MDIO_MMD_VEND1, 0x0002},
123362306a36Sopenharmony_ci		{ ETH_SR_VSMMD_DEV_ID2,                MDIO_MMD_VEND1, 0x0003},
123462306a36Sopenharmony_ci		{ ETH_SR_VSMMD_PCS_ID1,                MDIO_MMD_VEND1, 0x0004},
123562306a36Sopenharmony_ci		{ ETH_SR_VSMMD_PCS_ID2,                MDIO_MMD_VEND1, 0x0005},
123662306a36Sopenharmony_ci		{ ETH_SR_VSMMD_STS,                    MDIO_MMD_VEND1, 0x0008},
123762306a36Sopenharmony_ci		{ ETH_SR_VSMMD_CTRL,                   MDIO_MMD_VEND1, 0x0009},
123862306a36Sopenharmony_ci		{ ETH_SR_MII_CTRL,                     MDIO_MMD_VEND2, 0x0000},
123962306a36Sopenharmony_ci		{ ETH_SR_MII_STS,                      MDIO_MMD_VEND2, 0x0001},
124062306a36Sopenharmony_ci		{ ETH_SR_MII_DEV_ID1,                  MDIO_MMD_VEND2, 0x0002},
124162306a36Sopenharmony_ci		{ ETH_SR_MII_DEV_ID2,                  MDIO_MMD_VEND2, 0x0003},
124262306a36Sopenharmony_ci		{ ETH_SR_MII_AN_ADV,                   MDIO_MMD_VEND2, 0x0004},
124362306a36Sopenharmony_ci		{ ETH_SR_MII_LP_BABL,                  MDIO_MMD_VEND2, 0x0005},
124462306a36Sopenharmony_ci		{ ETH_SR_MII_EXPN,                     MDIO_MMD_VEND2, 0x0006},
124562306a36Sopenharmony_ci		{ ETH_SR_MII_EXT_STS,                  MDIO_MMD_VEND2, 0x000F},
124662306a36Sopenharmony_ci		{ ETH_SR_MII_TIME_SYNC_ABL,            MDIO_MMD_VEND2, 0x0708},
124762306a36Sopenharmony_ci		{ ETH_SR_MII_TIME_SYNC_TX_MAX_DLY_LWR, MDIO_MMD_VEND2, 0x0709},
124862306a36Sopenharmony_ci		{ ETH_SR_MII_TIME_SYNC_TX_MAX_DLY_UPR, MDIO_MMD_VEND2, 0x070A},
124962306a36Sopenharmony_ci		{ ETH_SR_MII_TIME_SYNC_TX_MIN_DLY_LWR, MDIO_MMD_VEND2, 0x070B},
125062306a36Sopenharmony_ci		{ ETH_SR_MII_TIME_SYNC_TX_MIN_DLY_UPR, MDIO_MMD_VEND2, 0x070C},
125162306a36Sopenharmony_ci		{ ETH_SR_MII_TIME_SYNC_RX_MAX_DLY_LWR, MDIO_MMD_VEND2, 0x070D},
125262306a36Sopenharmony_ci		{ ETH_SR_MII_TIME_SYNC_RX_MAX_DLY_UPR, MDIO_MMD_VEND2, 0x070E},
125362306a36Sopenharmony_ci		{ ETH_SR_MII_TIME_SYNC_RX_MIN_DLY_LWR, MDIO_MMD_VEND2, 0x070F},
125462306a36Sopenharmony_ci		{ ETH_SR_MII_TIME_SYNC_RX_MIN_DLY_UPR, MDIO_MMD_VEND2, 0x0710},
125562306a36Sopenharmony_ci		{ ETH_VR_MII_DIG_CTRL1,                MDIO_MMD_VEND2, 0x8000},
125662306a36Sopenharmony_ci		{ ETH_VR_MII_AN_CTRL,                  MDIO_MMD_VEND2, 0x8001},
125762306a36Sopenharmony_ci		{ ETH_VR_MII_AN_INTR_STS,              MDIO_MMD_VEND2, 0x8002},
125862306a36Sopenharmony_ci		{ ETH_VR_MII_TC,                       MDIO_MMD_VEND2, 0x8003},
125962306a36Sopenharmony_ci		{ ETH_VR_MII_DBG_CTRL,                 MDIO_MMD_VEND2, 0x8005},
126062306a36Sopenharmony_ci		{ ETH_VR_MII_EEE_MCTRL0,               MDIO_MMD_VEND2, 0x8006},
126162306a36Sopenharmony_ci		{ ETH_VR_MII_EEE_TXTIMER,              MDIO_MMD_VEND2, 0x8008},
126262306a36Sopenharmony_ci		{ ETH_VR_MII_EEE_RXTIMER,              MDIO_MMD_VEND2, 0x8009},
126362306a36Sopenharmony_ci		{ ETH_VR_MII_LINK_TIMER_CTRL,          MDIO_MMD_VEND2, 0x800A},
126462306a36Sopenharmony_ci		{ ETH_VR_MII_EEE_MCTRL1,               MDIO_MMD_VEND2, 0x800B},
126562306a36Sopenharmony_ci		{ ETH_VR_MII_DIG_STS,                  MDIO_MMD_VEND2, 0x8010},
126662306a36Sopenharmony_ci		{ ETH_VR_MII_ICG_ERRCNT1,              MDIO_MMD_VEND2, 0x8011},
126762306a36Sopenharmony_ci		{ ETH_VR_MII_GPIO,                     MDIO_MMD_VEND2, 0x8015},
126862306a36Sopenharmony_ci		{ ETH_VR_MII_EEE_LPI_STATUS,           MDIO_MMD_VEND2, 0x8016},
126962306a36Sopenharmony_ci		{ ETH_VR_MII_EEE_WKERR,                MDIO_MMD_VEND2, 0x8017},
127062306a36Sopenharmony_ci		{ ETH_VR_MII_MISC_STS,                 MDIO_MMD_VEND2, 0x8018},
127162306a36Sopenharmony_ci		{ ETH_VR_MII_RX_LSTS,                  MDIO_MMD_VEND2, 0x8020},
127262306a36Sopenharmony_ci		{ ETH_VR_MII_GEN2_GEN4_TX_BSTCTRL0,    MDIO_MMD_VEND2, 0x8038},
127362306a36Sopenharmony_ci		{ ETH_VR_MII_GEN2_GEN4_TX_LVLCTRL0,    MDIO_MMD_VEND2, 0x803A},
127462306a36Sopenharmony_ci		{ ETH_VR_MII_GEN2_GEN4_TXGENCTRL0,     MDIO_MMD_VEND2, 0x803C},
127562306a36Sopenharmony_ci		{ ETH_VR_MII_GEN2_GEN4_TXGENCTRL1,     MDIO_MMD_VEND2, 0x803D},
127662306a36Sopenharmony_ci		{ ETH_VR_MII_GEN4_TXGENCTRL2,          MDIO_MMD_VEND2, 0x803E},
127762306a36Sopenharmony_ci		{ ETH_VR_MII_GEN2_GEN4_TX_STS,         MDIO_MMD_VEND2, 0x8048},
127862306a36Sopenharmony_ci		{ ETH_VR_MII_GEN2_GEN4_RXGENCTRL0,     MDIO_MMD_VEND2, 0x8058},
127962306a36Sopenharmony_ci		{ ETH_VR_MII_GEN2_GEN4_RXGENCTRL1,     MDIO_MMD_VEND2, 0x8059},
128062306a36Sopenharmony_ci		{ ETH_VR_MII_GEN4_RXEQ_CTRL,           MDIO_MMD_VEND2, 0x805B},
128162306a36Sopenharmony_ci		{ ETH_VR_MII_GEN4_RXLOS_CTRL0,         MDIO_MMD_VEND2, 0x805D},
128262306a36Sopenharmony_ci		{ ETH_VR_MII_GEN2_GEN4_MPLL_CTRL0,     MDIO_MMD_VEND2, 0x8078},
128362306a36Sopenharmony_ci		{ ETH_VR_MII_GEN2_GEN4_MPLL_CTRL1,     MDIO_MMD_VEND2, 0x8079},
128462306a36Sopenharmony_ci		{ ETH_VR_MII_GEN2_GEN4_MPLL_STS,       MDIO_MMD_VEND2, 0x8088},
128562306a36Sopenharmony_ci		{ ETH_VR_MII_GEN2_GEN4_LVL_CTRL,       MDIO_MMD_VEND2, 0x8090},
128662306a36Sopenharmony_ci		{ ETH_VR_MII_GEN4_MISC_CTRL2,          MDIO_MMD_VEND2, 0x8093},
128762306a36Sopenharmony_ci		{ ETH_VR_MII_GEN2_GEN4_MISC_CTRL0,     MDIO_MMD_VEND2, 0x8099},
128862306a36Sopenharmony_ci		{ ETH_VR_MII_GEN2_GEN4_MISC_CTRL1,     MDIO_MMD_VEND2, 0x809A},
128962306a36Sopenharmony_ci		{ ETH_VR_MII_SNPS_CR_CTRL,             MDIO_MMD_VEND2, 0x80A0},
129062306a36Sopenharmony_ci		{ ETH_VR_MII_SNPS_CR_ADDR,             MDIO_MMD_VEND2, 0x80A1},
129162306a36Sopenharmony_ci		{ ETH_VR_MII_SNPS_CR_DATA,             MDIO_MMD_VEND2, 0x80A2},
129262306a36Sopenharmony_ci		{ ETH_VR_MII_DIG_CTRL2,                MDIO_MMD_VEND2, 0x80E1},
129362306a36Sopenharmony_ci		{ ETH_VR_MII_DIG_ERRCNT,               MDIO_MMD_VEND2, 0x80E2},
129462306a36Sopenharmony_ci	};
129562306a36Sopenharmony_ci
129662306a36Sopenharmony_ci	for (idx = 0; idx < ARRAY_SIZE(regs); idx++) {
129762306a36Sopenharmony_ci		val = lan743x_sgmii_read(adp, regs[idx].dev, regs[idx].addr);
129862306a36Sopenharmony_ci		if (val < 0)
129962306a36Sopenharmony_ci			rb[regs[idx].id] = 0xFFFF;
130062306a36Sopenharmony_ci		else
130162306a36Sopenharmony_ci			rb[regs[idx].id] = val;
130262306a36Sopenharmony_ci	}
130362306a36Sopenharmony_ci}
130462306a36Sopenharmony_ci
130562306a36Sopenharmony_cistatic int lan743x_get_regs_len(struct net_device *dev)
130662306a36Sopenharmony_ci{
130762306a36Sopenharmony_ci	struct lan743x_adapter *adapter = netdev_priv(dev);
130862306a36Sopenharmony_ci	u32 num_regs = MAX_LAN743X_ETH_COMMON_REGS;
130962306a36Sopenharmony_ci
131062306a36Sopenharmony_ci	if (adapter->is_sgmii_en)
131162306a36Sopenharmony_ci		num_regs += MAX_LAN743X_ETH_SGMII_REGS;
131262306a36Sopenharmony_ci
131362306a36Sopenharmony_ci	return num_regs * sizeof(u32);
131462306a36Sopenharmony_ci}
131562306a36Sopenharmony_ci
131662306a36Sopenharmony_cistatic void lan743x_get_regs(struct net_device *dev,
131762306a36Sopenharmony_ci			     struct ethtool_regs *regs, void *p)
131862306a36Sopenharmony_ci{
131962306a36Sopenharmony_ci	struct lan743x_adapter *adapter = netdev_priv(dev);
132062306a36Sopenharmony_ci	int regs_len;
132162306a36Sopenharmony_ci
132262306a36Sopenharmony_ci	regs_len = lan743x_get_regs_len(dev);
132362306a36Sopenharmony_ci	memset(p, 0, regs_len);
132462306a36Sopenharmony_ci
132562306a36Sopenharmony_ci	regs->version = LAN743X_ETH_REG_VERSION;
132662306a36Sopenharmony_ci	regs->len = regs_len;
132762306a36Sopenharmony_ci
132862306a36Sopenharmony_ci	lan743x_common_regs(dev, p);
132962306a36Sopenharmony_ci	p = (u32 *)p + MAX_LAN743X_ETH_COMMON_REGS;
133062306a36Sopenharmony_ci
133162306a36Sopenharmony_ci	if (adapter->is_sgmii_en) {
133262306a36Sopenharmony_ci		lan743x_sgmii_regs(dev, p);
133362306a36Sopenharmony_ci		p = (u32 *)p + MAX_LAN743X_ETH_SGMII_REGS;
133462306a36Sopenharmony_ci	}
133562306a36Sopenharmony_ci}
133662306a36Sopenharmony_ci
133762306a36Sopenharmony_cistatic void lan743x_get_pauseparam(struct net_device *dev,
133862306a36Sopenharmony_ci				   struct ethtool_pauseparam *pause)
133962306a36Sopenharmony_ci{
134062306a36Sopenharmony_ci	struct lan743x_adapter *adapter = netdev_priv(dev);
134162306a36Sopenharmony_ci	struct lan743x_phy *phy = &adapter->phy;
134262306a36Sopenharmony_ci
134362306a36Sopenharmony_ci	if (phy->fc_request_control & FLOW_CTRL_TX)
134462306a36Sopenharmony_ci		pause->tx_pause = 1;
134562306a36Sopenharmony_ci	if (phy->fc_request_control & FLOW_CTRL_RX)
134662306a36Sopenharmony_ci		pause->rx_pause = 1;
134762306a36Sopenharmony_ci	pause->autoneg = phy->fc_autoneg;
134862306a36Sopenharmony_ci}
134962306a36Sopenharmony_ci
135062306a36Sopenharmony_cistatic int lan743x_set_pauseparam(struct net_device *dev,
135162306a36Sopenharmony_ci				  struct ethtool_pauseparam *pause)
135262306a36Sopenharmony_ci{
135362306a36Sopenharmony_ci	struct lan743x_adapter *adapter = netdev_priv(dev);
135462306a36Sopenharmony_ci	struct phy_device *phydev = dev->phydev;
135562306a36Sopenharmony_ci	struct lan743x_phy *phy = &adapter->phy;
135662306a36Sopenharmony_ci
135762306a36Sopenharmony_ci	if (!phydev)
135862306a36Sopenharmony_ci		return -ENODEV;
135962306a36Sopenharmony_ci
136062306a36Sopenharmony_ci	if (!phy_validate_pause(phydev, pause))
136162306a36Sopenharmony_ci		return -EINVAL;
136262306a36Sopenharmony_ci
136362306a36Sopenharmony_ci	phy->fc_request_control = 0;
136462306a36Sopenharmony_ci	if (pause->rx_pause)
136562306a36Sopenharmony_ci		phy->fc_request_control |= FLOW_CTRL_RX;
136662306a36Sopenharmony_ci
136762306a36Sopenharmony_ci	if (pause->tx_pause)
136862306a36Sopenharmony_ci		phy->fc_request_control |= FLOW_CTRL_TX;
136962306a36Sopenharmony_ci
137062306a36Sopenharmony_ci	phy->fc_autoneg = pause->autoneg;
137162306a36Sopenharmony_ci
137262306a36Sopenharmony_ci	if (pause->autoneg == AUTONEG_DISABLE)
137362306a36Sopenharmony_ci		lan743x_mac_flow_ctrl_set_enables(adapter, pause->tx_pause,
137462306a36Sopenharmony_ci						  pause->rx_pause);
137562306a36Sopenharmony_ci	else
137662306a36Sopenharmony_ci		phy_set_asym_pause(phydev, pause->rx_pause,  pause->tx_pause);
137762306a36Sopenharmony_ci
137862306a36Sopenharmony_ci	return 0;
137962306a36Sopenharmony_ci}
138062306a36Sopenharmony_ci
138162306a36Sopenharmony_ciconst struct ethtool_ops lan743x_ethtool_ops = {
138262306a36Sopenharmony_ci	.get_drvinfo = lan743x_ethtool_get_drvinfo,
138362306a36Sopenharmony_ci	.get_msglevel = lan743x_ethtool_get_msglevel,
138462306a36Sopenharmony_ci	.set_msglevel = lan743x_ethtool_set_msglevel,
138562306a36Sopenharmony_ci	.get_link = ethtool_op_get_link,
138662306a36Sopenharmony_ci
138762306a36Sopenharmony_ci	.get_eeprom_len = lan743x_ethtool_get_eeprom_len,
138862306a36Sopenharmony_ci	.get_eeprom = lan743x_ethtool_get_eeprom,
138962306a36Sopenharmony_ci	.set_eeprom = lan743x_ethtool_set_eeprom,
139062306a36Sopenharmony_ci	.get_strings = lan743x_ethtool_get_strings,
139162306a36Sopenharmony_ci	.get_ethtool_stats = lan743x_ethtool_get_ethtool_stats,
139262306a36Sopenharmony_ci	.get_priv_flags = lan743x_ethtool_get_priv_flags,
139362306a36Sopenharmony_ci	.set_priv_flags = lan743x_ethtool_set_priv_flags,
139462306a36Sopenharmony_ci	.get_sset_count = lan743x_ethtool_get_sset_count,
139562306a36Sopenharmony_ci	.get_rxnfc = lan743x_ethtool_get_rxnfc,
139662306a36Sopenharmony_ci	.get_rxfh_key_size = lan743x_ethtool_get_rxfh_key_size,
139762306a36Sopenharmony_ci	.get_rxfh_indir_size = lan743x_ethtool_get_rxfh_indir_size,
139862306a36Sopenharmony_ci	.get_rxfh = lan743x_ethtool_get_rxfh,
139962306a36Sopenharmony_ci	.set_rxfh = lan743x_ethtool_set_rxfh,
140062306a36Sopenharmony_ci	.get_ts_info = lan743x_ethtool_get_ts_info,
140162306a36Sopenharmony_ci	.get_eee = lan743x_ethtool_get_eee,
140262306a36Sopenharmony_ci	.set_eee = lan743x_ethtool_set_eee,
140362306a36Sopenharmony_ci	.get_link_ksettings = phy_ethtool_get_link_ksettings,
140462306a36Sopenharmony_ci	.set_link_ksettings = phy_ethtool_set_link_ksettings,
140562306a36Sopenharmony_ci	.get_regs_len = lan743x_get_regs_len,
140662306a36Sopenharmony_ci	.get_regs = lan743x_get_regs,
140762306a36Sopenharmony_ci	.get_pauseparam = lan743x_get_pauseparam,
140862306a36Sopenharmony_ci	.set_pauseparam = lan743x_set_pauseparam,
140962306a36Sopenharmony_ci#ifdef CONFIG_PM
141062306a36Sopenharmony_ci	.get_wol = lan743x_ethtool_get_wol,
141162306a36Sopenharmony_ci	.set_wol = lan743x_ethtool_set_wol,
141262306a36Sopenharmony_ci#endif
141362306a36Sopenharmony_ci};
1414