18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2013 Johannes Berg <johannes@sipsolutions.net> 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * This file is free software: you may copy, redistribute and/or modify it 58c2ecf20Sopenharmony_ci * under the terms of the GNU General Public License as published by the 68c2ecf20Sopenharmony_ci * Free Software Foundation, either version 2 of the License, or (at your 78c2ecf20Sopenharmony_ci * option) any later version. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * This file is distributed in the hope that it will be useful, but 108c2ecf20Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of 118c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 128c2ecf20Sopenharmony_ci * General Public License for more details. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * You should have received a copy of the GNU General Public License 158c2ecf20Sopenharmony_ci * along with this program. If not, see <http://www.gnu.org/licenses/>. 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci * This file incorporates work covered by the following copyright and 188c2ecf20Sopenharmony_ci * permission notice: 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * Copyright (c) 2012 Qualcomm Atheros, Inc. 218c2ecf20Sopenharmony_ci * 228c2ecf20Sopenharmony_ci * Permission to use, copy, modify, and/or distribute this software for any 238c2ecf20Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above 248c2ecf20Sopenharmony_ci * copyright notice and this permission notice appear in all copies. 258c2ecf20Sopenharmony_ci * 268c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 278c2ecf20Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 288c2ecf20Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 298c2ecf20Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 308c2ecf20Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 318c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 328c2ecf20Sopenharmony_ci * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 338c2ecf20Sopenharmony_ci */ 348c2ecf20Sopenharmony_ci#include <linux/etherdevice.h> 358c2ecf20Sopenharmony_ci#include <linux/delay.h> 368c2ecf20Sopenharmony_ci#include <linux/pci.h> 378c2ecf20Sopenharmony_ci#include <linux/mdio.h> 388c2ecf20Sopenharmony_ci#include "reg.h" 398c2ecf20Sopenharmony_ci#include "hw.h" 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_cistatic inline bool alx_is_rev_a(u8 rev) 428c2ecf20Sopenharmony_ci{ 438c2ecf20Sopenharmony_ci return rev == ALX_REV_A0 || rev == ALX_REV_A1; 448c2ecf20Sopenharmony_ci} 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_cistatic int alx_wait_mdio_idle(struct alx_hw *hw) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci u32 val; 498c2ecf20Sopenharmony_ci int i; 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci for (i = 0; i < ALX_MDIO_MAX_AC_TO; i++) { 528c2ecf20Sopenharmony_ci val = alx_read_mem32(hw, ALX_MDIO); 538c2ecf20Sopenharmony_ci if (!(val & ALX_MDIO_BUSY)) 548c2ecf20Sopenharmony_ci return 0; 558c2ecf20Sopenharmony_ci udelay(10); 568c2ecf20Sopenharmony_ci } 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci return -ETIMEDOUT; 598c2ecf20Sopenharmony_ci} 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic int alx_read_phy_core(struct alx_hw *hw, bool ext, u8 dev, 628c2ecf20Sopenharmony_ci u16 reg, u16 *phy_data) 638c2ecf20Sopenharmony_ci{ 648c2ecf20Sopenharmony_ci u32 val, clk_sel; 658c2ecf20Sopenharmony_ci int err; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci *phy_data = 0; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci /* use slow clock when it's in hibernation status */ 708c2ecf20Sopenharmony_ci clk_sel = hw->link_speed != SPEED_UNKNOWN ? 718c2ecf20Sopenharmony_ci ALX_MDIO_CLK_SEL_25MD4 : 728c2ecf20Sopenharmony_ci ALX_MDIO_CLK_SEL_25MD128; 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci if (ext) { 758c2ecf20Sopenharmony_ci val = dev << ALX_MDIO_EXTN_DEVAD_SHIFT | 768c2ecf20Sopenharmony_ci reg << ALX_MDIO_EXTN_REG_SHIFT; 778c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_MDIO_EXTN, val); 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci val = ALX_MDIO_SPRES_PRMBL | ALX_MDIO_START | 808c2ecf20Sopenharmony_ci ALX_MDIO_MODE_EXT | ALX_MDIO_OP_READ | 818c2ecf20Sopenharmony_ci clk_sel << ALX_MDIO_CLK_SEL_SHIFT; 828c2ecf20Sopenharmony_ci } else { 838c2ecf20Sopenharmony_ci val = ALX_MDIO_SPRES_PRMBL | 848c2ecf20Sopenharmony_ci clk_sel << ALX_MDIO_CLK_SEL_SHIFT | 858c2ecf20Sopenharmony_ci reg << ALX_MDIO_REG_SHIFT | 868c2ecf20Sopenharmony_ci ALX_MDIO_START | ALX_MDIO_OP_READ; 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_MDIO, val); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci err = alx_wait_mdio_idle(hw); 918c2ecf20Sopenharmony_ci if (err) 928c2ecf20Sopenharmony_ci return err; 938c2ecf20Sopenharmony_ci val = alx_read_mem32(hw, ALX_MDIO); 948c2ecf20Sopenharmony_ci *phy_data = ALX_GET_FIELD(val, ALX_MDIO_DATA); 958c2ecf20Sopenharmony_ci return 0; 968c2ecf20Sopenharmony_ci} 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_cistatic int alx_write_phy_core(struct alx_hw *hw, bool ext, u8 dev, 998c2ecf20Sopenharmony_ci u16 reg, u16 phy_data) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci u32 val, clk_sel; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci /* use slow clock when it's in hibernation status */ 1048c2ecf20Sopenharmony_ci clk_sel = hw->link_speed != SPEED_UNKNOWN ? 1058c2ecf20Sopenharmony_ci ALX_MDIO_CLK_SEL_25MD4 : 1068c2ecf20Sopenharmony_ci ALX_MDIO_CLK_SEL_25MD128; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci if (ext) { 1098c2ecf20Sopenharmony_ci val = dev << ALX_MDIO_EXTN_DEVAD_SHIFT | 1108c2ecf20Sopenharmony_ci reg << ALX_MDIO_EXTN_REG_SHIFT; 1118c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_MDIO_EXTN, val); 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci val = ALX_MDIO_SPRES_PRMBL | 1148c2ecf20Sopenharmony_ci clk_sel << ALX_MDIO_CLK_SEL_SHIFT | 1158c2ecf20Sopenharmony_ci phy_data << ALX_MDIO_DATA_SHIFT | 1168c2ecf20Sopenharmony_ci ALX_MDIO_START | ALX_MDIO_MODE_EXT; 1178c2ecf20Sopenharmony_ci } else { 1188c2ecf20Sopenharmony_ci val = ALX_MDIO_SPRES_PRMBL | 1198c2ecf20Sopenharmony_ci clk_sel << ALX_MDIO_CLK_SEL_SHIFT | 1208c2ecf20Sopenharmony_ci reg << ALX_MDIO_REG_SHIFT | 1218c2ecf20Sopenharmony_ci phy_data << ALX_MDIO_DATA_SHIFT | 1228c2ecf20Sopenharmony_ci ALX_MDIO_START; 1238c2ecf20Sopenharmony_ci } 1248c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_MDIO, val); 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci return alx_wait_mdio_idle(hw); 1278c2ecf20Sopenharmony_ci} 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_cistatic int __alx_read_phy_reg(struct alx_hw *hw, u16 reg, u16 *phy_data) 1308c2ecf20Sopenharmony_ci{ 1318c2ecf20Sopenharmony_ci return alx_read_phy_core(hw, false, 0, reg, phy_data); 1328c2ecf20Sopenharmony_ci} 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_cistatic int __alx_write_phy_reg(struct alx_hw *hw, u16 reg, u16 phy_data) 1358c2ecf20Sopenharmony_ci{ 1368c2ecf20Sopenharmony_ci return alx_write_phy_core(hw, false, 0, reg, phy_data); 1378c2ecf20Sopenharmony_ci} 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_cistatic int __alx_read_phy_ext(struct alx_hw *hw, u8 dev, u16 reg, u16 *pdata) 1408c2ecf20Sopenharmony_ci{ 1418c2ecf20Sopenharmony_ci return alx_read_phy_core(hw, true, dev, reg, pdata); 1428c2ecf20Sopenharmony_ci} 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistatic int __alx_write_phy_ext(struct alx_hw *hw, u8 dev, u16 reg, u16 data) 1458c2ecf20Sopenharmony_ci{ 1468c2ecf20Sopenharmony_ci return alx_write_phy_core(hw, true, dev, reg, data); 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_cistatic int __alx_read_phy_dbg(struct alx_hw *hw, u16 reg, u16 *pdata) 1508c2ecf20Sopenharmony_ci{ 1518c2ecf20Sopenharmony_ci int err; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci err = __alx_write_phy_reg(hw, ALX_MII_DBG_ADDR, reg); 1548c2ecf20Sopenharmony_ci if (err) 1558c2ecf20Sopenharmony_ci return err; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci return __alx_read_phy_reg(hw, ALX_MII_DBG_DATA, pdata); 1588c2ecf20Sopenharmony_ci} 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_cistatic int __alx_write_phy_dbg(struct alx_hw *hw, u16 reg, u16 data) 1618c2ecf20Sopenharmony_ci{ 1628c2ecf20Sopenharmony_ci int err; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci err = __alx_write_phy_reg(hw, ALX_MII_DBG_ADDR, reg); 1658c2ecf20Sopenharmony_ci if (err) 1668c2ecf20Sopenharmony_ci return err; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci return __alx_write_phy_reg(hw, ALX_MII_DBG_DATA, data); 1698c2ecf20Sopenharmony_ci} 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ciint alx_read_phy_reg(struct alx_hw *hw, u16 reg, u16 *phy_data) 1728c2ecf20Sopenharmony_ci{ 1738c2ecf20Sopenharmony_ci int err; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci spin_lock(&hw->mdio_lock); 1768c2ecf20Sopenharmony_ci err = __alx_read_phy_reg(hw, reg, phy_data); 1778c2ecf20Sopenharmony_ci spin_unlock(&hw->mdio_lock); 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci return err; 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ciint alx_write_phy_reg(struct alx_hw *hw, u16 reg, u16 phy_data) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci int err; 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_ci spin_lock(&hw->mdio_lock); 1878c2ecf20Sopenharmony_ci err = __alx_write_phy_reg(hw, reg, phy_data); 1888c2ecf20Sopenharmony_ci spin_unlock(&hw->mdio_lock); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci return err; 1918c2ecf20Sopenharmony_ci} 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ciint alx_read_phy_ext(struct alx_hw *hw, u8 dev, u16 reg, u16 *pdata) 1948c2ecf20Sopenharmony_ci{ 1958c2ecf20Sopenharmony_ci int err; 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci spin_lock(&hw->mdio_lock); 1988c2ecf20Sopenharmony_ci err = __alx_read_phy_ext(hw, dev, reg, pdata); 1998c2ecf20Sopenharmony_ci spin_unlock(&hw->mdio_lock); 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_ci return err; 2028c2ecf20Sopenharmony_ci} 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ciint alx_write_phy_ext(struct alx_hw *hw, u8 dev, u16 reg, u16 data) 2058c2ecf20Sopenharmony_ci{ 2068c2ecf20Sopenharmony_ci int err; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci spin_lock(&hw->mdio_lock); 2098c2ecf20Sopenharmony_ci err = __alx_write_phy_ext(hw, dev, reg, data); 2108c2ecf20Sopenharmony_ci spin_unlock(&hw->mdio_lock); 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci return err; 2138c2ecf20Sopenharmony_ci} 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_cistatic int alx_read_phy_dbg(struct alx_hw *hw, u16 reg, u16 *pdata) 2168c2ecf20Sopenharmony_ci{ 2178c2ecf20Sopenharmony_ci int err; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci spin_lock(&hw->mdio_lock); 2208c2ecf20Sopenharmony_ci err = __alx_read_phy_dbg(hw, reg, pdata); 2218c2ecf20Sopenharmony_ci spin_unlock(&hw->mdio_lock); 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci return err; 2248c2ecf20Sopenharmony_ci} 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_cistatic int alx_write_phy_dbg(struct alx_hw *hw, u16 reg, u16 data) 2278c2ecf20Sopenharmony_ci{ 2288c2ecf20Sopenharmony_ci int err; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci spin_lock(&hw->mdio_lock); 2318c2ecf20Sopenharmony_ci err = __alx_write_phy_dbg(hw, reg, data); 2328c2ecf20Sopenharmony_ci spin_unlock(&hw->mdio_lock); 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci return err; 2358c2ecf20Sopenharmony_ci} 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_cistatic u16 alx_get_phy_config(struct alx_hw *hw) 2388c2ecf20Sopenharmony_ci{ 2398c2ecf20Sopenharmony_ci u32 val; 2408c2ecf20Sopenharmony_ci u16 phy_val; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci val = alx_read_mem32(hw, ALX_PHY_CTRL); 2438c2ecf20Sopenharmony_ci /* phy in reset */ 2448c2ecf20Sopenharmony_ci if ((val & ALX_PHY_CTRL_DSPRST_OUT) == 0) 2458c2ecf20Sopenharmony_ci return ALX_DRV_PHY_UNKNOWN; 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci val = alx_read_mem32(hw, ALX_DRV); 2488c2ecf20Sopenharmony_ci val = ALX_GET_FIELD(val, ALX_DRV_PHY); 2498c2ecf20Sopenharmony_ci if (ALX_DRV_PHY_UNKNOWN == val) 2508c2ecf20Sopenharmony_ci return ALX_DRV_PHY_UNKNOWN; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci alx_read_phy_reg(hw, ALX_MII_DBG_ADDR, &phy_val); 2538c2ecf20Sopenharmony_ci if (ALX_PHY_INITED == phy_val) 2548c2ecf20Sopenharmony_ci return val; 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci return ALX_DRV_PHY_UNKNOWN; 2578c2ecf20Sopenharmony_ci} 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_cistatic bool alx_wait_reg(struct alx_hw *hw, u32 reg, u32 wait, u32 *val) 2608c2ecf20Sopenharmony_ci{ 2618c2ecf20Sopenharmony_ci u32 read; 2628c2ecf20Sopenharmony_ci int i; 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci for (i = 0; i < ALX_SLD_MAX_TO; i++) { 2658c2ecf20Sopenharmony_ci read = alx_read_mem32(hw, reg); 2668c2ecf20Sopenharmony_ci if ((read & wait) == 0) { 2678c2ecf20Sopenharmony_ci if (val) 2688c2ecf20Sopenharmony_ci *val = read; 2698c2ecf20Sopenharmony_ci return true; 2708c2ecf20Sopenharmony_ci } 2718c2ecf20Sopenharmony_ci mdelay(1); 2728c2ecf20Sopenharmony_ci } 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci return false; 2758c2ecf20Sopenharmony_ci} 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_cistatic bool alx_read_macaddr(struct alx_hw *hw, u8 *addr) 2788c2ecf20Sopenharmony_ci{ 2798c2ecf20Sopenharmony_ci u32 mac0, mac1; 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci mac0 = alx_read_mem32(hw, ALX_STAD0); 2828c2ecf20Sopenharmony_ci mac1 = alx_read_mem32(hw, ALX_STAD1); 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci /* addr should be big-endian */ 2858c2ecf20Sopenharmony_ci put_unaligned(cpu_to_be32(mac0), (__be32 *)(addr + 2)); 2868c2ecf20Sopenharmony_ci put_unaligned(cpu_to_be16(mac1), (__be16 *)addr); 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci return is_valid_ether_addr(addr); 2898c2ecf20Sopenharmony_ci} 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ciint alx_get_perm_macaddr(struct alx_hw *hw, u8 *addr) 2928c2ecf20Sopenharmony_ci{ 2938c2ecf20Sopenharmony_ci u32 val; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci /* try to get it from register first */ 2968c2ecf20Sopenharmony_ci if (alx_read_macaddr(hw, addr)) 2978c2ecf20Sopenharmony_ci return 0; 2988c2ecf20Sopenharmony_ci 2998c2ecf20Sopenharmony_ci /* try to load from efuse */ 3008c2ecf20Sopenharmony_ci if (!alx_wait_reg(hw, ALX_SLD, ALX_SLD_STAT | ALX_SLD_START, &val)) 3018c2ecf20Sopenharmony_ci return -EIO; 3028c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_SLD, val | ALX_SLD_START); 3038c2ecf20Sopenharmony_ci if (!alx_wait_reg(hw, ALX_SLD, ALX_SLD_START, NULL)) 3048c2ecf20Sopenharmony_ci return -EIO; 3058c2ecf20Sopenharmony_ci if (alx_read_macaddr(hw, addr)) 3068c2ecf20Sopenharmony_ci return 0; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci /* try to load from flash/eeprom (if present) */ 3098c2ecf20Sopenharmony_ci val = alx_read_mem32(hw, ALX_EFLD); 3108c2ecf20Sopenharmony_ci if (val & (ALX_EFLD_F_EXIST | ALX_EFLD_E_EXIST)) { 3118c2ecf20Sopenharmony_ci if (!alx_wait_reg(hw, ALX_EFLD, 3128c2ecf20Sopenharmony_ci ALX_EFLD_STAT | ALX_EFLD_START, &val)) 3138c2ecf20Sopenharmony_ci return -EIO; 3148c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_EFLD, val | ALX_EFLD_START); 3158c2ecf20Sopenharmony_ci if (!alx_wait_reg(hw, ALX_EFLD, ALX_EFLD_START, NULL)) 3168c2ecf20Sopenharmony_ci return -EIO; 3178c2ecf20Sopenharmony_ci if (alx_read_macaddr(hw, addr)) 3188c2ecf20Sopenharmony_ci return 0; 3198c2ecf20Sopenharmony_ci } 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci return -EIO; 3228c2ecf20Sopenharmony_ci} 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_civoid alx_set_macaddr(struct alx_hw *hw, const u8 *addr) 3258c2ecf20Sopenharmony_ci{ 3268c2ecf20Sopenharmony_ci u32 val; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci /* for example: 00-0B-6A-F6-00-DC * STAD0=6AF600DC, STAD1=000B */ 3298c2ecf20Sopenharmony_ci val = be32_to_cpu(get_unaligned((__be32 *)(addr + 2))); 3308c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_STAD0, val); 3318c2ecf20Sopenharmony_ci val = be16_to_cpu(get_unaligned((__be16 *)addr)); 3328c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_STAD1, val); 3338c2ecf20Sopenharmony_ci} 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_cistatic void alx_reset_osc(struct alx_hw *hw, u8 rev) 3368c2ecf20Sopenharmony_ci{ 3378c2ecf20Sopenharmony_ci u32 val, val2; 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci /* clear Internal OSC settings, switching OSC by hw itself */ 3408c2ecf20Sopenharmony_ci val = alx_read_mem32(hw, ALX_MISC3); 3418c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_MISC3, 3428c2ecf20Sopenharmony_ci (val & ~ALX_MISC3_25M_BY_SW) | 3438c2ecf20Sopenharmony_ci ALX_MISC3_25M_NOTO_INTNL); 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci /* 25M clk from chipset may be unstable 1s after de-assert of 3468c2ecf20Sopenharmony_ci * PERST, driver need re-calibrate before enter Sleep for WoL 3478c2ecf20Sopenharmony_ci */ 3488c2ecf20Sopenharmony_ci val = alx_read_mem32(hw, ALX_MISC); 3498c2ecf20Sopenharmony_ci if (rev >= ALX_REV_B0) { 3508c2ecf20Sopenharmony_ci /* restore over current protection def-val, 3518c2ecf20Sopenharmony_ci * this val could be reset by MAC-RST 3528c2ecf20Sopenharmony_ci */ 3538c2ecf20Sopenharmony_ci ALX_SET_FIELD(val, ALX_MISC_PSW_OCP, ALX_MISC_PSW_OCP_DEF); 3548c2ecf20Sopenharmony_ci /* a 0->1 change will update the internal val of osc */ 3558c2ecf20Sopenharmony_ci val &= ~ALX_MISC_INTNLOSC_OPEN; 3568c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_MISC, val); 3578c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_MISC, val | ALX_MISC_INTNLOSC_OPEN); 3588c2ecf20Sopenharmony_ci /* hw will automatically dis OSC after cab. */ 3598c2ecf20Sopenharmony_ci val2 = alx_read_mem32(hw, ALX_MSIC2); 3608c2ecf20Sopenharmony_ci val2 &= ~ALX_MSIC2_CALB_START; 3618c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_MSIC2, val2); 3628c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_MSIC2, val2 | ALX_MSIC2_CALB_START); 3638c2ecf20Sopenharmony_ci } else { 3648c2ecf20Sopenharmony_ci val &= ~ALX_MISC_INTNLOSC_OPEN; 3658c2ecf20Sopenharmony_ci /* disable isolate for rev A devices */ 3668c2ecf20Sopenharmony_ci if (alx_is_rev_a(rev)) 3678c2ecf20Sopenharmony_ci val &= ~ALX_MISC_ISO_EN; 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_MISC, val | ALX_MISC_INTNLOSC_OPEN); 3708c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_MISC, val); 3718c2ecf20Sopenharmony_ci } 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci udelay(20); 3748c2ecf20Sopenharmony_ci} 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_cistatic int alx_stop_mac(struct alx_hw *hw) 3778c2ecf20Sopenharmony_ci{ 3788c2ecf20Sopenharmony_ci u32 rxq, txq, val; 3798c2ecf20Sopenharmony_ci u16 i; 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ci rxq = alx_read_mem32(hw, ALX_RXQ0); 3828c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_RXQ0, rxq & ~ALX_RXQ0_EN); 3838c2ecf20Sopenharmony_ci txq = alx_read_mem32(hw, ALX_TXQ0); 3848c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_TXQ0, txq & ~ALX_TXQ0_EN); 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci udelay(40); 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci hw->rx_ctrl &= ~(ALX_MAC_CTRL_RX_EN | ALX_MAC_CTRL_TX_EN); 3898c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_MAC_CTRL, hw->rx_ctrl); 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_ci for (i = 0; i < ALX_DMA_MAC_RST_TO; i++) { 3928c2ecf20Sopenharmony_ci val = alx_read_mem32(hw, ALX_MAC_STS); 3938c2ecf20Sopenharmony_ci if (!(val & ALX_MAC_STS_IDLE)) 3948c2ecf20Sopenharmony_ci return 0; 3958c2ecf20Sopenharmony_ci udelay(10); 3968c2ecf20Sopenharmony_ci } 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci return -ETIMEDOUT; 3998c2ecf20Sopenharmony_ci} 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ciint alx_reset_mac(struct alx_hw *hw) 4028c2ecf20Sopenharmony_ci{ 4038c2ecf20Sopenharmony_ci u32 val, pmctrl; 4048c2ecf20Sopenharmony_ci int i, ret; 4058c2ecf20Sopenharmony_ci u8 rev; 4068c2ecf20Sopenharmony_ci bool a_cr; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci pmctrl = 0; 4098c2ecf20Sopenharmony_ci rev = alx_hw_revision(hw); 4108c2ecf20Sopenharmony_ci a_cr = alx_is_rev_a(rev) && alx_hw_with_cr(hw); 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci /* disable all interrupts, RXQ/TXQ */ 4138c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_MSIX_MASK, 0xFFFFFFFF); 4148c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_IMR, 0); 4158c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_ISR, ALX_ISR_DIS); 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci ret = alx_stop_mac(hw); 4188c2ecf20Sopenharmony_ci if (ret) 4198c2ecf20Sopenharmony_ci return ret; 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci /* mac reset workaroud */ 4228c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_RFD_PIDX, 1); 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci /* dis l0s/l1 before mac reset */ 4258c2ecf20Sopenharmony_ci if (a_cr) { 4268c2ecf20Sopenharmony_ci pmctrl = alx_read_mem32(hw, ALX_PMCTRL); 4278c2ecf20Sopenharmony_ci if (pmctrl & (ALX_PMCTRL_L1_EN | ALX_PMCTRL_L0S_EN)) 4288c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_PMCTRL, 4298c2ecf20Sopenharmony_ci pmctrl & ~(ALX_PMCTRL_L1_EN | 4308c2ecf20Sopenharmony_ci ALX_PMCTRL_L0S_EN)); 4318c2ecf20Sopenharmony_ci } 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci /* reset whole mac safely */ 4348c2ecf20Sopenharmony_ci val = alx_read_mem32(hw, ALX_MASTER); 4358c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_MASTER, 4368c2ecf20Sopenharmony_ci val | ALX_MASTER_DMA_MAC_RST | ALX_MASTER_OOB_DIS); 4378c2ecf20Sopenharmony_ci 4388c2ecf20Sopenharmony_ci /* make sure it's real idle */ 4398c2ecf20Sopenharmony_ci udelay(10); 4408c2ecf20Sopenharmony_ci for (i = 0; i < ALX_DMA_MAC_RST_TO; i++) { 4418c2ecf20Sopenharmony_ci val = alx_read_mem32(hw, ALX_RFD_PIDX); 4428c2ecf20Sopenharmony_ci if (val == 0) 4438c2ecf20Sopenharmony_ci break; 4448c2ecf20Sopenharmony_ci udelay(10); 4458c2ecf20Sopenharmony_ci } 4468c2ecf20Sopenharmony_ci for (; i < ALX_DMA_MAC_RST_TO; i++) { 4478c2ecf20Sopenharmony_ci val = alx_read_mem32(hw, ALX_MASTER); 4488c2ecf20Sopenharmony_ci if ((val & ALX_MASTER_DMA_MAC_RST) == 0) 4498c2ecf20Sopenharmony_ci break; 4508c2ecf20Sopenharmony_ci udelay(10); 4518c2ecf20Sopenharmony_ci } 4528c2ecf20Sopenharmony_ci if (i == ALX_DMA_MAC_RST_TO) 4538c2ecf20Sopenharmony_ci return -EIO; 4548c2ecf20Sopenharmony_ci udelay(10); 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci if (a_cr) { 4578c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_MASTER, val | ALX_MASTER_PCLKSEL_SRDS); 4588c2ecf20Sopenharmony_ci /* restore l0s / l1 */ 4598c2ecf20Sopenharmony_ci if (pmctrl & (ALX_PMCTRL_L1_EN | ALX_PMCTRL_L0S_EN)) 4608c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_PMCTRL, pmctrl); 4618c2ecf20Sopenharmony_ci } 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci alx_reset_osc(hw, rev); 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci /* clear Internal OSC settings, switching OSC by hw itself, 4668c2ecf20Sopenharmony_ci * disable isolate for rev A devices 4678c2ecf20Sopenharmony_ci */ 4688c2ecf20Sopenharmony_ci val = alx_read_mem32(hw, ALX_MISC3); 4698c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_MISC3, 4708c2ecf20Sopenharmony_ci (val & ~ALX_MISC3_25M_BY_SW) | 4718c2ecf20Sopenharmony_ci ALX_MISC3_25M_NOTO_INTNL); 4728c2ecf20Sopenharmony_ci val = alx_read_mem32(hw, ALX_MISC); 4738c2ecf20Sopenharmony_ci val &= ~ALX_MISC_INTNLOSC_OPEN; 4748c2ecf20Sopenharmony_ci if (alx_is_rev_a(rev)) 4758c2ecf20Sopenharmony_ci val &= ~ALX_MISC_ISO_EN; 4768c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_MISC, val); 4778c2ecf20Sopenharmony_ci udelay(20); 4788c2ecf20Sopenharmony_ci 4798c2ecf20Sopenharmony_ci /* driver control speed/duplex, hash-alg */ 4808c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_MAC_CTRL, hw->rx_ctrl); 4818c2ecf20Sopenharmony_ci 4828c2ecf20Sopenharmony_ci val = alx_read_mem32(hw, ALX_SERDES); 4838c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_SERDES, 4848c2ecf20Sopenharmony_ci val | ALX_SERDES_MACCLK_SLWDWN | 4858c2ecf20Sopenharmony_ci ALX_SERDES_PHYCLK_SLWDWN); 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci return 0; 4888c2ecf20Sopenharmony_ci} 4898c2ecf20Sopenharmony_ci 4908c2ecf20Sopenharmony_civoid alx_reset_phy(struct alx_hw *hw) 4918c2ecf20Sopenharmony_ci{ 4928c2ecf20Sopenharmony_ci int i; 4938c2ecf20Sopenharmony_ci u32 val; 4948c2ecf20Sopenharmony_ci u16 phy_val; 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_ci /* (DSP)reset PHY core */ 4978c2ecf20Sopenharmony_ci val = alx_read_mem32(hw, ALX_PHY_CTRL); 4988c2ecf20Sopenharmony_ci val &= ~(ALX_PHY_CTRL_DSPRST_OUT | ALX_PHY_CTRL_IDDQ | 4998c2ecf20Sopenharmony_ci ALX_PHY_CTRL_GATE_25M | ALX_PHY_CTRL_POWER_DOWN | 5008c2ecf20Sopenharmony_ci ALX_PHY_CTRL_CLS); 5018c2ecf20Sopenharmony_ci val |= ALX_PHY_CTRL_RST_ANALOG; 5028c2ecf20Sopenharmony_ci 5038c2ecf20Sopenharmony_ci val |= (ALX_PHY_CTRL_HIB_PULSE | ALX_PHY_CTRL_HIB_EN); 5048c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_PHY_CTRL, val); 5058c2ecf20Sopenharmony_ci udelay(10); 5068c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_PHY_CTRL, val | ALX_PHY_CTRL_DSPRST_OUT); 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci for (i = 0; i < ALX_PHY_CTRL_DSPRST_TO; i++) 5098c2ecf20Sopenharmony_ci udelay(10); 5108c2ecf20Sopenharmony_ci 5118c2ecf20Sopenharmony_ci /* phy power saving & hib */ 5128c2ecf20Sopenharmony_ci alx_write_phy_dbg(hw, ALX_MIIDBG_LEGCYPS, ALX_LEGCYPS_DEF); 5138c2ecf20Sopenharmony_ci alx_write_phy_dbg(hw, ALX_MIIDBG_SYSMODCTRL, 5148c2ecf20Sopenharmony_ci ALX_SYSMODCTRL_IECHOADJ_DEF); 5158c2ecf20Sopenharmony_ci alx_write_phy_ext(hw, ALX_MIIEXT_PCS, ALX_MIIEXT_VDRVBIAS, 5168c2ecf20Sopenharmony_ci ALX_VDRVBIAS_DEF); 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci /* EEE advertisement */ 5198c2ecf20Sopenharmony_ci val = alx_read_mem32(hw, ALX_LPI_CTRL); 5208c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_LPI_CTRL, val & ~ALX_LPI_CTRL_EN); 5218c2ecf20Sopenharmony_ci alx_write_phy_ext(hw, ALX_MIIEXT_ANEG, ALX_MIIEXT_LOCAL_EEEADV, 0); 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci /* phy power saving */ 5248c2ecf20Sopenharmony_ci alx_write_phy_dbg(hw, ALX_MIIDBG_TST10BTCFG, ALX_TST10BTCFG_DEF); 5258c2ecf20Sopenharmony_ci alx_write_phy_dbg(hw, ALX_MIIDBG_SRDSYSMOD, ALX_SRDSYSMOD_DEF); 5268c2ecf20Sopenharmony_ci alx_write_phy_dbg(hw, ALX_MIIDBG_TST100BTCFG, ALX_TST100BTCFG_DEF); 5278c2ecf20Sopenharmony_ci alx_write_phy_dbg(hw, ALX_MIIDBG_ANACTRL, ALX_ANACTRL_DEF); 5288c2ecf20Sopenharmony_ci alx_read_phy_dbg(hw, ALX_MIIDBG_GREENCFG2, &phy_val); 5298c2ecf20Sopenharmony_ci alx_write_phy_dbg(hw, ALX_MIIDBG_GREENCFG2, 5308c2ecf20Sopenharmony_ci phy_val & ~ALX_GREENCFG2_GATE_DFSE_EN); 5318c2ecf20Sopenharmony_ci /* rtl8139c, 120m issue */ 5328c2ecf20Sopenharmony_ci alx_write_phy_ext(hw, ALX_MIIEXT_ANEG, ALX_MIIEXT_NLP78, 5338c2ecf20Sopenharmony_ci ALX_MIIEXT_NLP78_120M_DEF); 5348c2ecf20Sopenharmony_ci alx_write_phy_ext(hw, ALX_MIIEXT_ANEG, ALX_MIIEXT_S3DIG10, 5358c2ecf20Sopenharmony_ci ALX_MIIEXT_S3DIG10_DEF); 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ci if (hw->lnk_patch) { 5388c2ecf20Sopenharmony_ci /* Turn off half amplitude */ 5398c2ecf20Sopenharmony_ci alx_read_phy_ext(hw, ALX_MIIEXT_PCS, ALX_MIIEXT_CLDCTRL3, 5408c2ecf20Sopenharmony_ci &phy_val); 5418c2ecf20Sopenharmony_ci alx_write_phy_ext(hw, ALX_MIIEXT_PCS, ALX_MIIEXT_CLDCTRL3, 5428c2ecf20Sopenharmony_ci phy_val | ALX_CLDCTRL3_BP_CABLE1TH_DET_GT); 5438c2ecf20Sopenharmony_ci /* Turn off Green feature */ 5448c2ecf20Sopenharmony_ci alx_read_phy_dbg(hw, ALX_MIIDBG_GREENCFG2, &phy_val); 5458c2ecf20Sopenharmony_ci alx_write_phy_dbg(hw, ALX_MIIDBG_GREENCFG2, 5468c2ecf20Sopenharmony_ci phy_val | ALX_GREENCFG2_BP_GREEN); 5478c2ecf20Sopenharmony_ci /* Turn off half Bias */ 5488c2ecf20Sopenharmony_ci alx_read_phy_ext(hw, ALX_MIIEXT_PCS, ALX_MIIEXT_CLDCTRL5, 5498c2ecf20Sopenharmony_ci &phy_val); 5508c2ecf20Sopenharmony_ci alx_write_phy_ext(hw, ALX_MIIEXT_PCS, ALX_MIIEXT_CLDCTRL5, 5518c2ecf20Sopenharmony_ci phy_val | ALX_CLDCTRL5_BP_VD_HLFBIAS); 5528c2ecf20Sopenharmony_ci } 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_ci /* set phy interrupt mask */ 5558c2ecf20Sopenharmony_ci alx_write_phy_reg(hw, ALX_MII_IER, ALX_IER_LINK_UP | ALX_IER_LINK_DOWN); 5568c2ecf20Sopenharmony_ci} 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci#define ALX_PCI_CMD (PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY | PCI_COMMAND_IO) 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_civoid alx_reset_pcie(struct alx_hw *hw) 5618c2ecf20Sopenharmony_ci{ 5628c2ecf20Sopenharmony_ci u8 rev = alx_hw_revision(hw); 5638c2ecf20Sopenharmony_ci u32 val; 5648c2ecf20Sopenharmony_ci u16 val16; 5658c2ecf20Sopenharmony_ci 5668c2ecf20Sopenharmony_ci /* Workaround for PCI problem when BIOS sets MMRBC incorrectly. */ 5678c2ecf20Sopenharmony_ci pci_read_config_word(hw->pdev, PCI_COMMAND, &val16); 5688c2ecf20Sopenharmony_ci if (!(val16 & ALX_PCI_CMD) || (val16 & PCI_COMMAND_INTX_DISABLE)) { 5698c2ecf20Sopenharmony_ci val16 = (val16 | ALX_PCI_CMD) & ~PCI_COMMAND_INTX_DISABLE; 5708c2ecf20Sopenharmony_ci pci_write_config_word(hw->pdev, PCI_COMMAND, val16); 5718c2ecf20Sopenharmony_ci } 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci /* clear WoL setting/status */ 5748c2ecf20Sopenharmony_ci val = alx_read_mem32(hw, ALX_WOL0); 5758c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_WOL0, 0); 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci val = alx_read_mem32(hw, ALX_PDLL_TRNS1); 5788c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_PDLL_TRNS1, val & ~ALX_PDLL_TRNS1_D3PLLOFF_EN); 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci /* mask some pcie error bits */ 5818c2ecf20Sopenharmony_ci val = alx_read_mem32(hw, ALX_UE_SVRT); 5828c2ecf20Sopenharmony_ci val &= ~(ALX_UE_SVRT_DLPROTERR | ALX_UE_SVRT_FCPROTERR); 5838c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_UE_SVRT, val); 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci /* wol 25M & pclk */ 5868c2ecf20Sopenharmony_ci val = alx_read_mem32(hw, ALX_MASTER); 5878c2ecf20Sopenharmony_ci if (alx_is_rev_a(rev) && alx_hw_with_cr(hw)) { 5888c2ecf20Sopenharmony_ci if ((val & ALX_MASTER_WAKEN_25M) == 0 || 5898c2ecf20Sopenharmony_ci (val & ALX_MASTER_PCLKSEL_SRDS) == 0) 5908c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_MASTER, 5918c2ecf20Sopenharmony_ci val | ALX_MASTER_PCLKSEL_SRDS | 5928c2ecf20Sopenharmony_ci ALX_MASTER_WAKEN_25M); 5938c2ecf20Sopenharmony_ci } else { 5948c2ecf20Sopenharmony_ci if ((val & ALX_MASTER_WAKEN_25M) == 0 || 5958c2ecf20Sopenharmony_ci (val & ALX_MASTER_PCLKSEL_SRDS) != 0) 5968c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_MASTER, 5978c2ecf20Sopenharmony_ci (val & ~ALX_MASTER_PCLKSEL_SRDS) | 5988c2ecf20Sopenharmony_ci ALX_MASTER_WAKEN_25M); 5998c2ecf20Sopenharmony_ci } 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci /* ASPM setting */ 6028c2ecf20Sopenharmony_ci alx_enable_aspm(hw, true, true); 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci udelay(10); 6058c2ecf20Sopenharmony_ci} 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_civoid alx_start_mac(struct alx_hw *hw) 6088c2ecf20Sopenharmony_ci{ 6098c2ecf20Sopenharmony_ci u32 mac, txq, rxq; 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_ci rxq = alx_read_mem32(hw, ALX_RXQ0); 6128c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_RXQ0, rxq | ALX_RXQ0_EN); 6138c2ecf20Sopenharmony_ci txq = alx_read_mem32(hw, ALX_TXQ0); 6148c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_TXQ0, txq | ALX_TXQ0_EN); 6158c2ecf20Sopenharmony_ci 6168c2ecf20Sopenharmony_ci mac = hw->rx_ctrl; 6178c2ecf20Sopenharmony_ci if (hw->duplex == DUPLEX_FULL) 6188c2ecf20Sopenharmony_ci mac |= ALX_MAC_CTRL_FULLD; 6198c2ecf20Sopenharmony_ci else 6208c2ecf20Sopenharmony_ci mac &= ~ALX_MAC_CTRL_FULLD; 6218c2ecf20Sopenharmony_ci ALX_SET_FIELD(mac, ALX_MAC_CTRL_SPEED, 6228c2ecf20Sopenharmony_ci hw->link_speed == SPEED_1000 ? ALX_MAC_CTRL_SPEED_1000 : 6238c2ecf20Sopenharmony_ci ALX_MAC_CTRL_SPEED_10_100); 6248c2ecf20Sopenharmony_ci mac |= ALX_MAC_CTRL_TX_EN | ALX_MAC_CTRL_RX_EN; 6258c2ecf20Sopenharmony_ci hw->rx_ctrl = mac; 6268c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_MAC_CTRL, mac); 6278c2ecf20Sopenharmony_ci} 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_civoid alx_cfg_mac_flowcontrol(struct alx_hw *hw, u8 fc) 6308c2ecf20Sopenharmony_ci{ 6318c2ecf20Sopenharmony_ci if (fc & ALX_FC_RX) 6328c2ecf20Sopenharmony_ci hw->rx_ctrl |= ALX_MAC_CTRL_RXFC_EN; 6338c2ecf20Sopenharmony_ci else 6348c2ecf20Sopenharmony_ci hw->rx_ctrl &= ~ALX_MAC_CTRL_RXFC_EN; 6358c2ecf20Sopenharmony_ci 6368c2ecf20Sopenharmony_ci if (fc & ALX_FC_TX) 6378c2ecf20Sopenharmony_ci hw->rx_ctrl |= ALX_MAC_CTRL_TXFC_EN; 6388c2ecf20Sopenharmony_ci else 6398c2ecf20Sopenharmony_ci hw->rx_ctrl &= ~ALX_MAC_CTRL_TXFC_EN; 6408c2ecf20Sopenharmony_ci 6418c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_MAC_CTRL, hw->rx_ctrl); 6428c2ecf20Sopenharmony_ci} 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_civoid alx_enable_aspm(struct alx_hw *hw, bool l0s_en, bool l1_en) 6458c2ecf20Sopenharmony_ci{ 6468c2ecf20Sopenharmony_ci u32 pmctrl; 6478c2ecf20Sopenharmony_ci u8 rev = alx_hw_revision(hw); 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_ci pmctrl = alx_read_mem32(hw, ALX_PMCTRL); 6508c2ecf20Sopenharmony_ci 6518c2ecf20Sopenharmony_ci ALX_SET_FIELD(pmctrl, ALX_PMCTRL_LCKDET_TIMER, 6528c2ecf20Sopenharmony_ci ALX_PMCTRL_LCKDET_TIMER_DEF); 6538c2ecf20Sopenharmony_ci pmctrl |= ALX_PMCTRL_RCVR_WT_1US | 6548c2ecf20Sopenharmony_ci ALX_PMCTRL_L1_CLKSW_EN | 6558c2ecf20Sopenharmony_ci ALX_PMCTRL_L1_SRDSRX_PWD; 6568c2ecf20Sopenharmony_ci ALX_SET_FIELD(pmctrl, ALX_PMCTRL_L1REQ_TO, ALX_PMCTRL_L1REG_TO_DEF); 6578c2ecf20Sopenharmony_ci ALX_SET_FIELD(pmctrl, ALX_PMCTRL_L1_TIMER, ALX_PMCTRL_L1_TIMER_16US); 6588c2ecf20Sopenharmony_ci pmctrl &= ~(ALX_PMCTRL_L1_SRDS_EN | 6598c2ecf20Sopenharmony_ci ALX_PMCTRL_L1_SRDSPLL_EN | 6608c2ecf20Sopenharmony_ci ALX_PMCTRL_L1_BUFSRX_EN | 6618c2ecf20Sopenharmony_ci ALX_PMCTRL_SADLY_EN | 6628c2ecf20Sopenharmony_ci ALX_PMCTRL_HOTRST_WTEN| 6638c2ecf20Sopenharmony_ci ALX_PMCTRL_L0S_EN | 6648c2ecf20Sopenharmony_ci ALX_PMCTRL_L1_EN | 6658c2ecf20Sopenharmony_ci ALX_PMCTRL_ASPM_FCEN | 6668c2ecf20Sopenharmony_ci ALX_PMCTRL_TXL1_AFTER_L0S | 6678c2ecf20Sopenharmony_ci ALX_PMCTRL_RXL1_AFTER_L0S); 6688c2ecf20Sopenharmony_ci if (alx_is_rev_a(rev) && alx_hw_with_cr(hw)) 6698c2ecf20Sopenharmony_ci pmctrl |= ALX_PMCTRL_L1_SRDS_EN | ALX_PMCTRL_L1_SRDSPLL_EN; 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci if (l0s_en) 6728c2ecf20Sopenharmony_ci pmctrl |= (ALX_PMCTRL_L0S_EN | ALX_PMCTRL_ASPM_FCEN); 6738c2ecf20Sopenharmony_ci if (l1_en) 6748c2ecf20Sopenharmony_ci pmctrl |= (ALX_PMCTRL_L1_EN | ALX_PMCTRL_ASPM_FCEN); 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_PMCTRL, pmctrl); 6778c2ecf20Sopenharmony_ci} 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_cistatic u32 ethadv_to_hw_cfg(struct alx_hw *hw, u32 ethadv_cfg) 6818c2ecf20Sopenharmony_ci{ 6828c2ecf20Sopenharmony_ci u32 cfg = 0; 6838c2ecf20Sopenharmony_ci 6848c2ecf20Sopenharmony_ci if (ethadv_cfg & ADVERTISED_Autoneg) { 6858c2ecf20Sopenharmony_ci cfg |= ALX_DRV_PHY_AUTO; 6868c2ecf20Sopenharmony_ci if (ethadv_cfg & ADVERTISED_10baseT_Half) 6878c2ecf20Sopenharmony_ci cfg |= ALX_DRV_PHY_10; 6888c2ecf20Sopenharmony_ci if (ethadv_cfg & ADVERTISED_10baseT_Full) 6898c2ecf20Sopenharmony_ci cfg |= ALX_DRV_PHY_10 | ALX_DRV_PHY_DUPLEX; 6908c2ecf20Sopenharmony_ci if (ethadv_cfg & ADVERTISED_100baseT_Half) 6918c2ecf20Sopenharmony_ci cfg |= ALX_DRV_PHY_100; 6928c2ecf20Sopenharmony_ci if (ethadv_cfg & ADVERTISED_100baseT_Full) 6938c2ecf20Sopenharmony_ci cfg |= ALX_DRV_PHY_100 | ALX_DRV_PHY_DUPLEX; 6948c2ecf20Sopenharmony_ci if (ethadv_cfg & ADVERTISED_1000baseT_Half) 6958c2ecf20Sopenharmony_ci cfg |= ALX_DRV_PHY_1000; 6968c2ecf20Sopenharmony_ci if (ethadv_cfg & ADVERTISED_1000baseT_Full) 6978c2ecf20Sopenharmony_ci cfg |= ALX_DRV_PHY_100 | ALX_DRV_PHY_DUPLEX; 6988c2ecf20Sopenharmony_ci if (ethadv_cfg & ADVERTISED_Pause) 6998c2ecf20Sopenharmony_ci cfg |= ADVERTISE_PAUSE_CAP; 7008c2ecf20Sopenharmony_ci if (ethadv_cfg & ADVERTISED_Asym_Pause) 7018c2ecf20Sopenharmony_ci cfg |= ADVERTISE_PAUSE_ASYM; 7028c2ecf20Sopenharmony_ci } else { 7038c2ecf20Sopenharmony_ci switch (ethadv_cfg) { 7048c2ecf20Sopenharmony_ci case ADVERTISED_10baseT_Half: 7058c2ecf20Sopenharmony_ci cfg |= ALX_DRV_PHY_10; 7068c2ecf20Sopenharmony_ci break; 7078c2ecf20Sopenharmony_ci case ADVERTISED_100baseT_Half: 7088c2ecf20Sopenharmony_ci cfg |= ALX_DRV_PHY_100; 7098c2ecf20Sopenharmony_ci break; 7108c2ecf20Sopenharmony_ci case ADVERTISED_10baseT_Full: 7118c2ecf20Sopenharmony_ci cfg |= ALX_DRV_PHY_10 | ALX_DRV_PHY_DUPLEX; 7128c2ecf20Sopenharmony_ci break; 7138c2ecf20Sopenharmony_ci case ADVERTISED_100baseT_Full: 7148c2ecf20Sopenharmony_ci cfg |= ALX_DRV_PHY_100 | ALX_DRV_PHY_DUPLEX; 7158c2ecf20Sopenharmony_ci break; 7168c2ecf20Sopenharmony_ci } 7178c2ecf20Sopenharmony_ci } 7188c2ecf20Sopenharmony_ci 7198c2ecf20Sopenharmony_ci return cfg; 7208c2ecf20Sopenharmony_ci} 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ciint alx_setup_speed_duplex(struct alx_hw *hw, u32 ethadv, u8 flowctrl) 7238c2ecf20Sopenharmony_ci{ 7248c2ecf20Sopenharmony_ci u16 adv, giga, cr; 7258c2ecf20Sopenharmony_ci u32 val; 7268c2ecf20Sopenharmony_ci int err = 0; 7278c2ecf20Sopenharmony_ci 7288c2ecf20Sopenharmony_ci alx_write_phy_reg(hw, ALX_MII_DBG_ADDR, 0); 7298c2ecf20Sopenharmony_ci val = alx_read_mem32(hw, ALX_DRV); 7308c2ecf20Sopenharmony_ci ALX_SET_FIELD(val, ALX_DRV_PHY, 0); 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_ci if (ethadv & ADVERTISED_Autoneg) { 7338c2ecf20Sopenharmony_ci adv = ADVERTISE_CSMA; 7348c2ecf20Sopenharmony_ci adv |= ethtool_adv_to_mii_adv_t(ethadv); 7358c2ecf20Sopenharmony_ci 7368c2ecf20Sopenharmony_ci if (flowctrl & ALX_FC_ANEG) { 7378c2ecf20Sopenharmony_ci if (flowctrl & ALX_FC_RX) { 7388c2ecf20Sopenharmony_ci adv |= ADVERTISED_Pause; 7398c2ecf20Sopenharmony_ci if (!(flowctrl & ALX_FC_TX)) 7408c2ecf20Sopenharmony_ci adv |= ADVERTISED_Asym_Pause; 7418c2ecf20Sopenharmony_ci } else if (flowctrl & ALX_FC_TX) { 7428c2ecf20Sopenharmony_ci adv |= ADVERTISED_Asym_Pause; 7438c2ecf20Sopenharmony_ci } 7448c2ecf20Sopenharmony_ci } 7458c2ecf20Sopenharmony_ci giga = 0; 7468c2ecf20Sopenharmony_ci if (alx_hw_giga(hw)) 7478c2ecf20Sopenharmony_ci giga = ethtool_adv_to_mii_ctrl1000_t(ethadv); 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci cr = BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART; 7508c2ecf20Sopenharmony_ci 7518c2ecf20Sopenharmony_ci if (alx_write_phy_reg(hw, MII_ADVERTISE, adv) || 7528c2ecf20Sopenharmony_ci alx_write_phy_reg(hw, MII_CTRL1000, giga) || 7538c2ecf20Sopenharmony_ci alx_write_phy_reg(hw, MII_BMCR, cr)) 7548c2ecf20Sopenharmony_ci err = -EBUSY; 7558c2ecf20Sopenharmony_ci } else { 7568c2ecf20Sopenharmony_ci cr = BMCR_RESET; 7578c2ecf20Sopenharmony_ci if (ethadv == ADVERTISED_100baseT_Half || 7588c2ecf20Sopenharmony_ci ethadv == ADVERTISED_100baseT_Full) 7598c2ecf20Sopenharmony_ci cr |= BMCR_SPEED100; 7608c2ecf20Sopenharmony_ci if (ethadv == ADVERTISED_10baseT_Full || 7618c2ecf20Sopenharmony_ci ethadv == ADVERTISED_100baseT_Full) 7628c2ecf20Sopenharmony_ci cr |= BMCR_FULLDPLX; 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci err = alx_write_phy_reg(hw, MII_BMCR, cr); 7658c2ecf20Sopenharmony_ci } 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_ci if (!err) { 7688c2ecf20Sopenharmony_ci alx_write_phy_reg(hw, ALX_MII_DBG_ADDR, ALX_PHY_INITED); 7698c2ecf20Sopenharmony_ci val |= ethadv_to_hw_cfg(hw, ethadv); 7708c2ecf20Sopenharmony_ci } 7718c2ecf20Sopenharmony_ci 7728c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_DRV, val); 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci return err; 7758c2ecf20Sopenharmony_ci} 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_civoid alx_post_phy_link(struct alx_hw *hw) 7798c2ecf20Sopenharmony_ci{ 7808c2ecf20Sopenharmony_ci u16 phy_val, len, agc; 7818c2ecf20Sopenharmony_ci u8 revid = alx_hw_revision(hw); 7828c2ecf20Sopenharmony_ci bool adj_th = revid == ALX_REV_B0; 7838c2ecf20Sopenharmony_ci 7848c2ecf20Sopenharmony_ci if (revid != ALX_REV_B0 && !alx_is_rev_a(revid)) 7858c2ecf20Sopenharmony_ci return; 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_ci /* 1000BT/AZ, wrong cable length */ 7888c2ecf20Sopenharmony_ci if (hw->link_speed != SPEED_UNKNOWN) { 7898c2ecf20Sopenharmony_ci alx_read_phy_ext(hw, ALX_MIIEXT_PCS, ALX_MIIEXT_CLDCTRL6, 7908c2ecf20Sopenharmony_ci &phy_val); 7918c2ecf20Sopenharmony_ci len = ALX_GET_FIELD(phy_val, ALX_CLDCTRL6_CAB_LEN); 7928c2ecf20Sopenharmony_ci alx_read_phy_dbg(hw, ALX_MIIDBG_AGC, &phy_val); 7938c2ecf20Sopenharmony_ci agc = ALX_GET_FIELD(phy_val, ALX_AGC_2_VGA); 7948c2ecf20Sopenharmony_ci 7958c2ecf20Sopenharmony_ci if ((hw->link_speed == SPEED_1000 && 7968c2ecf20Sopenharmony_ci (len > ALX_CLDCTRL6_CAB_LEN_SHORT1G || 7978c2ecf20Sopenharmony_ci (len == 0 && agc > ALX_AGC_LONG1G_LIMT))) || 7988c2ecf20Sopenharmony_ci (hw->link_speed == SPEED_100 && 7998c2ecf20Sopenharmony_ci (len > ALX_CLDCTRL6_CAB_LEN_SHORT100M || 8008c2ecf20Sopenharmony_ci (len == 0 && agc > ALX_AGC_LONG100M_LIMT)))) { 8018c2ecf20Sopenharmony_ci alx_write_phy_dbg(hw, ALX_MIIDBG_AZ_ANADECT, 8028c2ecf20Sopenharmony_ci ALX_AZ_ANADECT_LONG); 8038c2ecf20Sopenharmony_ci alx_read_phy_ext(hw, ALX_MIIEXT_ANEG, ALX_MIIEXT_AFE, 8048c2ecf20Sopenharmony_ci &phy_val); 8058c2ecf20Sopenharmony_ci alx_write_phy_ext(hw, ALX_MIIEXT_ANEG, ALX_MIIEXT_AFE, 8068c2ecf20Sopenharmony_ci phy_val | ALX_AFE_10BT_100M_TH); 8078c2ecf20Sopenharmony_ci } else { 8088c2ecf20Sopenharmony_ci alx_write_phy_dbg(hw, ALX_MIIDBG_AZ_ANADECT, 8098c2ecf20Sopenharmony_ci ALX_AZ_ANADECT_DEF); 8108c2ecf20Sopenharmony_ci alx_read_phy_ext(hw, ALX_MIIEXT_ANEG, 8118c2ecf20Sopenharmony_ci ALX_MIIEXT_AFE, &phy_val); 8128c2ecf20Sopenharmony_ci alx_write_phy_ext(hw, ALX_MIIEXT_ANEG, ALX_MIIEXT_AFE, 8138c2ecf20Sopenharmony_ci phy_val & ~ALX_AFE_10BT_100M_TH); 8148c2ecf20Sopenharmony_ci } 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_ci /* threshold adjust */ 8178c2ecf20Sopenharmony_ci if (adj_th && hw->lnk_patch) { 8188c2ecf20Sopenharmony_ci if (hw->link_speed == SPEED_100) { 8198c2ecf20Sopenharmony_ci alx_write_phy_dbg(hw, ALX_MIIDBG_MSE16DB, 8208c2ecf20Sopenharmony_ci ALX_MSE16DB_UP); 8218c2ecf20Sopenharmony_ci } else if (hw->link_speed == SPEED_1000) { 8228c2ecf20Sopenharmony_ci /* 8238c2ecf20Sopenharmony_ci * Giga link threshold, raise the tolerance of 8248c2ecf20Sopenharmony_ci * noise 50% 8258c2ecf20Sopenharmony_ci */ 8268c2ecf20Sopenharmony_ci alx_read_phy_dbg(hw, ALX_MIIDBG_MSE20DB, 8278c2ecf20Sopenharmony_ci &phy_val); 8288c2ecf20Sopenharmony_ci ALX_SET_FIELD(phy_val, ALX_MSE20DB_TH, 8298c2ecf20Sopenharmony_ci ALX_MSE20DB_TH_HI); 8308c2ecf20Sopenharmony_ci alx_write_phy_dbg(hw, ALX_MIIDBG_MSE20DB, 8318c2ecf20Sopenharmony_ci phy_val); 8328c2ecf20Sopenharmony_ci } 8338c2ecf20Sopenharmony_ci } 8348c2ecf20Sopenharmony_ci } else { 8358c2ecf20Sopenharmony_ci alx_read_phy_ext(hw, ALX_MIIEXT_ANEG, ALX_MIIEXT_AFE, 8368c2ecf20Sopenharmony_ci &phy_val); 8378c2ecf20Sopenharmony_ci alx_write_phy_ext(hw, ALX_MIIEXT_ANEG, ALX_MIIEXT_AFE, 8388c2ecf20Sopenharmony_ci phy_val & ~ALX_AFE_10BT_100M_TH); 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci if (adj_th && hw->lnk_patch) { 8418c2ecf20Sopenharmony_ci alx_write_phy_dbg(hw, ALX_MIIDBG_MSE16DB, 8428c2ecf20Sopenharmony_ci ALX_MSE16DB_DOWN); 8438c2ecf20Sopenharmony_ci alx_read_phy_dbg(hw, ALX_MIIDBG_MSE20DB, &phy_val); 8448c2ecf20Sopenharmony_ci ALX_SET_FIELD(phy_val, ALX_MSE20DB_TH, 8458c2ecf20Sopenharmony_ci ALX_MSE20DB_TH_DEF); 8468c2ecf20Sopenharmony_ci alx_write_phy_dbg(hw, ALX_MIIDBG_MSE20DB, phy_val); 8478c2ecf20Sopenharmony_ci } 8488c2ecf20Sopenharmony_ci } 8498c2ecf20Sopenharmony_ci} 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_cibool alx_phy_configured(struct alx_hw *hw) 8528c2ecf20Sopenharmony_ci{ 8538c2ecf20Sopenharmony_ci u32 cfg, hw_cfg; 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci cfg = ethadv_to_hw_cfg(hw, hw->adv_cfg); 8568c2ecf20Sopenharmony_ci cfg = ALX_GET_FIELD(cfg, ALX_DRV_PHY); 8578c2ecf20Sopenharmony_ci hw_cfg = alx_get_phy_config(hw); 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci if (hw_cfg == ALX_DRV_PHY_UNKNOWN) 8608c2ecf20Sopenharmony_ci return false; 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci return cfg == hw_cfg; 8638c2ecf20Sopenharmony_ci} 8648c2ecf20Sopenharmony_ci 8658c2ecf20Sopenharmony_ciint alx_read_phy_link(struct alx_hw *hw) 8668c2ecf20Sopenharmony_ci{ 8678c2ecf20Sopenharmony_ci struct pci_dev *pdev = hw->pdev; 8688c2ecf20Sopenharmony_ci u16 bmsr, giga; 8698c2ecf20Sopenharmony_ci int err; 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ci err = alx_read_phy_reg(hw, MII_BMSR, &bmsr); 8728c2ecf20Sopenharmony_ci if (err) 8738c2ecf20Sopenharmony_ci return err; 8748c2ecf20Sopenharmony_ci 8758c2ecf20Sopenharmony_ci err = alx_read_phy_reg(hw, MII_BMSR, &bmsr); 8768c2ecf20Sopenharmony_ci if (err) 8778c2ecf20Sopenharmony_ci return err; 8788c2ecf20Sopenharmony_ci 8798c2ecf20Sopenharmony_ci if (!(bmsr & BMSR_LSTATUS)) { 8808c2ecf20Sopenharmony_ci hw->link_speed = SPEED_UNKNOWN; 8818c2ecf20Sopenharmony_ci hw->duplex = DUPLEX_UNKNOWN; 8828c2ecf20Sopenharmony_ci return 0; 8838c2ecf20Sopenharmony_ci } 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci /* speed/duplex result is saved in PHY Specific Status Register */ 8868c2ecf20Sopenharmony_ci err = alx_read_phy_reg(hw, ALX_MII_GIGA_PSSR, &giga); 8878c2ecf20Sopenharmony_ci if (err) 8888c2ecf20Sopenharmony_ci return err; 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci if (!(giga & ALX_GIGA_PSSR_SPD_DPLX_RESOLVED)) 8918c2ecf20Sopenharmony_ci goto wrong_speed; 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci switch (giga & ALX_GIGA_PSSR_SPEED) { 8948c2ecf20Sopenharmony_ci case ALX_GIGA_PSSR_1000MBS: 8958c2ecf20Sopenharmony_ci hw->link_speed = SPEED_1000; 8968c2ecf20Sopenharmony_ci break; 8978c2ecf20Sopenharmony_ci case ALX_GIGA_PSSR_100MBS: 8988c2ecf20Sopenharmony_ci hw->link_speed = SPEED_100; 8998c2ecf20Sopenharmony_ci break; 9008c2ecf20Sopenharmony_ci case ALX_GIGA_PSSR_10MBS: 9018c2ecf20Sopenharmony_ci hw->link_speed = SPEED_10; 9028c2ecf20Sopenharmony_ci break; 9038c2ecf20Sopenharmony_ci default: 9048c2ecf20Sopenharmony_ci goto wrong_speed; 9058c2ecf20Sopenharmony_ci } 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_ci hw->duplex = (giga & ALX_GIGA_PSSR_DPLX) ? DUPLEX_FULL : DUPLEX_HALF; 9088c2ecf20Sopenharmony_ci return 0; 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ciwrong_speed: 9118c2ecf20Sopenharmony_ci dev_err(&pdev->dev, "invalid PHY speed/duplex: 0x%x\n", giga); 9128c2ecf20Sopenharmony_ci return -EINVAL; 9138c2ecf20Sopenharmony_ci} 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_ciint alx_clear_phy_intr(struct alx_hw *hw) 9168c2ecf20Sopenharmony_ci{ 9178c2ecf20Sopenharmony_ci u16 isr; 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci /* clear interrupt status by reading it */ 9208c2ecf20Sopenharmony_ci return alx_read_phy_reg(hw, ALX_MII_ISR, &isr); 9218c2ecf20Sopenharmony_ci} 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_civoid alx_disable_rss(struct alx_hw *hw) 9248c2ecf20Sopenharmony_ci{ 9258c2ecf20Sopenharmony_ci u32 ctrl = alx_read_mem32(hw, ALX_RXQ0); 9268c2ecf20Sopenharmony_ci 9278c2ecf20Sopenharmony_ci ctrl &= ~ALX_RXQ0_RSS_HASH_EN; 9288c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_RXQ0, ctrl); 9298c2ecf20Sopenharmony_ci} 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_civoid alx_configure_basic(struct alx_hw *hw) 9328c2ecf20Sopenharmony_ci{ 9338c2ecf20Sopenharmony_ci u32 val, raw_mtu, max_payload; 9348c2ecf20Sopenharmony_ci u16 val16; 9358c2ecf20Sopenharmony_ci u8 chip_rev = alx_hw_revision(hw); 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci alx_set_macaddr(hw, hw->mac_addr); 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_CLK_GATE, ALX_CLK_GATE_ALL); 9408c2ecf20Sopenharmony_ci 9418c2ecf20Sopenharmony_ci /* idle timeout to switch clk_125M */ 9428c2ecf20Sopenharmony_ci if (chip_rev >= ALX_REV_B0) 9438c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_IDLE_DECISN_TIMER, 9448c2ecf20Sopenharmony_ci ALX_IDLE_DECISN_TIMER_DEF); 9458c2ecf20Sopenharmony_ci 9468c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_SMB_TIMER, hw->smb_timer * 500UL); 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_ci val = alx_read_mem32(hw, ALX_MASTER); 9498c2ecf20Sopenharmony_ci val |= ALX_MASTER_IRQMOD2_EN | 9508c2ecf20Sopenharmony_ci ALX_MASTER_IRQMOD1_EN | 9518c2ecf20Sopenharmony_ci ALX_MASTER_SYSALVTIMER_EN; 9528c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_MASTER, val); 9538c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_IRQ_MODU_TIMER, 9548c2ecf20Sopenharmony_ci (hw->imt >> 1) << ALX_IRQ_MODU_TIMER1_SHIFT); 9558c2ecf20Sopenharmony_ci /* intr re-trig timeout */ 9568c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_INT_RETRIG, ALX_INT_RETRIG_TO); 9578c2ecf20Sopenharmony_ci /* tpd threshold to trig int */ 9588c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_TINT_TPD_THRSHLD, hw->ith_tpd); 9598c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_TINT_TIMER, hw->imt); 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci raw_mtu = ALX_RAW_MTU(hw->mtu); 9628c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_MTU, raw_mtu); 9638c2ecf20Sopenharmony_ci if (raw_mtu > (ALX_MTU_JUMBO_TH + ETH_FCS_LEN + VLAN_HLEN)) 9648c2ecf20Sopenharmony_ci hw->rx_ctrl &= ~ALX_MAC_CTRL_FAST_PAUSE; 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_ci if (raw_mtu < ALX_TXQ1_JUMBO_TSO_TH) 9678c2ecf20Sopenharmony_ci val = (raw_mtu + 7) >> 3; 9688c2ecf20Sopenharmony_ci else 9698c2ecf20Sopenharmony_ci val = ALX_TXQ1_JUMBO_TSO_TH >> 3; 9708c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_TXQ1, val | ALX_TXQ1_ERRLGPKT_DROP_EN); 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_ci max_payload = pcie_get_readrq(hw->pdev) >> 8; 9738c2ecf20Sopenharmony_ci /* 9748c2ecf20Sopenharmony_ci * if BIOS had changed the default dma read max length, 9758c2ecf20Sopenharmony_ci * restore it to default value 9768c2ecf20Sopenharmony_ci */ 9778c2ecf20Sopenharmony_ci if (max_payload < ALX_DEV_CTRL_MAXRRS_MIN) 9788c2ecf20Sopenharmony_ci pcie_set_readrq(hw->pdev, 128 << ALX_DEV_CTRL_MAXRRS_MIN); 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_ci val = ALX_TXQ_TPD_BURSTPREF_DEF << ALX_TXQ0_TPD_BURSTPREF_SHIFT | 9818c2ecf20Sopenharmony_ci ALX_TXQ0_MODE_ENHANCE | ALX_TXQ0_LSO_8023_EN | 9828c2ecf20Sopenharmony_ci ALX_TXQ0_SUPT_IPOPT | 9838c2ecf20Sopenharmony_ci ALX_TXQ_TXF_BURST_PREF_DEF << ALX_TXQ0_TXF_BURST_PREF_SHIFT; 9848c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_TXQ0, val); 9858c2ecf20Sopenharmony_ci val = ALX_TXQ_TPD_BURSTPREF_DEF << ALX_HQTPD_Q1_NUMPREF_SHIFT | 9868c2ecf20Sopenharmony_ci ALX_TXQ_TPD_BURSTPREF_DEF << ALX_HQTPD_Q2_NUMPREF_SHIFT | 9878c2ecf20Sopenharmony_ci ALX_TXQ_TPD_BURSTPREF_DEF << ALX_HQTPD_Q3_NUMPREF_SHIFT | 9888c2ecf20Sopenharmony_ci ALX_HQTPD_BURST_EN; 9898c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_HQTPD, val); 9908c2ecf20Sopenharmony_ci 9918c2ecf20Sopenharmony_ci /* rxq, flow control */ 9928c2ecf20Sopenharmony_ci val = alx_read_mem32(hw, ALX_SRAM5); 9938c2ecf20Sopenharmony_ci val = ALX_GET_FIELD(val, ALX_SRAM_RXF_LEN) << 3; 9948c2ecf20Sopenharmony_ci if (val > ALX_SRAM_RXF_LEN_8K) { 9958c2ecf20Sopenharmony_ci val16 = ALX_MTU_STD_ALGN >> 3; 9968c2ecf20Sopenharmony_ci val = (val - ALX_RXQ2_RXF_FLOW_CTRL_RSVD) >> 3; 9978c2ecf20Sopenharmony_ci } else { 9988c2ecf20Sopenharmony_ci val16 = ALX_MTU_STD_ALGN >> 3; 9998c2ecf20Sopenharmony_ci val = (val - ALX_MTU_STD_ALGN) >> 3; 10008c2ecf20Sopenharmony_ci } 10018c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_RXQ2, 10028c2ecf20Sopenharmony_ci val16 << ALX_RXQ2_RXF_XOFF_THRESH_SHIFT | 10038c2ecf20Sopenharmony_ci val << ALX_RXQ2_RXF_XON_THRESH_SHIFT); 10048c2ecf20Sopenharmony_ci val = ALX_RXQ0_NUM_RFD_PREF_DEF << ALX_RXQ0_NUM_RFD_PREF_SHIFT | 10058c2ecf20Sopenharmony_ci ALX_RXQ0_RSS_MODE_DIS << ALX_RXQ0_RSS_MODE_SHIFT | 10068c2ecf20Sopenharmony_ci ALX_RXQ0_IDT_TBL_SIZE_DEF << ALX_RXQ0_IDT_TBL_SIZE_SHIFT | 10078c2ecf20Sopenharmony_ci ALX_RXQ0_RSS_HSTYP_ALL | ALX_RXQ0_RSS_HASH_EN | 10088c2ecf20Sopenharmony_ci ALX_RXQ0_IPV6_PARSE_EN; 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci if (alx_hw_giga(hw)) 10118c2ecf20Sopenharmony_ci ALX_SET_FIELD(val, ALX_RXQ0_ASPM_THRESH, 10128c2ecf20Sopenharmony_ci ALX_RXQ0_ASPM_THRESH_100M); 10138c2ecf20Sopenharmony_ci 10148c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_RXQ0, val); 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci val = alx_read_mem32(hw, ALX_DMA); 10178c2ecf20Sopenharmony_ci val = ALX_DMA_RORDER_MODE_OUT << ALX_DMA_RORDER_MODE_SHIFT | 10188c2ecf20Sopenharmony_ci ALX_DMA_RREQ_PRI_DATA | 10198c2ecf20Sopenharmony_ci max_payload << ALX_DMA_RREQ_BLEN_SHIFT | 10208c2ecf20Sopenharmony_ci ALX_DMA_WDLY_CNT_DEF << ALX_DMA_WDLY_CNT_SHIFT | 10218c2ecf20Sopenharmony_ci ALX_DMA_RDLY_CNT_DEF << ALX_DMA_RDLY_CNT_SHIFT | 10228c2ecf20Sopenharmony_ci (hw->dma_chnl - 1) << ALX_DMA_RCHNL_SEL_SHIFT; 10238c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_DMA, val); 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci /* default multi-tx-q weights */ 10268c2ecf20Sopenharmony_ci val = ALX_WRR_PRI_RESTRICT_NONE << ALX_WRR_PRI_SHIFT | 10278c2ecf20Sopenharmony_ci 4 << ALX_WRR_PRI0_SHIFT | 10288c2ecf20Sopenharmony_ci 4 << ALX_WRR_PRI1_SHIFT | 10298c2ecf20Sopenharmony_ci 4 << ALX_WRR_PRI2_SHIFT | 10308c2ecf20Sopenharmony_ci 4 << ALX_WRR_PRI3_SHIFT; 10318c2ecf20Sopenharmony_ci alx_write_mem32(hw, ALX_WRR, val); 10328c2ecf20Sopenharmony_ci} 10338c2ecf20Sopenharmony_ci 10348c2ecf20Sopenharmony_civoid alx_mask_msix(struct alx_hw *hw, int index, bool mask) 10358c2ecf20Sopenharmony_ci{ 10368c2ecf20Sopenharmony_ci u32 reg, val; 10378c2ecf20Sopenharmony_ci 10388c2ecf20Sopenharmony_ci reg = ALX_MSIX_ENTRY_BASE + index * PCI_MSIX_ENTRY_SIZE + 10398c2ecf20Sopenharmony_ci PCI_MSIX_ENTRY_VECTOR_CTRL; 10408c2ecf20Sopenharmony_ci 10418c2ecf20Sopenharmony_ci val = mask ? PCI_MSIX_ENTRY_CTRL_MASKBIT : 0; 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_ci alx_write_mem32(hw, reg, val); 10448c2ecf20Sopenharmony_ci alx_post_write(hw); 10458c2ecf20Sopenharmony_ci} 10468c2ecf20Sopenharmony_ci 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_cibool alx_get_phy_info(struct alx_hw *hw) 10498c2ecf20Sopenharmony_ci{ 10508c2ecf20Sopenharmony_ci u16 devs1, devs2; 10518c2ecf20Sopenharmony_ci 10528c2ecf20Sopenharmony_ci if (alx_read_phy_reg(hw, MII_PHYSID1, &hw->phy_id[0]) || 10538c2ecf20Sopenharmony_ci alx_read_phy_reg(hw, MII_PHYSID2, &hw->phy_id[1])) 10548c2ecf20Sopenharmony_ci return false; 10558c2ecf20Sopenharmony_ci 10568c2ecf20Sopenharmony_ci /* since we haven't PMA/PMD status2 register, we can't 10578c2ecf20Sopenharmony_ci * use mdio45_probe function for prtad and mmds. 10588c2ecf20Sopenharmony_ci * use fixed MMD3 to get mmds. 10598c2ecf20Sopenharmony_ci */ 10608c2ecf20Sopenharmony_ci if (alx_read_phy_ext(hw, 3, MDIO_DEVS1, &devs1) || 10618c2ecf20Sopenharmony_ci alx_read_phy_ext(hw, 3, MDIO_DEVS2, &devs2)) 10628c2ecf20Sopenharmony_ci return false; 10638c2ecf20Sopenharmony_ci hw->mdio.mmds = devs1 | devs2 << 16; 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_ci return true; 10668c2ecf20Sopenharmony_ci} 10678c2ecf20Sopenharmony_ci 10688c2ecf20Sopenharmony_civoid alx_update_hw_stats(struct alx_hw *hw) 10698c2ecf20Sopenharmony_ci{ 10708c2ecf20Sopenharmony_ci /* RX stats */ 10718c2ecf20Sopenharmony_ci hw->stats.rx_ok += alx_read_mem32(hw, ALX_MIB_RX_OK); 10728c2ecf20Sopenharmony_ci hw->stats.rx_bcast += alx_read_mem32(hw, ALX_MIB_RX_BCAST); 10738c2ecf20Sopenharmony_ci hw->stats.rx_mcast += alx_read_mem32(hw, ALX_MIB_RX_MCAST); 10748c2ecf20Sopenharmony_ci hw->stats.rx_pause += alx_read_mem32(hw, ALX_MIB_RX_PAUSE); 10758c2ecf20Sopenharmony_ci hw->stats.rx_ctrl += alx_read_mem32(hw, ALX_MIB_RX_CTRL); 10768c2ecf20Sopenharmony_ci hw->stats.rx_fcs_err += alx_read_mem32(hw, ALX_MIB_RX_FCS_ERR); 10778c2ecf20Sopenharmony_ci hw->stats.rx_len_err += alx_read_mem32(hw, ALX_MIB_RX_LEN_ERR); 10788c2ecf20Sopenharmony_ci hw->stats.rx_byte_cnt += alx_read_mem32(hw, ALX_MIB_RX_BYTE_CNT); 10798c2ecf20Sopenharmony_ci hw->stats.rx_runt += alx_read_mem32(hw, ALX_MIB_RX_RUNT); 10808c2ecf20Sopenharmony_ci hw->stats.rx_frag += alx_read_mem32(hw, ALX_MIB_RX_FRAG); 10818c2ecf20Sopenharmony_ci hw->stats.rx_sz_64B += alx_read_mem32(hw, ALX_MIB_RX_SZ_64B); 10828c2ecf20Sopenharmony_ci hw->stats.rx_sz_127B += alx_read_mem32(hw, ALX_MIB_RX_SZ_127B); 10838c2ecf20Sopenharmony_ci hw->stats.rx_sz_255B += alx_read_mem32(hw, ALX_MIB_RX_SZ_255B); 10848c2ecf20Sopenharmony_ci hw->stats.rx_sz_511B += alx_read_mem32(hw, ALX_MIB_RX_SZ_511B); 10858c2ecf20Sopenharmony_ci hw->stats.rx_sz_1023B += alx_read_mem32(hw, ALX_MIB_RX_SZ_1023B); 10868c2ecf20Sopenharmony_ci hw->stats.rx_sz_1518B += alx_read_mem32(hw, ALX_MIB_RX_SZ_1518B); 10878c2ecf20Sopenharmony_ci hw->stats.rx_sz_max += alx_read_mem32(hw, ALX_MIB_RX_SZ_MAX); 10888c2ecf20Sopenharmony_ci hw->stats.rx_ov_sz += alx_read_mem32(hw, ALX_MIB_RX_OV_SZ); 10898c2ecf20Sopenharmony_ci hw->stats.rx_ov_rxf += alx_read_mem32(hw, ALX_MIB_RX_OV_RXF); 10908c2ecf20Sopenharmony_ci hw->stats.rx_ov_rrd += alx_read_mem32(hw, ALX_MIB_RX_OV_RRD); 10918c2ecf20Sopenharmony_ci hw->stats.rx_align_err += alx_read_mem32(hw, ALX_MIB_RX_ALIGN_ERR); 10928c2ecf20Sopenharmony_ci hw->stats.rx_bc_byte_cnt += alx_read_mem32(hw, ALX_MIB_RX_BCCNT); 10938c2ecf20Sopenharmony_ci hw->stats.rx_mc_byte_cnt += alx_read_mem32(hw, ALX_MIB_RX_MCCNT); 10948c2ecf20Sopenharmony_ci hw->stats.rx_err_addr += alx_read_mem32(hw, ALX_MIB_RX_ERRADDR); 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_ci /* TX stats */ 10978c2ecf20Sopenharmony_ci hw->stats.tx_ok += alx_read_mem32(hw, ALX_MIB_TX_OK); 10988c2ecf20Sopenharmony_ci hw->stats.tx_bcast += alx_read_mem32(hw, ALX_MIB_TX_BCAST); 10998c2ecf20Sopenharmony_ci hw->stats.tx_mcast += alx_read_mem32(hw, ALX_MIB_TX_MCAST); 11008c2ecf20Sopenharmony_ci hw->stats.tx_pause += alx_read_mem32(hw, ALX_MIB_TX_PAUSE); 11018c2ecf20Sopenharmony_ci hw->stats.tx_exc_defer += alx_read_mem32(hw, ALX_MIB_TX_EXC_DEFER); 11028c2ecf20Sopenharmony_ci hw->stats.tx_ctrl += alx_read_mem32(hw, ALX_MIB_TX_CTRL); 11038c2ecf20Sopenharmony_ci hw->stats.tx_defer += alx_read_mem32(hw, ALX_MIB_TX_DEFER); 11048c2ecf20Sopenharmony_ci hw->stats.tx_byte_cnt += alx_read_mem32(hw, ALX_MIB_TX_BYTE_CNT); 11058c2ecf20Sopenharmony_ci hw->stats.tx_sz_64B += alx_read_mem32(hw, ALX_MIB_TX_SZ_64B); 11068c2ecf20Sopenharmony_ci hw->stats.tx_sz_127B += alx_read_mem32(hw, ALX_MIB_TX_SZ_127B); 11078c2ecf20Sopenharmony_ci hw->stats.tx_sz_255B += alx_read_mem32(hw, ALX_MIB_TX_SZ_255B); 11088c2ecf20Sopenharmony_ci hw->stats.tx_sz_511B += alx_read_mem32(hw, ALX_MIB_TX_SZ_511B); 11098c2ecf20Sopenharmony_ci hw->stats.tx_sz_1023B += alx_read_mem32(hw, ALX_MIB_TX_SZ_1023B); 11108c2ecf20Sopenharmony_ci hw->stats.tx_sz_1518B += alx_read_mem32(hw, ALX_MIB_TX_SZ_1518B); 11118c2ecf20Sopenharmony_ci hw->stats.tx_sz_max += alx_read_mem32(hw, ALX_MIB_TX_SZ_MAX); 11128c2ecf20Sopenharmony_ci hw->stats.tx_single_col += alx_read_mem32(hw, ALX_MIB_TX_SINGLE_COL); 11138c2ecf20Sopenharmony_ci hw->stats.tx_multi_col += alx_read_mem32(hw, ALX_MIB_TX_MULTI_COL); 11148c2ecf20Sopenharmony_ci hw->stats.tx_late_col += alx_read_mem32(hw, ALX_MIB_TX_LATE_COL); 11158c2ecf20Sopenharmony_ci hw->stats.tx_abort_col += alx_read_mem32(hw, ALX_MIB_TX_ABORT_COL); 11168c2ecf20Sopenharmony_ci hw->stats.tx_underrun += alx_read_mem32(hw, ALX_MIB_TX_UNDERRUN); 11178c2ecf20Sopenharmony_ci hw->stats.tx_trd_eop += alx_read_mem32(hw, ALX_MIB_TX_TRD_EOP); 11188c2ecf20Sopenharmony_ci hw->stats.tx_len_err += alx_read_mem32(hw, ALX_MIB_TX_LEN_ERR); 11198c2ecf20Sopenharmony_ci hw->stats.tx_trunc += alx_read_mem32(hw, ALX_MIB_TX_TRUNC); 11208c2ecf20Sopenharmony_ci hw->stats.tx_bc_byte_cnt += alx_read_mem32(hw, ALX_MIB_TX_BCCNT); 11218c2ecf20Sopenharmony_ci hw->stats.tx_mc_byte_cnt += alx_read_mem32(hw, ALX_MIB_TX_MCCNT); 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_ci hw->stats.update += alx_read_mem32(hw, ALX_MIB_UPDATE); 11248c2ecf20Sopenharmony_ci} 1125