18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright(c) 2007 Atheros Corporation. All rights reserved.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Derived from Intel e1000 driver
68c2ecf20Sopenharmony_ci * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved.
78c2ecf20Sopenharmony_ci */
88c2ecf20Sopenharmony_ci#include <linux/pci.h>
98c2ecf20Sopenharmony_ci#include <linux/delay.h>
108c2ecf20Sopenharmony_ci#include <linux/mii.h>
118c2ecf20Sopenharmony_ci#include <linux/crc32.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include "atl1e.h"
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci/*
168c2ecf20Sopenharmony_ci * check_eeprom_exist
178c2ecf20Sopenharmony_ci * return 0 if eeprom exist
188c2ecf20Sopenharmony_ci */
198c2ecf20Sopenharmony_ciint atl1e_check_eeprom_exist(struct atl1e_hw *hw)
208c2ecf20Sopenharmony_ci{
218c2ecf20Sopenharmony_ci	u32 value;
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci	value = AT_READ_REG(hw, REG_SPI_FLASH_CTRL);
248c2ecf20Sopenharmony_ci	if (value & SPI_FLASH_CTRL_EN_VPD) {
258c2ecf20Sopenharmony_ci		value &= ~SPI_FLASH_CTRL_EN_VPD;
268c2ecf20Sopenharmony_ci		AT_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value);
278c2ecf20Sopenharmony_ci	}
288c2ecf20Sopenharmony_ci	value = AT_READ_REGW(hw, REG_PCIE_CAP_LIST);
298c2ecf20Sopenharmony_ci	return ((value & 0xFF00) == 0x6C00) ? 0 : 1;
308c2ecf20Sopenharmony_ci}
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_civoid atl1e_hw_set_mac_addr(struct atl1e_hw *hw)
338c2ecf20Sopenharmony_ci{
348c2ecf20Sopenharmony_ci	u32 value;
358c2ecf20Sopenharmony_ci	/*
368c2ecf20Sopenharmony_ci	 * 00-0B-6A-F6-00-DC
378c2ecf20Sopenharmony_ci	 * 0:  6AF600DC 1: 000B
388c2ecf20Sopenharmony_ci	 * low dword
398c2ecf20Sopenharmony_ci	 */
408c2ecf20Sopenharmony_ci	value = (((u32)hw->mac_addr[2]) << 24) |
418c2ecf20Sopenharmony_ci		(((u32)hw->mac_addr[3]) << 16) |
428c2ecf20Sopenharmony_ci		(((u32)hw->mac_addr[4]) << 8)  |
438c2ecf20Sopenharmony_ci		(((u32)hw->mac_addr[5])) ;
448c2ecf20Sopenharmony_ci	AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value);
458c2ecf20Sopenharmony_ci	/* hight dword */
468c2ecf20Sopenharmony_ci	value = (((u32)hw->mac_addr[0]) << 8) |
478c2ecf20Sopenharmony_ci		(((u32)hw->mac_addr[1])) ;
488c2ecf20Sopenharmony_ci	AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value);
498c2ecf20Sopenharmony_ci}
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci/*
528c2ecf20Sopenharmony_ci * atl1e_get_permanent_address
538c2ecf20Sopenharmony_ci * return 0 if get valid mac address,
548c2ecf20Sopenharmony_ci */
558c2ecf20Sopenharmony_cistatic int atl1e_get_permanent_address(struct atl1e_hw *hw)
568c2ecf20Sopenharmony_ci{
578c2ecf20Sopenharmony_ci	u32 addr[2];
588c2ecf20Sopenharmony_ci	u32 i;
598c2ecf20Sopenharmony_ci	u32 twsi_ctrl_data;
608c2ecf20Sopenharmony_ci	u8  eth_addr[ETH_ALEN];
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	if (is_valid_ether_addr(hw->perm_mac_addr))
638c2ecf20Sopenharmony_ci		return 0;
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	/* init */
668c2ecf20Sopenharmony_ci	addr[0] = addr[1] = 0;
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_ci	if (!atl1e_check_eeprom_exist(hw)) {
698c2ecf20Sopenharmony_ci		/* eeprom exist */
708c2ecf20Sopenharmony_ci		twsi_ctrl_data = AT_READ_REG(hw, REG_TWSI_CTRL);
718c2ecf20Sopenharmony_ci		twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART;
728c2ecf20Sopenharmony_ci		AT_WRITE_REG(hw, REG_TWSI_CTRL, twsi_ctrl_data);
738c2ecf20Sopenharmony_ci		for (i = 0; i < AT_TWSI_EEPROM_TIMEOUT; i++) {
748c2ecf20Sopenharmony_ci			msleep(10);
758c2ecf20Sopenharmony_ci			twsi_ctrl_data = AT_READ_REG(hw, REG_TWSI_CTRL);
768c2ecf20Sopenharmony_ci			if ((twsi_ctrl_data & TWSI_CTRL_SW_LDSTART) == 0)
778c2ecf20Sopenharmony_ci				break;
788c2ecf20Sopenharmony_ci		}
798c2ecf20Sopenharmony_ci		if (i >= AT_TWSI_EEPROM_TIMEOUT)
808c2ecf20Sopenharmony_ci			return AT_ERR_TIMEOUT;
818c2ecf20Sopenharmony_ci	}
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci	/* maybe MAC-address is from BIOS */
848c2ecf20Sopenharmony_ci	addr[0] = AT_READ_REG(hw, REG_MAC_STA_ADDR);
858c2ecf20Sopenharmony_ci	addr[1] = AT_READ_REG(hw, REG_MAC_STA_ADDR + 4);
868c2ecf20Sopenharmony_ci	*(u32 *) &eth_addr[2] = swab32(addr[0]);
878c2ecf20Sopenharmony_ci	*(u16 *) &eth_addr[0] = swab16(*(u16 *)&addr[1]);
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci	if (is_valid_ether_addr(eth_addr)) {
908c2ecf20Sopenharmony_ci		memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN);
918c2ecf20Sopenharmony_ci		return 0;
928c2ecf20Sopenharmony_ci	}
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	return AT_ERR_EEPROM;
958c2ecf20Sopenharmony_ci}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_cibool atl1e_write_eeprom(struct atl1e_hw *hw, u32 offset, u32 value)
988c2ecf20Sopenharmony_ci{
998c2ecf20Sopenharmony_ci	return true;
1008c2ecf20Sopenharmony_ci}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_cibool atl1e_read_eeprom(struct atl1e_hw *hw, u32 offset, u32 *p_value)
1038c2ecf20Sopenharmony_ci{
1048c2ecf20Sopenharmony_ci	int i;
1058c2ecf20Sopenharmony_ci	u32 control;
1068c2ecf20Sopenharmony_ci
1078c2ecf20Sopenharmony_ci	if (offset & 3)
1088c2ecf20Sopenharmony_ci		return false; /* address do not align */
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci	AT_WRITE_REG(hw, REG_VPD_DATA, 0);
1118c2ecf20Sopenharmony_ci	control = (offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT;
1128c2ecf20Sopenharmony_ci	AT_WRITE_REG(hw, REG_VPD_CAP, control);
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	for (i = 0; i < 10; i++) {
1158c2ecf20Sopenharmony_ci		msleep(2);
1168c2ecf20Sopenharmony_ci		control = AT_READ_REG(hw, REG_VPD_CAP);
1178c2ecf20Sopenharmony_ci		if (control & VPD_CAP_VPD_FLAG)
1188c2ecf20Sopenharmony_ci			break;
1198c2ecf20Sopenharmony_ci	}
1208c2ecf20Sopenharmony_ci	if (control & VPD_CAP_VPD_FLAG) {
1218c2ecf20Sopenharmony_ci		*p_value = AT_READ_REG(hw, REG_VPD_DATA);
1228c2ecf20Sopenharmony_ci		return true;
1238c2ecf20Sopenharmony_ci	}
1248c2ecf20Sopenharmony_ci	return false; /* timeout */
1258c2ecf20Sopenharmony_ci}
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_civoid atl1e_force_ps(struct atl1e_hw *hw)
1288c2ecf20Sopenharmony_ci{
1298c2ecf20Sopenharmony_ci	AT_WRITE_REGW(hw, REG_GPHY_CTRL,
1308c2ecf20Sopenharmony_ci			GPHY_CTRL_PW_WOL_DIS | GPHY_CTRL_EXT_RESET);
1318c2ecf20Sopenharmony_ci}
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_ci/*
1348c2ecf20Sopenharmony_ci * Reads the adapter's MAC address from the EEPROM
1358c2ecf20Sopenharmony_ci *
1368c2ecf20Sopenharmony_ci * hw - Struct containing variables accessed by shared code
1378c2ecf20Sopenharmony_ci */
1388c2ecf20Sopenharmony_ciint atl1e_read_mac_addr(struct atl1e_hw *hw)
1398c2ecf20Sopenharmony_ci{
1408c2ecf20Sopenharmony_ci	int err = 0;
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci	err = atl1e_get_permanent_address(hw);
1438c2ecf20Sopenharmony_ci	if (err)
1448c2ecf20Sopenharmony_ci		return AT_ERR_EEPROM;
1458c2ecf20Sopenharmony_ci	memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr));
1468c2ecf20Sopenharmony_ci	return 0;
1478c2ecf20Sopenharmony_ci}
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci/*
1508c2ecf20Sopenharmony_ci * atl1e_hash_mc_addr
1518c2ecf20Sopenharmony_ci *  purpose
1528c2ecf20Sopenharmony_ci *      set hash value for a multicast address
1538c2ecf20Sopenharmony_ci */
1548c2ecf20Sopenharmony_ciu32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr)
1558c2ecf20Sopenharmony_ci{
1568c2ecf20Sopenharmony_ci	u32 crc32;
1578c2ecf20Sopenharmony_ci	u32 value = 0;
1588c2ecf20Sopenharmony_ci	int i;
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	crc32 = ether_crc_le(6, mc_addr);
1618c2ecf20Sopenharmony_ci	for (i = 0; i < 32; i++)
1628c2ecf20Sopenharmony_ci		value |= (((crc32 >> i) & 1) << (31 - i));
1638c2ecf20Sopenharmony_ci
1648c2ecf20Sopenharmony_ci	return value;
1658c2ecf20Sopenharmony_ci}
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ci/*
1688c2ecf20Sopenharmony_ci * Sets the bit in the multicast table corresponding to the hash value.
1698c2ecf20Sopenharmony_ci * hw - Struct containing variables accessed by shared code
1708c2ecf20Sopenharmony_ci * hash_value - Multicast address hash value
1718c2ecf20Sopenharmony_ci */
1728c2ecf20Sopenharmony_civoid atl1e_hash_set(struct atl1e_hw *hw, u32 hash_value)
1738c2ecf20Sopenharmony_ci{
1748c2ecf20Sopenharmony_ci	u32 hash_bit, hash_reg;
1758c2ecf20Sopenharmony_ci	u32 mta;
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	/*
1788c2ecf20Sopenharmony_ci	 * The HASH Table  is a register array of 2 32-bit registers.
1798c2ecf20Sopenharmony_ci	 * It is treated like an array of 64 bits.  We want to set
1808c2ecf20Sopenharmony_ci	 * bit BitArray[hash_value]. So we figure out what register
1818c2ecf20Sopenharmony_ci	 * the bit is in, read it, OR in the new bit, then write
1828c2ecf20Sopenharmony_ci	 * back the new value.  The register is determined by the
1838c2ecf20Sopenharmony_ci	 * upper 7 bits of the hash value and the bit within that
1848c2ecf20Sopenharmony_ci	 * register are determined by the lower 5 bits of the value.
1858c2ecf20Sopenharmony_ci	 */
1868c2ecf20Sopenharmony_ci	hash_reg = (hash_value >> 31) & 0x1;
1878c2ecf20Sopenharmony_ci	hash_bit = (hash_value >> 26) & 0x1F;
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	mta = AT_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg);
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	mta |= (1 << hash_bit);
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci	AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta);
1948c2ecf20Sopenharmony_ci}
1958c2ecf20Sopenharmony_ci/*
1968c2ecf20Sopenharmony_ci * Reads the value from a PHY register
1978c2ecf20Sopenharmony_ci * hw - Struct containing variables accessed by shared code
1988c2ecf20Sopenharmony_ci * reg_addr - address of the PHY register to read
1998c2ecf20Sopenharmony_ci */
2008c2ecf20Sopenharmony_ciint atl1e_read_phy_reg(struct atl1e_hw *hw, u16 reg_addr, u16 *phy_data)
2018c2ecf20Sopenharmony_ci{
2028c2ecf20Sopenharmony_ci	u32 val;
2038c2ecf20Sopenharmony_ci	int i;
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci	val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT |
2068c2ecf20Sopenharmony_ci		MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW |
2078c2ecf20Sopenharmony_ci		MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci	wmb();
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
2148c2ecf20Sopenharmony_ci		udelay(2);
2158c2ecf20Sopenharmony_ci		val = AT_READ_REG(hw, REG_MDIO_CTRL);
2168c2ecf20Sopenharmony_ci		if (!(val & (MDIO_START | MDIO_BUSY)))
2178c2ecf20Sopenharmony_ci			break;
2188c2ecf20Sopenharmony_ci		wmb();
2198c2ecf20Sopenharmony_ci	}
2208c2ecf20Sopenharmony_ci	if (!(val & (MDIO_START | MDIO_BUSY))) {
2218c2ecf20Sopenharmony_ci		*phy_data = (u16)val;
2228c2ecf20Sopenharmony_ci		return 0;
2238c2ecf20Sopenharmony_ci	}
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	return AT_ERR_PHY;
2268c2ecf20Sopenharmony_ci}
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_ci/*
2298c2ecf20Sopenharmony_ci * Writes a value to a PHY register
2308c2ecf20Sopenharmony_ci * hw - Struct containing variables accessed by shared code
2318c2ecf20Sopenharmony_ci * reg_addr - address of the PHY register to write
2328c2ecf20Sopenharmony_ci * data - data to write to the PHY
2338c2ecf20Sopenharmony_ci */
2348c2ecf20Sopenharmony_ciint atl1e_write_phy_reg(struct atl1e_hw *hw, u32 reg_addr, u16 phy_data)
2358c2ecf20Sopenharmony_ci{
2368c2ecf20Sopenharmony_ci	int i;
2378c2ecf20Sopenharmony_ci	u32 val;
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT |
2408c2ecf20Sopenharmony_ci	       (reg_addr&MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT |
2418c2ecf20Sopenharmony_ci	       MDIO_SUP_PREAMBLE |
2428c2ecf20Sopenharmony_ci	       MDIO_START |
2438c2ecf20Sopenharmony_ci	       MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT;
2448c2ecf20Sopenharmony_ci
2458c2ecf20Sopenharmony_ci	AT_WRITE_REG(hw, REG_MDIO_CTRL, val);
2468c2ecf20Sopenharmony_ci	wmb();
2478c2ecf20Sopenharmony_ci
2488c2ecf20Sopenharmony_ci	for (i = 0; i < MDIO_WAIT_TIMES; i++) {
2498c2ecf20Sopenharmony_ci		udelay(2);
2508c2ecf20Sopenharmony_ci		val = AT_READ_REG(hw, REG_MDIO_CTRL);
2518c2ecf20Sopenharmony_ci		if (!(val & (MDIO_START | MDIO_BUSY)))
2528c2ecf20Sopenharmony_ci			break;
2538c2ecf20Sopenharmony_ci		wmb();
2548c2ecf20Sopenharmony_ci	}
2558c2ecf20Sopenharmony_ci
2568c2ecf20Sopenharmony_ci	if (!(val & (MDIO_START | MDIO_BUSY)))
2578c2ecf20Sopenharmony_ci		return 0;
2588c2ecf20Sopenharmony_ci
2598c2ecf20Sopenharmony_ci	return AT_ERR_PHY;
2608c2ecf20Sopenharmony_ci}
2618c2ecf20Sopenharmony_ci
2628c2ecf20Sopenharmony_ci/*
2638c2ecf20Sopenharmony_ci * atl1e_init_pcie - init PCIE module
2648c2ecf20Sopenharmony_ci */
2658c2ecf20Sopenharmony_cistatic void atl1e_init_pcie(struct atl1e_hw *hw)
2668c2ecf20Sopenharmony_ci{
2678c2ecf20Sopenharmony_ci	u32 value;
2688c2ecf20Sopenharmony_ci	/* comment 2lines below to save more power when sususpend
2698c2ecf20Sopenharmony_ci	   value = LTSSM_TEST_MODE_DEF;
2708c2ecf20Sopenharmony_ci	   AT_WRITE_REG(hw, REG_LTSSM_TEST_MODE, value);
2718c2ecf20Sopenharmony_ci	 */
2728c2ecf20Sopenharmony_ci
2738c2ecf20Sopenharmony_ci	/* pcie flow control mode change */
2748c2ecf20Sopenharmony_ci	value = AT_READ_REG(hw, 0x1008);
2758c2ecf20Sopenharmony_ci	value |= 0x8000;
2768c2ecf20Sopenharmony_ci	AT_WRITE_REG(hw, 0x1008, value);
2778c2ecf20Sopenharmony_ci}
2788c2ecf20Sopenharmony_ci/*
2798c2ecf20Sopenharmony_ci * Configures PHY autoneg and flow control advertisement settings
2808c2ecf20Sopenharmony_ci *
2818c2ecf20Sopenharmony_ci * hw - Struct containing variables accessed by shared code
2828c2ecf20Sopenharmony_ci */
2838c2ecf20Sopenharmony_cistatic int atl1e_phy_setup_autoneg_adv(struct atl1e_hw *hw)
2848c2ecf20Sopenharmony_ci{
2858c2ecf20Sopenharmony_ci	s32 ret_val;
2868c2ecf20Sopenharmony_ci	u16 mii_autoneg_adv_reg;
2878c2ecf20Sopenharmony_ci	u16 mii_1000t_ctrl_reg;
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	if (0 != hw->mii_autoneg_adv_reg)
2908c2ecf20Sopenharmony_ci		return 0;
2918c2ecf20Sopenharmony_ci	/* Read the MII Auto-Neg Advertisement Register (Address 4/9). */
2928c2ecf20Sopenharmony_ci	mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK;
2938c2ecf20Sopenharmony_ci	mii_1000t_ctrl_reg  = MII_AT001_CR_1000T_DEFAULT_CAP_MASK;
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	/*
2968c2ecf20Sopenharmony_ci	 * Need to parse autoneg_advertised  and set up
2978c2ecf20Sopenharmony_ci	 * the appropriate PHY registers.  First we will parse for
2988c2ecf20Sopenharmony_ci	 * autoneg_advertised software override.  Since we can advertise
2998c2ecf20Sopenharmony_ci	 * a plethora of combinations, we need to check each bit
3008c2ecf20Sopenharmony_ci	 * individually.
3018c2ecf20Sopenharmony_ci	 */
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_ci	/*
3048c2ecf20Sopenharmony_ci	 * First we clear all the 10/100 mb speed bits in the Auto-Neg
3058c2ecf20Sopenharmony_ci	 * Advertisement Register (Address 4) and the 1000 mb speed bits in
3068c2ecf20Sopenharmony_ci	 * the  1000Base-T control Register (Address 9).
3078c2ecf20Sopenharmony_ci	 */
3088c2ecf20Sopenharmony_ci	mii_autoneg_adv_reg &= ~ADVERTISE_ALL;
3098c2ecf20Sopenharmony_ci	mii_1000t_ctrl_reg  &= ~MII_AT001_CR_1000T_SPEED_MASK;
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	/*
3128c2ecf20Sopenharmony_ci	 * Need to parse MediaType and setup the
3138c2ecf20Sopenharmony_ci	 * appropriate PHY registers.
3148c2ecf20Sopenharmony_ci	 */
3158c2ecf20Sopenharmony_ci	switch (hw->media_type) {
3168c2ecf20Sopenharmony_ci	case MEDIA_TYPE_AUTO_SENSOR:
3178c2ecf20Sopenharmony_ci		mii_autoneg_adv_reg |= ADVERTISE_ALL;
3188c2ecf20Sopenharmony_ci		hw->autoneg_advertised = ADVERTISE_ALL;
3198c2ecf20Sopenharmony_ci		if (hw->nic_type == athr_l1e) {
3208c2ecf20Sopenharmony_ci			mii_1000t_ctrl_reg |= ADVERTISE_1000FULL;
3218c2ecf20Sopenharmony_ci			hw->autoneg_advertised |= ADVERTISE_1000_FULL;
3228c2ecf20Sopenharmony_ci		}
3238c2ecf20Sopenharmony_ci		break;
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	case MEDIA_TYPE_100M_FULL:
3268c2ecf20Sopenharmony_ci		mii_autoneg_adv_reg   |= ADVERTISE_100FULL;
3278c2ecf20Sopenharmony_ci		hw->autoneg_advertised = ADVERTISE_100_FULL;
3288c2ecf20Sopenharmony_ci		break;
3298c2ecf20Sopenharmony_ci
3308c2ecf20Sopenharmony_ci	case MEDIA_TYPE_100M_HALF:
3318c2ecf20Sopenharmony_ci		mii_autoneg_adv_reg   |= ADVERTISE_100_HALF;
3328c2ecf20Sopenharmony_ci		hw->autoneg_advertised = ADVERTISE_100_HALF;
3338c2ecf20Sopenharmony_ci		break;
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci	case MEDIA_TYPE_10M_FULL:
3368c2ecf20Sopenharmony_ci		mii_autoneg_adv_reg   |= ADVERTISE_10_FULL;
3378c2ecf20Sopenharmony_ci		hw->autoneg_advertised = ADVERTISE_10_FULL;
3388c2ecf20Sopenharmony_ci		break;
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci	default:
3418c2ecf20Sopenharmony_ci		mii_autoneg_adv_reg   |= ADVERTISE_10_HALF;
3428c2ecf20Sopenharmony_ci		hw->autoneg_advertised = ADVERTISE_10_HALF;
3438c2ecf20Sopenharmony_ci		break;
3448c2ecf20Sopenharmony_ci	}
3458c2ecf20Sopenharmony_ci
3468c2ecf20Sopenharmony_ci	/* flow control fixed to enable all */
3478c2ecf20Sopenharmony_ci	mii_autoneg_adv_reg |= (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP);
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_ci	hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg;
3508c2ecf20Sopenharmony_ci	hw->mii_1000t_ctrl_reg  = mii_1000t_ctrl_reg;
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci	ret_val = atl1e_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg);
3538c2ecf20Sopenharmony_ci	if (ret_val)
3548c2ecf20Sopenharmony_ci		return ret_val;
3558c2ecf20Sopenharmony_ci
3568c2ecf20Sopenharmony_ci	if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) {
3578c2ecf20Sopenharmony_ci		ret_val = atl1e_write_phy_reg(hw, MII_CTRL1000,
3588c2ecf20Sopenharmony_ci					   mii_1000t_ctrl_reg);
3598c2ecf20Sopenharmony_ci		if (ret_val)
3608c2ecf20Sopenharmony_ci			return ret_val;
3618c2ecf20Sopenharmony_ci	}
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci	return 0;
3648c2ecf20Sopenharmony_ci}
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_ci/*
3688c2ecf20Sopenharmony_ci * Resets the PHY and make all config validate
3698c2ecf20Sopenharmony_ci *
3708c2ecf20Sopenharmony_ci * hw - Struct containing variables accessed by shared code
3718c2ecf20Sopenharmony_ci *
3728c2ecf20Sopenharmony_ci * Sets bit 15 and 12 of the MII control regiser (for F001 bug)
3738c2ecf20Sopenharmony_ci */
3748c2ecf20Sopenharmony_ciint atl1e_phy_commit(struct atl1e_hw *hw)
3758c2ecf20Sopenharmony_ci{
3768c2ecf20Sopenharmony_ci	struct atl1e_adapter *adapter = hw->adapter;
3778c2ecf20Sopenharmony_ci	int ret_val;
3788c2ecf20Sopenharmony_ci	u16 phy_data;
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci	phy_data = BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART;
3818c2ecf20Sopenharmony_ci
3828c2ecf20Sopenharmony_ci	ret_val = atl1e_write_phy_reg(hw, MII_BMCR, phy_data);
3838c2ecf20Sopenharmony_ci	if (ret_val) {
3848c2ecf20Sopenharmony_ci		u32 val;
3858c2ecf20Sopenharmony_ci		int i;
3868c2ecf20Sopenharmony_ci		/**************************************
3878c2ecf20Sopenharmony_ci		 * pcie serdes link may be down !
3888c2ecf20Sopenharmony_ci		 **************************************/
3898c2ecf20Sopenharmony_ci		for (i = 0; i < 25; i++) {
3908c2ecf20Sopenharmony_ci			msleep(1);
3918c2ecf20Sopenharmony_ci			val = AT_READ_REG(hw, REG_MDIO_CTRL);
3928c2ecf20Sopenharmony_ci			if (!(val & (MDIO_START | MDIO_BUSY)))
3938c2ecf20Sopenharmony_ci				break;
3948c2ecf20Sopenharmony_ci		}
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci		if (0 != (val & (MDIO_START | MDIO_BUSY))) {
3978c2ecf20Sopenharmony_ci			netdev_err(adapter->netdev,
3988c2ecf20Sopenharmony_ci				   "pcie linkdown at least for 25ms\n");
3998c2ecf20Sopenharmony_ci			return ret_val;
4008c2ecf20Sopenharmony_ci		}
4018c2ecf20Sopenharmony_ci
4028c2ecf20Sopenharmony_ci		netdev_err(adapter->netdev, "pcie linkup after %d ms\n", i);
4038c2ecf20Sopenharmony_ci	}
4048c2ecf20Sopenharmony_ci	return 0;
4058c2ecf20Sopenharmony_ci}
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ciint atl1e_phy_init(struct atl1e_hw *hw)
4088c2ecf20Sopenharmony_ci{
4098c2ecf20Sopenharmony_ci	struct atl1e_adapter *adapter = hw->adapter;
4108c2ecf20Sopenharmony_ci	s32 ret_val;
4118c2ecf20Sopenharmony_ci	u16 phy_val;
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	if (hw->phy_configured) {
4148c2ecf20Sopenharmony_ci		if (hw->re_autoneg) {
4158c2ecf20Sopenharmony_ci			hw->re_autoneg = false;
4168c2ecf20Sopenharmony_ci			return atl1e_restart_autoneg(hw);
4178c2ecf20Sopenharmony_ci		}
4188c2ecf20Sopenharmony_ci		return 0;
4198c2ecf20Sopenharmony_ci	}
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	/* RESET GPHY Core */
4228c2ecf20Sopenharmony_ci	AT_WRITE_REGW(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT);
4238c2ecf20Sopenharmony_ci	msleep(2);
4248c2ecf20Sopenharmony_ci	AT_WRITE_REGW(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT |
4258c2ecf20Sopenharmony_ci		      GPHY_CTRL_EXT_RESET);
4268c2ecf20Sopenharmony_ci	msleep(2);
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	/* patches */
4298c2ecf20Sopenharmony_ci	/* p1. eable hibernation mode */
4308c2ecf20Sopenharmony_ci	ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0xB);
4318c2ecf20Sopenharmony_ci	if (ret_val)
4328c2ecf20Sopenharmony_ci		return ret_val;
4338c2ecf20Sopenharmony_ci	ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0xBC00);
4348c2ecf20Sopenharmony_ci	if (ret_val)
4358c2ecf20Sopenharmony_ci		return ret_val;
4368c2ecf20Sopenharmony_ci	/* p2. set Class A/B for all modes */
4378c2ecf20Sopenharmony_ci	ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0);
4388c2ecf20Sopenharmony_ci	if (ret_val)
4398c2ecf20Sopenharmony_ci		return ret_val;
4408c2ecf20Sopenharmony_ci	phy_val = 0x02ef;
4418c2ecf20Sopenharmony_ci	/* remove Class AB */
4428c2ecf20Sopenharmony_ci	/* phy_val = hw->emi_ca ? 0x02ef : 0x02df; */
4438c2ecf20Sopenharmony_ci	ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, phy_val);
4448c2ecf20Sopenharmony_ci	if (ret_val)
4458c2ecf20Sopenharmony_ci		return ret_val;
4468c2ecf20Sopenharmony_ci	/* p3. 10B ??? */
4478c2ecf20Sopenharmony_ci	ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x12);
4488c2ecf20Sopenharmony_ci	if (ret_val)
4498c2ecf20Sopenharmony_ci		return ret_val;
4508c2ecf20Sopenharmony_ci	ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x4C04);
4518c2ecf20Sopenharmony_ci	if (ret_val)
4528c2ecf20Sopenharmony_ci		return ret_val;
4538c2ecf20Sopenharmony_ci	/* p4. 1000T power */
4548c2ecf20Sopenharmony_ci	ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x4);
4558c2ecf20Sopenharmony_ci	if (ret_val)
4568c2ecf20Sopenharmony_ci		return ret_val;
4578c2ecf20Sopenharmony_ci	ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x8BBB);
4588c2ecf20Sopenharmony_ci	if (ret_val)
4598c2ecf20Sopenharmony_ci		return ret_val;
4608c2ecf20Sopenharmony_ci
4618c2ecf20Sopenharmony_ci	ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x5);
4628c2ecf20Sopenharmony_ci	if (ret_val)
4638c2ecf20Sopenharmony_ci		return ret_val;
4648c2ecf20Sopenharmony_ci	ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x2C46);
4658c2ecf20Sopenharmony_ci	if (ret_val)
4668c2ecf20Sopenharmony_ci		return ret_val;
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	msleep(1);
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci	/*Enable PHY LinkChange Interrupt */
4718c2ecf20Sopenharmony_ci	ret_val = atl1e_write_phy_reg(hw, MII_INT_CTRL, 0xC00);
4728c2ecf20Sopenharmony_ci	if (ret_val) {
4738c2ecf20Sopenharmony_ci		netdev_err(adapter->netdev,
4748c2ecf20Sopenharmony_ci			   "Error enable PHY linkChange Interrupt\n");
4758c2ecf20Sopenharmony_ci		return ret_val;
4768c2ecf20Sopenharmony_ci	}
4778c2ecf20Sopenharmony_ci	/* setup AutoNeg parameters */
4788c2ecf20Sopenharmony_ci	ret_val = atl1e_phy_setup_autoneg_adv(hw);
4798c2ecf20Sopenharmony_ci	if (ret_val) {
4808c2ecf20Sopenharmony_ci		netdev_err(adapter->netdev,
4818c2ecf20Sopenharmony_ci			   "Error Setting up Auto-Negotiation\n");
4828c2ecf20Sopenharmony_ci		return ret_val;
4838c2ecf20Sopenharmony_ci	}
4848c2ecf20Sopenharmony_ci	/* SW.Reset & En-Auto-Neg to restart Auto-Neg*/
4858c2ecf20Sopenharmony_ci	netdev_dbg(adapter->netdev, "Restarting Auto-Negotiation\n");
4868c2ecf20Sopenharmony_ci	ret_val = atl1e_phy_commit(hw);
4878c2ecf20Sopenharmony_ci	if (ret_val) {
4888c2ecf20Sopenharmony_ci		netdev_err(adapter->netdev, "Error resetting the phy\n");
4898c2ecf20Sopenharmony_ci		return ret_val;
4908c2ecf20Sopenharmony_ci	}
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci	hw->phy_configured = true;
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ci	return 0;
4958c2ecf20Sopenharmony_ci}
4968c2ecf20Sopenharmony_ci
4978c2ecf20Sopenharmony_ci/*
4988c2ecf20Sopenharmony_ci * Reset the transmit and receive units; mask and clear all interrupts.
4998c2ecf20Sopenharmony_ci * hw - Struct containing variables accessed by shared code
5008c2ecf20Sopenharmony_ci * return : 0  or  idle status (if error)
5018c2ecf20Sopenharmony_ci */
5028c2ecf20Sopenharmony_ciint atl1e_reset_hw(struct atl1e_hw *hw)
5038c2ecf20Sopenharmony_ci{
5048c2ecf20Sopenharmony_ci	struct atl1e_adapter *adapter = hw->adapter;
5058c2ecf20Sopenharmony_ci	struct pci_dev *pdev = adapter->pdev;
5068c2ecf20Sopenharmony_ci
5078c2ecf20Sopenharmony_ci	u32 idle_status_data = 0;
5088c2ecf20Sopenharmony_ci	u16 pci_cfg_cmd_word = 0;
5098c2ecf20Sopenharmony_ci	int timeout = 0;
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	/* Workaround for PCI problem when BIOS sets MMRBC incorrectly. */
5128c2ecf20Sopenharmony_ci	pci_read_config_word(pdev, PCI_REG_COMMAND, &pci_cfg_cmd_word);
5138c2ecf20Sopenharmony_ci	if ((pci_cfg_cmd_word & (CMD_IO_SPACE |
5148c2ecf20Sopenharmony_ci				CMD_MEMORY_SPACE | CMD_BUS_MASTER))
5158c2ecf20Sopenharmony_ci			!= (CMD_IO_SPACE | CMD_MEMORY_SPACE | CMD_BUS_MASTER)) {
5168c2ecf20Sopenharmony_ci		pci_cfg_cmd_word |= (CMD_IO_SPACE |
5178c2ecf20Sopenharmony_ci				     CMD_MEMORY_SPACE | CMD_BUS_MASTER);
5188c2ecf20Sopenharmony_ci		pci_write_config_word(pdev, PCI_REG_COMMAND, pci_cfg_cmd_word);
5198c2ecf20Sopenharmony_ci	}
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci	/*
5228c2ecf20Sopenharmony_ci	 * Issue Soft Reset to the MAC.  This will reset the chip's
5238c2ecf20Sopenharmony_ci	 * transmit, receive, DMA.  It will not effect
5248c2ecf20Sopenharmony_ci	 * the current PCI configuration.  The global reset bit is self-
5258c2ecf20Sopenharmony_ci	 * clearing, and should clear within a microsecond.
5268c2ecf20Sopenharmony_ci	 */
5278c2ecf20Sopenharmony_ci	AT_WRITE_REG(hw, REG_MASTER_CTRL,
5288c2ecf20Sopenharmony_ci			MASTER_CTRL_LED_MODE | MASTER_CTRL_SOFT_RST);
5298c2ecf20Sopenharmony_ci	wmb();
5308c2ecf20Sopenharmony_ci	msleep(1);
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci	/* Wait at least 10ms for All module to be Idle */
5338c2ecf20Sopenharmony_ci	for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) {
5348c2ecf20Sopenharmony_ci		idle_status_data = AT_READ_REG(hw, REG_IDLE_STATUS);
5358c2ecf20Sopenharmony_ci		if (idle_status_data == 0)
5368c2ecf20Sopenharmony_ci			break;
5378c2ecf20Sopenharmony_ci		msleep(1);
5388c2ecf20Sopenharmony_ci		cpu_relax();
5398c2ecf20Sopenharmony_ci	}
5408c2ecf20Sopenharmony_ci
5418c2ecf20Sopenharmony_ci	if (timeout >= AT_HW_MAX_IDLE_DELAY) {
5428c2ecf20Sopenharmony_ci		netdev_err(adapter->netdev,
5438c2ecf20Sopenharmony_ci			   "MAC state machine can't be idle since disabled for 10ms second\n");
5448c2ecf20Sopenharmony_ci		return AT_ERR_TIMEOUT;
5458c2ecf20Sopenharmony_ci	}
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci	return 0;
5488c2ecf20Sopenharmony_ci}
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_ci
5518c2ecf20Sopenharmony_ci/*
5528c2ecf20Sopenharmony_ci * Performs basic configuration of the adapter.
5538c2ecf20Sopenharmony_ci *
5548c2ecf20Sopenharmony_ci * hw - Struct containing variables accessed by shared code
5558c2ecf20Sopenharmony_ci * Assumes that the controller has previously been reset and is in a
5568c2ecf20Sopenharmony_ci * post-reset uninitialized state. Initializes multicast table,
5578c2ecf20Sopenharmony_ci * and  Calls routines to setup link
5588c2ecf20Sopenharmony_ci * Leaves the transmit and receive units disabled and uninitialized.
5598c2ecf20Sopenharmony_ci */
5608c2ecf20Sopenharmony_ciint atl1e_init_hw(struct atl1e_hw *hw)
5618c2ecf20Sopenharmony_ci{
5628c2ecf20Sopenharmony_ci	s32 ret_val = 0;
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci	atl1e_init_pcie(hw);
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci	/* Zero out the Multicast HASH table */
5678c2ecf20Sopenharmony_ci	/* clear the old settings from the multicast hash table */
5688c2ecf20Sopenharmony_ci	AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0);
5698c2ecf20Sopenharmony_ci	AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0);
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_ci	ret_val = atl1e_phy_init(hw);
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci	return ret_val;
5748c2ecf20Sopenharmony_ci}
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci/*
5778c2ecf20Sopenharmony_ci * Detects the current speed and duplex settings of the hardware.
5788c2ecf20Sopenharmony_ci *
5798c2ecf20Sopenharmony_ci * hw - Struct containing variables accessed by shared code
5808c2ecf20Sopenharmony_ci * speed - Speed of the connection
5818c2ecf20Sopenharmony_ci * duplex - Duplex setting of the connection
5828c2ecf20Sopenharmony_ci */
5838c2ecf20Sopenharmony_ciint atl1e_get_speed_and_duplex(struct atl1e_hw *hw, u16 *speed, u16 *duplex)
5848c2ecf20Sopenharmony_ci{
5858c2ecf20Sopenharmony_ci	int err;
5868c2ecf20Sopenharmony_ci	u16 phy_data;
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci	/* Read   PHY Specific Status Register (17) */
5898c2ecf20Sopenharmony_ci	err = atl1e_read_phy_reg(hw, MII_AT001_PSSR, &phy_data);
5908c2ecf20Sopenharmony_ci	if (err)
5918c2ecf20Sopenharmony_ci		return err;
5928c2ecf20Sopenharmony_ci
5938c2ecf20Sopenharmony_ci	if (!(phy_data & MII_AT001_PSSR_SPD_DPLX_RESOLVED))
5948c2ecf20Sopenharmony_ci		return AT_ERR_PHY_RES;
5958c2ecf20Sopenharmony_ci
5968c2ecf20Sopenharmony_ci	switch (phy_data & MII_AT001_PSSR_SPEED) {
5978c2ecf20Sopenharmony_ci	case MII_AT001_PSSR_1000MBS:
5988c2ecf20Sopenharmony_ci		*speed = SPEED_1000;
5998c2ecf20Sopenharmony_ci		break;
6008c2ecf20Sopenharmony_ci	case MII_AT001_PSSR_100MBS:
6018c2ecf20Sopenharmony_ci		*speed = SPEED_100;
6028c2ecf20Sopenharmony_ci		break;
6038c2ecf20Sopenharmony_ci	case MII_AT001_PSSR_10MBS:
6048c2ecf20Sopenharmony_ci		*speed = SPEED_10;
6058c2ecf20Sopenharmony_ci		break;
6068c2ecf20Sopenharmony_ci	default:
6078c2ecf20Sopenharmony_ci		return AT_ERR_PHY_SPEED;
6088c2ecf20Sopenharmony_ci	}
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci	if (phy_data & MII_AT001_PSSR_DPLX)
6118c2ecf20Sopenharmony_ci		*duplex = FULL_DUPLEX;
6128c2ecf20Sopenharmony_ci	else
6138c2ecf20Sopenharmony_ci		*duplex = HALF_DUPLEX;
6148c2ecf20Sopenharmony_ci
6158c2ecf20Sopenharmony_ci	return 0;
6168c2ecf20Sopenharmony_ci}
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ciint atl1e_restart_autoneg(struct atl1e_hw *hw)
6198c2ecf20Sopenharmony_ci{
6208c2ecf20Sopenharmony_ci	int err = 0;
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci	err = atl1e_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg);
6238c2ecf20Sopenharmony_ci	if (err)
6248c2ecf20Sopenharmony_ci		return err;
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_ci	if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) {
6278c2ecf20Sopenharmony_ci		err = atl1e_write_phy_reg(hw, MII_CTRL1000,
6288c2ecf20Sopenharmony_ci				       hw->mii_1000t_ctrl_reg);
6298c2ecf20Sopenharmony_ci		if (err)
6308c2ecf20Sopenharmony_ci			return err;
6318c2ecf20Sopenharmony_ci	}
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	err = atl1e_write_phy_reg(hw, MII_BMCR,
6348c2ecf20Sopenharmony_ci			BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART);
6358c2ecf20Sopenharmony_ci	return err;
6368c2ecf20Sopenharmony_ci}
6378c2ecf20Sopenharmony_ci
638