18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * AMD 10Gb Ethernet driver
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * This file is available to you under your choice of the following two
58c2ecf20Sopenharmony_ci * licenses:
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * License 1: GPLv2
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Copyright (c) 2016 Advanced Micro Devices, Inc.
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci * This file is free software; you may copy, redistribute and/or modify
128c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License as published by
138c2ecf20Sopenharmony_ci * the Free Software Foundation, either version 2 of the License, or (at
148c2ecf20Sopenharmony_ci * your option) any later version.
158c2ecf20Sopenharmony_ci *
168c2ecf20Sopenharmony_ci * This file is distributed in the hope that it will be useful, but
178c2ecf20Sopenharmony_ci * WITHOUT ANY WARRANTY; without even the implied warranty of
188c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
198c2ecf20Sopenharmony_ci * General Public License for more details.
208c2ecf20Sopenharmony_ci *
218c2ecf20Sopenharmony_ci * You should have received a copy of the GNU General Public License
228c2ecf20Sopenharmony_ci * along with this program.  If not, see <http://www.gnu.org/licenses/>.
238c2ecf20Sopenharmony_ci *
248c2ecf20Sopenharmony_ci * This file incorporates work covered by the following copyright and
258c2ecf20Sopenharmony_ci * permission notice:
268c2ecf20Sopenharmony_ci *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
278c2ecf20Sopenharmony_ci *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
288c2ecf20Sopenharmony_ci *     Inc. unless otherwise expressly agreed to in writing between Synopsys
298c2ecf20Sopenharmony_ci *     and you.
308c2ecf20Sopenharmony_ci *
318c2ecf20Sopenharmony_ci *     The Software IS NOT an item of Licensed Software or Licensed Product
328c2ecf20Sopenharmony_ci *     under any End User Software License Agreement or Agreement for Licensed
338c2ecf20Sopenharmony_ci *     Product with Synopsys or any supplement thereto.  Permission is hereby
348c2ecf20Sopenharmony_ci *     granted, free of charge, to any person obtaining a copy of this software
358c2ecf20Sopenharmony_ci *     annotated with this license and the Software, to deal in the Software
368c2ecf20Sopenharmony_ci *     without restriction, including without limitation the rights to use,
378c2ecf20Sopenharmony_ci *     copy, modify, merge, publish, distribute, sublicense, and/or sell copies
388c2ecf20Sopenharmony_ci *     of the Software, and to permit persons to whom the Software is furnished
398c2ecf20Sopenharmony_ci *     to do so, subject to the following conditions:
408c2ecf20Sopenharmony_ci *
418c2ecf20Sopenharmony_ci *     The above copyright notice and this permission notice shall be included
428c2ecf20Sopenharmony_ci *     in all copies or substantial portions of the Software.
438c2ecf20Sopenharmony_ci *
448c2ecf20Sopenharmony_ci *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
458c2ecf20Sopenharmony_ci *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
468c2ecf20Sopenharmony_ci *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
478c2ecf20Sopenharmony_ci *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
488c2ecf20Sopenharmony_ci *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
498c2ecf20Sopenharmony_ci *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
508c2ecf20Sopenharmony_ci *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
518c2ecf20Sopenharmony_ci *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
528c2ecf20Sopenharmony_ci *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
538c2ecf20Sopenharmony_ci *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
548c2ecf20Sopenharmony_ci *     THE POSSIBILITY OF SUCH DAMAGE.
558c2ecf20Sopenharmony_ci *
568c2ecf20Sopenharmony_ci *
578c2ecf20Sopenharmony_ci * License 2: Modified BSD
588c2ecf20Sopenharmony_ci *
598c2ecf20Sopenharmony_ci * Copyright (c) 2016 Advanced Micro Devices, Inc.
608c2ecf20Sopenharmony_ci * All rights reserved.
618c2ecf20Sopenharmony_ci *
628c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
638c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions are met:
648c2ecf20Sopenharmony_ci *     * Redistributions of source code must retain the above copyright
658c2ecf20Sopenharmony_ci *       notice, this list of conditions and the following disclaimer.
668c2ecf20Sopenharmony_ci *     * Redistributions in binary form must reproduce the above copyright
678c2ecf20Sopenharmony_ci *       notice, this list of conditions and the following disclaimer in the
688c2ecf20Sopenharmony_ci *       documentation and/or other materials provided with the distribution.
698c2ecf20Sopenharmony_ci *     * Neither the name of Advanced Micro Devices, Inc. nor the
708c2ecf20Sopenharmony_ci *       names of its contributors may be used to endorse or promote products
718c2ecf20Sopenharmony_ci *       derived from this software without specific prior written permission.
728c2ecf20Sopenharmony_ci *
738c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
748c2ecf20Sopenharmony_ci * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
758c2ecf20Sopenharmony_ci * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
768c2ecf20Sopenharmony_ci * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
778c2ecf20Sopenharmony_ci * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
788c2ecf20Sopenharmony_ci * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
798c2ecf20Sopenharmony_ci * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
808c2ecf20Sopenharmony_ci * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
818c2ecf20Sopenharmony_ci * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
828c2ecf20Sopenharmony_ci * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
838c2ecf20Sopenharmony_ci *
848c2ecf20Sopenharmony_ci * This file incorporates work covered by the following copyright and
858c2ecf20Sopenharmony_ci * permission notice:
868c2ecf20Sopenharmony_ci *     The Synopsys DWC ETHER XGMAC Software Driver and documentation
878c2ecf20Sopenharmony_ci *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,
888c2ecf20Sopenharmony_ci *     Inc. unless otherwise expressly agreed to in writing between Synopsys
898c2ecf20Sopenharmony_ci *     and you.
908c2ecf20Sopenharmony_ci *
918c2ecf20Sopenharmony_ci *     The Software IS NOT an item of Licensed Software or Licensed Product
928c2ecf20Sopenharmony_ci *     under any End User Software License Agreement or Agreement for Licensed
938c2ecf20Sopenharmony_ci *     Product with Synopsys or any supplement thereto.  Permission is hereby
948c2ecf20Sopenharmony_ci *     granted, free of charge, to any person obtaining a copy of this software
958c2ecf20Sopenharmony_ci *     annotated with this license and the Software, to deal in the Software
968c2ecf20Sopenharmony_ci *     without restriction, including without limitation the rights to use,
978c2ecf20Sopenharmony_ci *     copy, modify, merge, publish, distribute, sublicense, and/or sell copies
988c2ecf20Sopenharmony_ci *     of the Software, and to permit persons to whom the Software is furnished
998c2ecf20Sopenharmony_ci *     to do so, subject to the following conditions:
1008c2ecf20Sopenharmony_ci *
1018c2ecf20Sopenharmony_ci *     The above copyright notice and this permission notice shall be included
1028c2ecf20Sopenharmony_ci *     in all copies or substantial portions of the Software.
1038c2ecf20Sopenharmony_ci *
1048c2ecf20Sopenharmony_ci *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"
1058c2ecf20Sopenharmony_ci *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
1068c2ecf20Sopenharmony_ci *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
1078c2ecf20Sopenharmony_ci *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS
1088c2ecf20Sopenharmony_ci *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1098c2ecf20Sopenharmony_ci *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1108c2ecf20Sopenharmony_ci *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
1118c2ecf20Sopenharmony_ci *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
1128c2ecf20Sopenharmony_ci *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1138c2ecf20Sopenharmony_ci *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
1148c2ecf20Sopenharmony_ci *     THE POSSIBILITY OF SUCH DAMAGE.
1158c2ecf20Sopenharmony_ci */
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci#include <linux/module.h>
1188c2ecf20Sopenharmony_ci#include <linux/kmod.h>
1198c2ecf20Sopenharmony_ci#include <linux/device.h>
1208c2ecf20Sopenharmony_ci#include <linux/property.h>
1218c2ecf20Sopenharmony_ci#include <linux/mdio.h>
1228c2ecf20Sopenharmony_ci#include <linux/phy.h>
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci#include "xgbe.h"
1258c2ecf20Sopenharmony_ci#include "xgbe-common.h"
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_ci#define XGBE_BLWC_PROPERTY		"amd,serdes-blwc"
1288c2ecf20Sopenharmony_ci#define XGBE_CDR_RATE_PROPERTY		"amd,serdes-cdr-rate"
1298c2ecf20Sopenharmony_ci#define XGBE_PQ_SKEW_PROPERTY		"amd,serdes-pq-skew"
1308c2ecf20Sopenharmony_ci#define XGBE_TX_AMP_PROPERTY		"amd,serdes-tx-amp"
1318c2ecf20Sopenharmony_ci#define XGBE_DFE_CFG_PROPERTY		"amd,serdes-dfe-tap-config"
1328c2ecf20Sopenharmony_ci#define XGBE_DFE_ENA_PROPERTY		"amd,serdes-dfe-tap-enable"
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci/* Default SerDes settings */
1358c2ecf20Sopenharmony_ci#define XGBE_SPEED_1000_BLWC		1
1368c2ecf20Sopenharmony_ci#define XGBE_SPEED_1000_CDR		0x2
1378c2ecf20Sopenharmony_ci#define XGBE_SPEED_1000_PLL		0x0
1388c2ecf20Sopenharmony_ci#define XGBE_SPEED_1000_PQ		0xa
1398c2ecf20Sopenharmony_ci#define XGBE_SPEED_1000_RATE		0x3
1408c2ecf20Sopenharmony_ci#define XGBE_SPEED_1000_TXAMP		0xf
1418c2ecf20Sopenharmony_ci#define XGBE_SPEED_1000_WORD		0x1
1428c2ecf20Sopenharmony_ci#define XGBE_SPEED_1000_DFE_TAP_CONFIG	0x3
1438c2ecf20Sopenharmony_ci#define XGBE_SPEED_1000_DFE_TAP_ENABLE	0x0
1448c2ecf20Sopenharmony_ci
1458c2ecf20Sopenharmony_ci#define XGBE_SPEED_2500_BLWC		1
1468c2ecf20Sopenharmony_ci#define XGBE_SPEED_2500_CDR		0x2
1478c2ecf20Sopenharmony_ci#define XGBE_SPEED_2500_PLL		0x0
1488c2ecf20Sopenharmony_ci#define XGBE_SPEED_2500_PQ		0xa
1498c2ecf20Sopenharmony_ci#define XGBE_SPEED_2500_RATE		0x1
1508c2ecf20Sopenharmony_ci#define XGBE_SPEED_2500_TXAMP		0xf
1518c2ecf20Sopenharmony_ci#define XGBE_SPEED_2500_WORD		0x1
1528c2ecf20Sopenharmony_ci#define XGBE_SPEED_2500_DFE_TAP_CONFIG	0x3
1538c2ecf20Sopenharmony_ci#define XGBE_SPEED_2500_DFE_TAP_ENABLE	0x0
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci#define XGBE_SPEED_10000_BLWC		0
1568c2ecf20Sopenharmony_ci#define XGBE_SPEED_10000_CDR		0x7
1578c2ecf20Sopenharmony_ci#define XGBE_SPEED_10000_PLL		0x1
1588c2ecf20Sopenharmony_ci#define XGBE_SPEED_10000_PQ		0x12
1598c2ecf20Sopenharmony_ci#define XGBE_SPEED_10000_RATE		0x0
1608c2ecf20Sopenharmony_ci#define XGBE_SPEED_10000_TXAMP		0xa
1618c2ecf20Sopenharmony_ci#define XGBE_SPEED_10000_WORD		0x7
1628c2ecf20Sopenharmony_ci#define XGBE_SPEED_10000_DFE_TAP_CONFIG	0x1
1638c2ecf20Sopenharmony_ci#define XGBE_SPEED_10000_DFE_TAP_ENABLE	0x7f
1648c2ecf20Sopenharmony_ci
1658c2ecf20Sopenharmony_ci/* Rate-change complete wait/retry count */
1668c2ecf20Sopenharmony_ci#define XGBE_RATECHANGE_COUNT		500
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_cistatic const u32 xgbe_phy_blwc[] = {
1698c2ecf20Sopenharmony_ci	XGBE_SPEED_1000_BLWC,
1708c2ecf20Sopenharmony_ci	XGBE_SPEED_2500_BLWC,
1718c2ecf20Sopenharmony_ci	XGBE_SPEED_10000_BLWC,
1728c2ecf20Sopenharmony_ci};
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_cistatic const u32 xgbe_phy_cdr_rate[] = {
1758c2ecf20Sopenharmony_ci	XGBE_SPEED_1000_CDR,
1768c2ecf20Sopenharmony_ci	XGBE_SPEED_2500_CDR,
1778c2ecf20Sopenharmony_ci	XGBE_SPEED_10000_CDR,
1788c2ecf20Sopenharmony_ci};
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_cistatic const u32 xgbe_phy_pq_skew[] = {
1818c2ecf20Sopenharmony_ci	XGBE_SPEED_1000_PQ,
1828c2ecf20Sopenharmony_ci	XGBE_SPEED_2500_PQ,
1838c2ecf20Sopenharmony_ci	XGBE_SPEED_10000_PQ,
1848c2ecf20Sopenharmony_ci};
1858c2ecf20Sopenharmony_ci
1868c2ecf20Sopenharmony_cistatic const u32 xgbe_phy_tx_amp[] = {
1878c2ecf20Sopenharmony_ci	XGBE_SPEED_1000_TXAMP,
1888c2ecf20Sopenharmony_ci	XGBE_SPEED_2500_TXAMP,
1898c2ecf20Sopenharmony_ci	XGBE_SPEED_10000_TXAMP,
1908c2ecf20Sopenharmony_ci};
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_cistatic const u32 xgbe_phy_dfe_tap_cfg[] = {
1938c2ecf20Sopenharmony_ci	XGBE_SPEED_1000_DFE_TAP_CONFIG,
1948c2ecf20Sopenharmony_ci	XGBE_SPEED_2500_DFE_TAP_CONFIG,
1958c2ecf20Sopenharmony_ci	XGBE_SPEED_10000_DFE_TAP_CONFIG,
1968c2ecf20Sopenharmony_ci};
1978c2ecf20Sopenharmony_ci
1988c2ecf20Sopenharmony_cistatic const u32 xgbe_phy_dfe_tap_ena[] = {
1998c2ecf20Sopenharmony_ci	XGBE_SPEED_1000_DFE_TAP_ENABLE,
2008c2ecf20Sopenharmony_ci	XGBE_SPEED_2500_DFE_TAP_ENABLE,
2018c2ecf20Sopenharmony_ci	XGBE_SPEED_10000_DFE_TAP_ENABLE,
2028c2ecf20Sopenharmony_ci};
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_cistruct xgbe_phy_data {
2058c2ecf20Sopenharmony_ci	/* 1000/10000 vs 2500/10000 indicator */
2068c2ecf20Sopenharmony_ci	unsigned int speed_set;
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_ci	/* SerDes UEFI configurable settings.
2098c2ecf20Sopenharmony_ci	 *   Switching between modes/speeds requires new values for some
2108c2ecf20Sopenharmony_ci	 *   SerDes settings.  The values can be supplied as device
2118c2ecf20Sopenharmony_ci	 *   properties in array format.  The first array entry is for
2128c2ecf20Sopenharmony_ci	 *   1GbE, second for 2.5GbE and third for 10GbE
2138c2ecf20Sopenharmony_ci	 */
2148c2ecf20Sopenharmony_ci	u32 blwc[XGBE_SPEEDS];
2158c2ecf20Sopenharmony_ci	u32 cdr_rate[XGBE_SPEEDS];
2168c2ecf20Sopenharmony_ci	u32 pq_skew[XGBE_SPEEDS];
2178c2ecf20Sopenharmony_ci	u32 tx_amp[XGBE_SPEEDS];
2188c2ecf20Sopenharmony_ci	u32 dfe_tap_cfg[XGBE_SPEEDS];
2198c2ecf20Sopenharmony_ci	u32 dfe_tap_ena[XGBE_SPEEDS];
2208c2ecf20Sopenharmony_ci};
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_cistatic void xgbe_phy_kr_training_pre(struct xgbe_prv_data *pdata)
2238c2ecf20Sopenharmony_ci{
2248c2ecf20Sopenharmony_ci		XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 1);
2258c2ecf20Sopenharmony_ci}
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_cistatic void xgbe_phy_kr_training_post(struct xgbe_prv_data *pdata)
2288c2ecf20Sopenharmony_ci{
2298c2ecf20Sopenharmony_ci		XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 0);
2308c2ecf20Sopenharmony_ci}
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_cistatic enum xgbe_mode xgbe_phy_an_outcome(struct xgbe_prv_data *pdata)
2338c2ecf20Sopenharmony_ci{
2348c2ecf20Sopenharmony_ci	struct ethtool_link_ksettings *lks = &pdata->phy.lks;
2358c2ecf20Sopenharmony_ci	struct xgbe_phy_data *phy_data = pdata->phy_data;
2368c2ecf20Sopenharmony_ci	enum xgbe_mode mode;
2378c2ecf20Sopenharmony_ci	unsigned int ad_reg, lp_reg;
2388c2ecf20Sopenharmony_ci
2398c2ecf20Sopenharmony_ci	XGBE_SET_LP_ADV(lks, Autoneg);
2408c2ecf20Sopenharmony_ci	XGBE_SET_LP_ADV(lks, Backplane);
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci	/* Compare Advertisement and Link Partner register 1 */
2438c2ecf20Sopenharmony_ci	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
2448c2ecf20Sopenharmony_ci	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);
2458c2ecf20Sopenharmony_ci	if (lp_reg & 0x400)
2468c2ecf20Sopenharmony_ci		XGBE_SET_LP_ADV(lks, Pause);
2478c2ecf20Sopenharmony_ci	if (lp_reg & 0x800)
2488c2ecf20Sopenharmony_ci		XGBE_SET_LP_ADV(lks, Asym_Pause);
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ci	if (pdata->phy.pause_autoneg) {
2518c2ecf20Sopenharmony_ci		/* Set flow control based on auto-negotiation result */
2528c2ecf20Sopenharmony_ci		pdata->phy.tx_pause = 0;
2538c2ecf20Sopenharmony_ci		pdata->phy.rx_pause = 0;
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci		if (ad_reg & lp_reg & 0x400) {
2568c2ecf20Sopenharmony_ci			pdata->phy.tx_pause = 1;
2578c2ecf20Sopenharmony_ci			pdata->phy.rx_pause = 1;
2588c2ecf20Sopenharmony_ci		} else if (ad_reg & lp_reg & 0x800) {
2598c2ecf20Sopenharmony_ci			if (ad_reg & 0x400)
2608c2ecf20Sopenharmony_ci				pdata->phy.rx_pause = 1;
2618c2ecf20Sopenharmony_ci			else if (lp_reg & 0x400)
2628c2ecf20Sopenharmony_ci				pdata->phy.tx_pause = 1;
2638c2ecf20Sopenharmony_ci		}
2648c2ecf20Sopenharmony_ci	}
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	/* Compare Advertisement and Link Partner register 2 */
2678c2ecf20Sopenharmony_ci	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
2688c2ecf20Sopenharmony_ci	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
2698c2ecf20Sopenharmony_ci	if (lp_reg & 0x80)
2708c2ecf20Sopenharmony_ci		XGBE_SET_LP_ADV(lks, 10000baseKR_Full);
2718c2ecf20Sopenharmony_ci	if (lp_reg & 0x20) {
2728c2ecf20Sopenharmony_ci		if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
2738c2ecf20Sopenharmony_ci			XGBE_SET_LP_ADV(lks, 2500baseX_Full);
2748c2ecf20Sopenharmony_ci		else
2758c2ecf20Sopenharmony_ci			XGBE_SET_LP_ADV(lks, 1000baseKX_Full);
2768c2ecf20Sopenharmony_ci	}
2778c2ecf20Sopenharmony_ci
2788c2ecf20Sopenharmony_ci	ad_reg &= lp_reg;
2798c2ecf20Sopenharmony_ci	if (ad_reg & 0x80) {
2808c2ecf20Sopenharmony_ci		mode = XGBE_MODE_KR;
2818c2ecf20Sopenharmony_ci	} else if (ad_reg & 0x20) {
2828c2ecf20Sopenharmony_ci		if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
2838c2ecf20Sopenharmony_ci			mode = XGBE_MODE_KX_2500;
2848c2ecf20Sopenharmony_ci		else
2858c2ecf20Sopenharmony_ci			mode = XGBE_MODE_KX_1000;
2868c2ecf20Sopenharmony_ci	} else {
2878c2ecf20Sopenharmony_ci		mode = XGBE_MODE_UNKNOWN;
2888c2ecf20Sopenharmony_ci	}
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ci	/* Compare Advertisement and Link Partner register 3 */
2918c2ecf20Sopenharmony_ci	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
2928c2ecf20Sopenharmony_ci	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
2938c2ecf20Sopenharmony_ci	if (lp_reg & 0xc000)
2948c2ecf20Sopenharmony_ci		XGBE_SET_LP_ADV(lks, 10000baseR_FEC);
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	return mode;
2978c2ecf20Sopenharmony_ci}
2988c2ecf20Sopenharmony_ci
2998c2ecf20Sopenharmony_cistatic void xgbe_phy_an_advertising(struct xgbe_prv_data *pdata,
3008c2ecf20Sopenharmony_ci				    struct ethtool_link_ksettings *dlks)
3018c2ecf20Sopenharmony_ci{
3028c2ecf20Sopenharmony_ci	struct ethtool_link_ksettings *slks = &pdata->phy.lks;
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci	XGBE_LM_COPY(dlks, advertising, slks, advertising);
3058c2ecf20Sopenharmony_ci}
3068c2ecf20Sopenharmony_ci
3078c2ecf20Sopenharmony_cistatic int xgbe_phy_an_config(struct xgbe_prv_data *pdata)
3088c2ecf20Sopenharmony_ci{
3098c2ecf20Sopenharmony_ci	/* Nothing uniquely required for an configuration */
3108c2ecf20Sopenharmony_ci	return 0;
3118c2ecf20Sopenharmony_ci}
3128c2ecf20Sopenharmony_ci
3138c2ecf20Sopenharmony_cistatic enum xgbe_an_mode xgbe_phy_an_mode(struct xgbe_prv_data *pdata)
3148c2ecf20Sopenharmony_ci{
3158c2ecf20Sopenharmony_ci	return XGBE_AN_MODE_CL73;
3168c2ecf20Sopenharmony_ci}
3178c2ecf20Sopenharmony_ci
3188c2ecf20Sopenharmony_cistatic void xgbe_phy_pcs_power_cycle(struct xgbe_prv_data *pdata)
3198c2ecf20Sopenharmony_ci{
3208c2ecf20Sopenharmony_ci	unsigned int reg;
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	reg |= MDIO_CTRL1_LPOWER;
3258c2ecf20Sopenharmony_ci	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci	usleep_range(75, 100);
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	reg &= ~MDIO_CTRL1_LPOWER;
3308c2ecf20Sopenharmony_ci	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
3318c2ecf20Sopenharmony_ci}
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_cistatic void xgbe_phy_start_ratechange(struct xgbe_prv_data *pdata)
3348c2ecf20Sopenharmony_ci{
3358c2ecf20Sopenharmony_ci	/* Assert Rx and Tx ratechange */
3368c2ecf20Sopenharmony_ci	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 1);
3378c2ecf20Sopenharmony_ci}
3388c2ecf20Sopenharmony_ci
3398c2ecf20Sopenharmony_cistatic void xgbe_phy_complete_ratechange(struct xgbe_prv_data *pdata)
3408c2ecf20Sopenharmony_ci{
3418c2ecf20Sopenharmony_ci	unsigned int wait;
3428c2ecf20Sopenharmony_ci	u16 status;
3438c2ecf20Sopenharmony_ci
3448c2ecf20Sopenharmony_ci	/* Release Rx and Tx ratechange */
3458c2ecf20Sopenharmony_ci	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 0);
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	/* Wait for Rx and Tx ready */
3488c2ecf20Sopenharmony_ci	wait = XGBE_RATECHANGE_COUNT;
3498c2ecf20Sopenharmony_ci	while (wait--) {
3508c2ecf20Sopenharmony_ci		usleep_range(50, 75);
3518c2ecf20Sopenharmony_ci
3528c2ecf20Sopenharmony_ci		status = XSIR0_IOREAD(pdata, SIR0_STATUS);
3538c2ecf20Sopenharmony_ci		if (XSIR_GET_BITS(status, SIR0_STATUS, RX_READY) &&
3548c2ecf20Sopenharmony_ci		    XSIR_GET_BITS(status, SIR0_STATUS, TX_READY))
3558c2ecf20Sopenharmony_ci			goto rx_reset;
3568c2ecf20Sopenharmony_ci	}
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	netif_dbg(pdata, link, pdata->netdev, "SerDes rx/tx not ready (%#hx)\n",
3598c2ecf20Sopenharmony_ci		  status);
3608c2ecf20Sopenharmony_ci
3618c2ecf20Sopenharmony_cirx_reset:
3628c2ecf20Sopenharmony_ci	/* Perform Rx reset for the DFE changes */
3638c2ecf20Sopenharmony_ci	XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 0);
3648c2ecf20Sopenharmony_ci	XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 1);
3658c2ecf20Sopenharmony_ci}
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_cistatic void xgbe_phy_kr_mode(struct xgbe_prv_data *pdata)
3688c2ecf20Sopenharmony_ci{
3698c2ecf20Sopenharmony_ci	struct xgbe_phy_data *phy_data = pdata->phy_data;
3708c2ecf20Sopenharmony_ci	unsigned int reg;
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	/* Set PCS to KR/10G speed */
3738c2ecf20Sopenharmony_ci	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
3748c2ecf20Sopenharmony_ci	reg &= ~MDIO_PCS_CTRL2_TYPE;
3758c2ecf20Sopenharmony_ci	reg |= MDIO_PCS_CTRL2_10GBR;
3768c2ecf20Sopenharmony_ci	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
3778c2ecf20Sopenharmony_ci
3788c2ecf20Sopenharmony_ci	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
3798c2ecf20Sopenharmony_ci	reg &= ~MDIO_CTRL1_SPEEDSEL;
3808c2ecf20Sopenharmony_ci	reg |= MDIO_CTRL1_SPEED10G;
3818c2ecf20Sopenharmony_ci	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
3828c2ecf20Sopenharmony_ci
3838c2ecf20Sopenharmony_ci	xgbe_phy_pcs_power_cycle(pdata);
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	/* Set SerDes to 10G speed */
3868c2ecf20Sopenharmony_ci	xgbe_phy_start_ratechange(pdata);
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_10000_RATE);
3898c2ecf20Sopenharmony_ci	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_10000_WORD);
3908c2ecf20Sopenharmony_ci	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_10000_PLL);
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_ci	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
3938c2ecf20Sopenharmony_ci			   phy_data->cdr_rate[XGBE_SPEED_10000]);
3948c2ecf20Sopenharmony_ci	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
3958c2ecf20Sopenharmony_ci			   phy_data->tx_amp[XGBE_SPEED_10000]);
3968c2ecf20Sopenharmony_ci	XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
3978c2ecf20Sopenharmony_ci			   phy_data->blwc[XGBE_SPEED_10000]);
3988c2ecf20Sopenharmony_ci	XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
3998c2ecf20Sopenharmony_ci			   phy_data->pq_skew[XGBE_SPEED_10000]);
4008c2ecf20Sopenharmony_ci	XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
4018c2ecf20Sopenharmony_ci			   phy_data->dfe_tap_cfg[XGBE_SPEED_10000]);
4028c2ecf20Sopenharmony_ci	XRXTX_IOWRITE(pdata, RXTX_REG22,
4038c2ecf20Sopenharmony_ci		      phy_data->dfe_tap_ena[XGBE_SPEED_10000]);
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_ci	xgbe_phy_complete_ratechange(pdata);
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	netif_dbg(pdata, link, pdata->netdev, "10GbE KR mode set\n");
4088c2ecf20Sopenharmony_ci}
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_cistatic void xgbe_phy_kx_2500_mode(struct xgbe_prv_data *pdata)
4118c2ecf20Sopenharmony_ci{
4128c2ecf20Sopenharmony_ci	struct xgbe_phy_data *phy_data = pdata->phy_data;
4138c2ecf20Sopenharmony_ci	unsigned int reg;
4148c2ecf20Sopenharmony_ci
4158c2ecf20Sopenharmony_ci	/* Set PCS to KX/1G speed */
4168c2ecf20Sopenharmony_ci	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
4178c2ecf20Sopenharmony_ci	reg &= ~MDIO_PCS_CTRL2_TYPE;
4188c2ecf20Sopenharmony_ci	reg |= MDIO_PCS_CTRL2_10GBX;
4198c2ecf20Sopenharmony_ci	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
4228c2ecf20Sopenharmony_ci	reg &= ~MDIO_CTRL1_SPEEDSEL;
4238c2ecf20Sopenharmony_ci	reg |= MDIO_CTRL1_SPEED1G;
4248c2ecf20Sopenharmony_ci	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_ci	xgbe_phy_pcs_power_cycle(pdata);
4278c2ecf20Sopenharmony_ci
4288c2ecf20Sopenharmony_ci	/* Set SerDes to 2.5G speed */
4298c2ecf20Sopenharmony_ci	xgbe_phy_start_ratechange(pdata);
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_ci	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_2500_RATE);
4328c2ecf20Sopenharmony_ci	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_2500_WORD);
4338c2ecf20Sopenharmony_ci	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_2500_PLL);
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_ci	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
4368c2ecf20Sopenharmony_ci			   phy_data->cdr_rate[XGBE_SPEED_2500]);
4378c2ecf20Sopenharmony_ci	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
4388c2ecf20Sopenharmony_ci			   phy_data->tx_amp[XGBE_SPEED_2500]);
4398c2ecf20Sopenharmony_ci	XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
4408c2ecf20Sopenharmony_ci			   phy_data->blwc[XGBE_SPEED_2500]);
4418c2ecf20Sopenharmony_ci	XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
4428c2ecf20Sopenharmony_ci			   phy_data->pq_skew[XGBE_SPEED_2500]);
4438c2ecf20Sopenharmony_ci	XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
4448c2ecf20Sopenharmony_ci			   phy_data->dfe_tap_cfg[XGBE_SPEED_2500]);
4458c2ecf20Sopenharmony_ci	XRXTX_IOWRITE(pdata, RXTX_REG22,
4468c2ecf20Sopenharmony_ci		      phy_data->dfe_tap_ena[XGBE_SPEED_2500]);
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci	xgbe_phy_complete_ratechange(pdata);
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci	netif_dbg(pdata, link, pdata->netdev, "2.5GbE KX mode set\n");
4518c2ecf20Sopenharmony_ci}
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_cistatic void xgbe_phy_kx_1000_mode(struct xgbe_prv_data *pdata)
4548c2ecf20Sopenharmony_ci{
4558c2ecf20Sopenharmony_ci	struct xgbe_phy_data *phy_data = pdata->phy_data;
4568c2ecf20Sopenharmony_ci	unsigned int reg;
4578c2ecf20Sopenharmony_ci
4588c2ecf20Sopenharmony_ci	/* Set PCS to KX/1G speed */
4598c2ecf20Sopenharmony_ci	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
4608c2ecf20Sopenharmony_ci	reg &= ~MDIO_PCS_CTRL2_TYPE;
4618c2ecf20Sopenharmony_ci	reg |= MDIO_PCS_CTRL2_10GBX;
4628c2ecf20Sopenharmony_ci	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
4638c2ecf20Sopenharmony_ci
4648c2ecf20Sopenharmony_ci	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
4658c2ecf20Sopenharmony_ci	reg &= ~MDIO_CTRL1_SPEEDSEL;
4668c2ecf20Sopenharmony_ci	reg |= MDIO_CTRL1_SPEED1G;
4678c2ecf20Sopenharmony_ci	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
4688c2ecf20Sopenharmony_ci
4698c2ecf20Sopenharmony_ci	xgbe_phy_pcs_power_cycle(pdata);
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	/* Set SerDes to 1G speed */
4728c2ecf20Sopenharmony_ci	xgbe_phy_start_ratechange(pdata);
4738c2ecf20Sopenharmony_ci
4748c2ecf20Sopenharmony_ci	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_1000_RATE);
4758c2ecf20Sopenharmony_ci	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_1000_WORD);
4768c2ecf20Sopenharmony_ci	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_1000_PLL);
4778c2ecf20Sopenharmony_ci
4788c2ecf20Sopenharmony_ci	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
4798c2ecf20Sopenharmony_ci			   phy_data->cdr_rate[XGBE_SPEED_1000]);
4808c2ecf20Sopenharmony_ci	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
4818c2ecf20Sopenharmony_ci			   phy_data->tx_amp[XGBE_SPEED_1000]);
4828c2ecf20Sopenharmony_ci	XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
4838c2ecf20Sopenharmony_ci			   phy_data->blwc[XGBE_SPEED_1000]);
4848c2ecf20Sopenharmony_ci	XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
4858c2ecf20Sopenharmony_ci			   phy_data->pq_skew[XGBE_SPEED_1000]);
4868c2ecf20Sopenharmony_ci	XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
4878c2ecf20Sopenharmony_ci			   phy_data->dfe_tap_cfg[XGBE_SPEED_1000]);
4888c2ecf20Sopenharmony_ci	XRXTX_IOWRITE(pdata, RXTX_REG22,
4898c2ecf20Sopenharmony_ci		      phy_data->dfe_tap_ena[XGBE_SPEED_1000]);
4908c2ecf20Sopenharmony_ci
4918c2ecf20Sopenharmony_ci	xgbe_phy_complete_ratechange(pdata);
4928c2ecf20Sopenharmony_ci
4938c2ecf20Sopenharmony_ci	netif_dbg(pdata, link, pdata->netdev, "1GbE KX mode set\n");
4948c2ecf20Sopenharmony_ci}
4958c2ecf20Sopenharmony_ci
4968c2ecf20Sopenharmony_cistatic enum xgbe_mode xgbe_phy_cur_mode(struct xgbe_prv_data *pdata)
4978c2ecf20Sopenharmony_ci{
4988c2ecf20Sopenharmony_ci	struct xgbe_phy_data *phy_data = pdata->phy_data;
4998c2ecf20Sopenharmony_ci	enum xgbe_mode mode;
5008c2ecf20Sopenharmony_ci	unsigned int reg;
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
5038c2ecf20Sopenharmony_ci	reg &= MDIO_PCS_CTRL2_TYPE;
5048c2ecf20Sopenharmony_ci
5058c2ecf20Sopenharmony_ci	if (reg == MDIO_PCS_CTRL2_10GBR) {
5068c2ecf20Sopenharmony_ci		mode = XGBE_MODE_KR;
5078c2ecf20Sopenharmony_ci	} else {
5088c2ecf20Sopenharmony_ci		if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
5098c2ecf20Sopenharmony_ci			mode = XGBE_MODE_KX_2500;
5108c2ecf20Sopenharmony_ci		else
5118c2ecf20Sopenharmony_ci			mode = XGBE_MODE_KX_1000;
5128c2ecf20Sopenharmony_ci	}
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci	return mode;
5158c2ecf20Sopenharmony_ci}
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_cistatic enum xgbe_mode xgbe_phy_switch_mode(struct xgbe_prv_data *pdata)
5188c2ecf20Sopenharmony_ci{
5198c2ecf20Sopenharmony_ci	struct xgbe_phy_data *phy_data = pdata->phy_data;
5208c2ecf20Sopenharmony_ci	enum xgbe_mode mode;
5218c2ecf20Sopenharmony_ci
5228c2ecf20Sopenharmony_ci	/* If we are in KR switch to KX, and vice-versa */
5238c2ecf20Sopenharmony_ci	if (xgbe_phy_cur_mode(pdata) == XGBE_MODE_KR) {
5248c2ecf20Sopenharmony_ci		if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
5258c2ecf20Sopenharmony_ci			mode = XGBE_MODE_KX_2500;
5268c2ecf20Sopenharmony_ci		else
5278c2ecf20Sopenharmony_ci			mode = XGBE_MODE_KX_1000;
5288c2ecf20Sopenharmony_ci	} else {
5298c2ecf20Sopenharmony_ci		mode = XGBE_MODE_KR;
5308c2ecf20Sopenharmony_ci	}
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ci	return mode;
5338c2ecf20Sopenharmony_ci}
5348c2ecf20Sopenharmony_ci
5358c2ecf20Sopenharmony_cistatic enum xgbe_mode xgbe_phy_get_mode(struct xgbe_prv_data *pdata,
5368c2ecf20Sopenharmony_ci					int speed)
5378c2ecf20Sopenharmony_ci{
5388c2ecf20Sopenharmony_ci	struct xgbe_phy_data *phy_data = pdata->phy_data;
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci	switch (speed) {
5418c2ecf20Sopenharmony_ci	case SPEED_1000:
5428c2ecf20Sopenharmony_ci		return (phy_data->speed_set == XGBE_SPEEDSET_1000_10000)
5438c2ecf20Sopenharmony_ci			? XGBE_MODE_KX_1000 : XGBE_MODE_UNKNOWN;
5448c2ecf20Sopenharmony_ci	case SPEED_2500:
5458c2ecf20Sopenharmony_ci		return (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
5468c2ecf20Sopenharmony_ci			? XGBE_MODE_KX_2500 : XGBE_MODE_UNKNOWN;
5478c2ecf20Sopenharmony_ci	case SPEED_10000:
5488c2ecf20Sopenharmony_ci		return XGBE_MODE_KR;
5498c2ecf20Sopenharmony_ci	default:
5508c2ecf20Sopenharmony_ci		return XGBE_MODE_UNKNOWN;
5518c2ecf20Sopenharmony_ci	}
5528c2ecf20Sopenharmony_ci}
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_cistatic void xgbe_phy_set_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
5558c2ecf20Sopenharmony_ci{
5568c2ecf20Sopenharmony_ci	switch (mode) {
5578c2ecf20Sopenharmony_ci	case XGBE_MODE_KX_1000:
5588c2ecf20Sopenharmony_ci		xgbe_phy_kx_1000_mode(pdata);
5598c2ecf20Sopenharmony_ci		break;
5608c2ecf20Sopenharmony_ci	case XGBE_MODE_KX_2500:
5618c2ecf20Sopenharmony_ci		xgbe_phy_kx_2500_mode(pdata);
5628c2ecf20Sopenharmony_ci		break;
5638c2ecf20Sopenharmony_ci	case XGBE_MODE_KR:
5648c2ecf20Sopenharmony_ci		xgbe_phy_kr_mode(pdata);
5658c2ecf20Sopenharmony_ci		break;
5668c2ecf20Sopenharmony_ci	default:
5678c2ecf20Sopenharmony_ci		break;
5688c2ecf20Sopenharmony_ci	}
5698c2ecf20Sopenharmony_ci}
5708c2ecf20Sopenharmony_ci
5718c2ecf20Sopenharmony_cistatic bool xgbe_phy_check_mode(struct xgbe_prv_data *pdata,
5728c2ecf20Sopenharmony_ci				enum xgbe_mode mode, bool advert)
5738c2ecf20Sopenharmony_ci{
5748c2ecf20Sopenharmony_ci	if (pdata->phy.autoneg == AUTONEG_ENABLE) {
5758c2ecf20Sopenharmony_ci		return advert;
5768c2ecf20Sopenharmony_ci	} else {
5778c2ecf20Sopenharmony_ci		enum xgbe_mode cur_mode;
5788c2ecf20Sopenharmony_ci
5798c2ecf20Sopenharmony_ci		cur_mode = xgbe_phy_get_mode(pdata, pdata->phy.speed);
5808c2ecf20Sopenharmony_ci		if (cur_mode == mode)
5818c2ecf20Sopenharmony_ci			return true;
5828c2ecf20Sopenharmony_ci	}
5838c2ecf20Sopenharmony_ci
5848c2ecf20Sopenharmony_ci	return false;
5858c2ecf20Sopenharmony_ci}
5868c2ecf20Sopenharmony_ci
5878c2ecf20Sopenharmony_cistatic bool xgbe_phy_use_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
5888c2ecf20Sopenharmony_ci{
5898c2ecf20Sopenharmony_ci	struct ethtool_link_ksettings *lks = &pdata->phy.lks;
5908c2ecf20Sopenharmony_ci
5918c2ecf20Sopenharmony_ci	switch (mode) {
5928c2ecf20Sopenharmony_ci	case XGBE_MODE_KX_1000:
5938c2ecf20Sopenharmony_ci		return xgbe_phy_check_mode(pdata, mode,
5948c2ecf20Sopenharmony_ci					   XGBE_ADV(lks, 1000baseKX_Full));
5958c2ecf20Sopenharmony_ci	case XGBE_MODE_KX_2500:
5968c2ecf20Sopenharmony_ci		return xgbe_phy_check_mode(pdata, mode,
5978c2ecf20Sopenharmony_ci					   XGBE_ADV(lks, 2500baseX_Full));
5988c2ecf20Sopenharmony_ci	case XGBE_MODE_KR:
5998c2ecf20Sopenharmony_ci		return xgbe_phy_check_mode(pdata, mode,
6008c2ecf20Sopenharmony_ci					   XGBE_ADV(lks, 10000baseKR_Full));
6018c2ecf20Sopenharmony_ci	default:
6028c2ecf20Sopenharmony_ci		return false;
6038c2ecf20Sopenharmony_ci	}
6048c2ecf20Sopenharmony_ci}
6058c2ecf20Sopenharmony_ci
6068c2ecf20Sopenharmony_cistatic bool xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed)
6078c2ecf20Sopenharmony_ci{
6088c2ecf20Sopenharmony_ci	struct xgbe_phy_data *phy_data = pdata->phy_data;
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci	switch (speed) {
6118c2ecf20Sopenharmony_ci	case SPEED_1000:
6128c2ecf20Sopenharmony_ci		if (phy_data->speed_set != XGBE_SPEEDSET_1000_10000)
6138c2ecf20Sopenharmony_ci			return false;
6148c2ecf20Sopenharmony_ci		return true;
6158c2ecf20Sopenharmony_ci	case SPEED_2500:
6168c2ecf20Sopenharmony_ci		if (phy_data->speed_set != XGBE_SPEEDSET_2500_10000)
6178c2ecf20Sopenharmony_ci			return false;
6188c2ecf20Sopenharmony_ci		return true;
6198c2ecf20Sopenharmony_ci	case SPEED_10000:
6208c2ecf20Sopenharmony_ci		return true;
6218c2ecf20Sopenharmony_ci	default:
6228c2ecf20Sopenharmony_ci		return false;
6238c2ecf20Sopenharmony_ci	}
6248c2ecf20Sopenharmony_ci}
6258c2ecf20Sopenharmony_ci
6268c2ecf20Sopenharmony_cistatic int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart)
6278c2ecf20Sopenharmony_ci{
6288c2ecf20Sopenharmony_ci	unsigned int reg;
6298c2ecf20Sopenharmony_ci
6308c2ecf20Sopenharmony_ci	*an_restart = 0;
6318c2ecf20Sopenharmony_ci
6328c2ecf20Sopenharmony_ci	/* Link status is latched low, so read once to clear
6338c2ecf20Sopenharmony_ci	 * and then read again to get current state
6348c2ecf20Sopenharmony_ci	 */
6358c2ecf20Sopenharmony_ci	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
6368c2ecf20Sopenharmony_ci	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_ci	return (reg & MDIO_STAT1_LSTATUS) ? 1 : 0;
6398c2ecf20Sopenharmony_ci}
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_cistatic void xgbe_phy_stop(struct xgbe_prv_data *pdata)
6428c2ecf20Sopenharmony_ci{
6438c2ecf20Sopenharmony_ci	/* Nothing uniquely required for stop */
6448c2ecf20Sopenharmony_ci}
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_cistatic int xgbe_phy_start(struct xgbe_prv_data *pdata)
6478c2ecf20Sopenharmony_ci{
6488c2ecf20Sopenharmony_ci	/* Nothing uniquely required for start */
6498c2ecf20Sopenharmony_ci	return 0;
6508c2ecf20Sopenharmony_ci}
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_cistatic int xgbe_phy_reset(struct xgbe_prv_data *pdata)
6538c2ecf20Sopenharmony_ci{
6548c2ecf20Sopenharmony_ci	unsigned int reg, count;
6558c2ecf20Sopenharmony_ci
6568c2ecf20Sopenharmony_ci	/* Perform a software reset of the PCS */
6578c2ecf20Sopenharmony_ci	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
6588c2ecf20Sopenharmony_ci	reg |= MDIO_CTRL1_RESET;
6598c2ecf20Sopenharmony_ci	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
6608c2ecf20Sopenharmony_ci
6618c2ecf20Sopenharmony_ci	count = 50;
6628c2ecf20Sopenharmony_ci	do {
6638c2ecf20Sopenharmony_ci		msleep(20);
6648c2ecf20Sopenharmony_ci		reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
6658c2ecf20Sopenharmony_ci	} while ((reg & MDIO_CTRL1_RESET) && --count);
6668c2ecf20Sopenharmony_ci
6678c2ecf20Sopenharmony_ci	if (reg & MDIO_CTRL1_RESET)
6688c2ecf20Sopenharmony_ci		return -ETIMEDOUT;
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_ci	return 0;
6718c2ecf20Sopenharmony_ci}
6728c2ecf20Sopenharmony_ci
6738c2ecf20Sopenharmony_cistatic void xgbe_phy_exit(struct xgbe_prv_data *pdata)
6748c2ecf20Sopenharmony_ci{
6758c2ecf20Sopenharmony_ci	/* Nothing uniquely required for exit */
6768c2ecf20Sopenharmony_ci}
6778c2ecf20Sopenharmony_ci
6788c2ecf20Sopenharmony_cistatic int xgbe_phy_init(struct xgbe_prv_data *pdata)
6798c2ecf20Sopenharmony_ci{
6808c2ecf20Sopenharmony_ci	struct ethtool_link_ksettings *lks = &pdata->phy.lks;
6818c2ecf20Sopenharmony_ci	struct xgbe_phy_data *phy_data;
6828c2ecf20Sopenharmony_ci	int ret;
6838c2ecf20Sopenharmony_ci
6848c2ecf20Sopenharmony_ci	phy_data = devm_kzalloc(pdata->dev, sizeof(*phy_data), GFP_KERNEL);
6858c2ecf20Sopenharmony_ci	if (!phy_data)
6868c2ecf20Sopenharmony_ci		return -ENOMEM;
6878c2ecf20Sopenharmony_ci
6888c2ecf20Sopenharmony_ci	/* Retrieve the PHY speedset */
6898c2ecf20Sopenharmony_ci	ret = device_property_read_u32(pdata->phy_dev, XGBE_SPEEDSET_PROPERTY,
6908c2ecf20Sopenharmony_ci				       &phy_data->speed_set);
6918c2ecf20Sopenharmony_ci	if (ret) {
6928c2ecf20Sopenharmony_ci		dev_err(pdata->dev, "invalid %s property\n",
6938c2ecf20Sopenharmony_ci			XGBE_SPEEDSET_PROPERTY);
6948c2ecf20Sopenharmony_ci		return ret;
6958c2ecf20Sopenharmony_ci	}
6968c2ecf20Sopenharmony_ci
6978c2ecf20Sopenharmony_ci	switch (phy_data->speed_set) {
6988c2ecf20Sopenharmony_ci	case XGBE_SPEEDSET_1000_10000:
6998c2ecf20Sopenharmony_ci	case XGBE_SPEEDSET_2500_10000:
7008c2ecf20Sopenharmony_ci		break;
7018c2ecf20Sopenharmony_ci	default:
7028c2ecf20Sopenharmony_ci		dev_err(pdata->dev, "invalid %s property\n",
7038c2ecf20Sopenharmony_ci			XGBE_SPEEDSET_PROPERTY);
7048c2ecf20Sopenharmony_ci		return -EINVAL;
7058c2ecf20Sopenharmony_ci	}
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_ci	/* Retrieve the PHY configuration properties */
7088c2ecf20Sopenharmony_ci	if (device_property_present(pdata->phy_dev, XGBE_BLWC_PROPERTY)) {
7098c2ecf20Sopenharmony_ci		ret = device_property_read_u32_array(pdata->phy_dev,
7108c2ecf20Sopenharmony_ci						     XGBE_BLWC_PROPERTY,
7118c2ecf20Sopenharmony_ci						     phy_data->blwc,
7128c2ecf20Sopenharmony_ci						     XGBE_SPEEDS);
7138c2ecf20Sopenharmony_ci		if (ret) {
7148c2ecf20Sopenharmony_ci			dev_err(pdata->dev, "invalid %s property\n",
7158c2ecf20Sopenharmony_ci				XGBE_BLWC_PROPERTY);
7168c2ecf20Sopenharmony_ci			return ret;
7178c2ecf20Sopenharmony_ci		}
7188c2ecf20Sopenharmony_ci	} else {
7198c2ecf20Sopenharmony_ci		memcpy(phy_data->blwc, xgbe_phy_blwc,
7208c2ecf20Sopenharmony_ci		       sizeof(phy_data->blwc));
7218c2ecf20Sopenharmony_ci	}
7228c2ecf20Sopenharmony_ci
7238c2ecf20Sopenharmony_ci	if (device_property_present(pdata->phy_dev, XGBE_CDR_RATE_PROPERTY)) {
7248c2ecf20Sopenharmony_ci		ret = device_property_read_u32_array(pdata->phy_dev,
7258c2ecf20Sopenharmony_ci						     XGBE_CDR_RATE_PROPERTY,
7268c2ecf20Sopenharmony_ci						     phy_data->cdr_rate,
7278c2ecf20Sopenharmony_ci						     XGBE_SPEEDS);
7288c2ecf20Sopenharmony_ci		if (ret) {
7298c2ecf20Sopenharmony_ci			dev_err(pdata->dev, "invalid %s property\n",
7308c2ecf20Sopenharmony_ci				XGBE_CDR_RATE_PROPERTY);
7318c2ecf20Sopenharmony_ci			return ret;
7328c2ecf20Sopenharmony_ci		}
7338c2ecf20Sopenharmony_ci	} else {
7348c2ecf20Sopenharmony_ci		memcpy(phy_data->cdr_rate, xgbe_phy_cdr_rate,
7358c2ecf20Sopenharmony_ci		       sizeof(phy_data->cdr_rate));
7368c2ecf20Sopenharmony_ci	}
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_ci	if (device_property_present(pdata->phy_dev, XGBE_PQ_SKEW_PROPERTY)) {
7398c2ecf20Sopenharmony_ci		ret = device_property_read_u32_array(pdata->phy_dev,
7408c2ecf20Sopenharmony_ci						     XGBE_PQ_SKEW_PROPERTY,
7418c2ecf20Sopenharmony_ci						     phy_data->pq_skew,
7428c2ecf20Sopenharmony_ci						     XGBE_SPEEDS);
7438c2ecf20Sopenharmony_ci		if (ret) {
7448c2ecf20Sopenharmony_ci			dev_err(pdata->dev, "invalid %s property\n",
7458c2ecf20Sopenharmony_ci				XGBE_PQ_SKEW_PROPERTY);
7468c2ecf20Sopenharmony_ci			return ret;
7478c2ecf20Sopenharmony_ci		}
7488c2ecf20Sopenharmony_ci	} else {
7498c2ecf20Sopenharmony_ci		memcpy(phy_data->pq_skew, xgbe_phy_pq_skew,
7508c2ecf20Sopenharmony_ci		       sizeof(phy_data->pq_skew));
7518c2ecf20Sopenharmony_ci	}
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_ci	if (device_property_present(pdata->phy_dev, XGBE_TX_AMP_PROPERTY)) {
7548c2ecf20Sopenharmony_ci		ret = device_property_read_u32_array(pdata->phy_dev,
7558c2ecf20Sopenharmony_ci						     XGBE_TX_AMP_PROPERTY,
7568c2ecf20Sopenharmony_ci						     phy_data->tx_amp,
7578c2ecf20Sopenharmony_ci						     XGBE_SPEEDS);
7588c2ecf20Sopenharmony_ci		if (ret) {
7598c2ecf20Sopenharmony_ci			dev_err(pdata->dev, "invalid %s property\n",
7608c2ecf20Sopenharmony_ci				XGBE_TX_AMP_PROPERTY);
7618c2ecf20Sopenharmony_ci			return ret;
7628c2ecf20Sopenharmony_ci		}
7638c2ecf20Sopenharmony_ci	} else {
7648c2ecf20Sopenharmony_ci		memcpy(phy_data->tx_amp, xgbe_phy_tx_amp,
7658c2ecf20Sopenharmony_ci		       sizeof(phy_data->tx_amp));
7668c2ecf20Sopenharmony_ci	}
7678c2ecf20Sopenharmony_ci
7688c2ecf20Sopenharmony_ci	if (device_property_present(pdata->phy_dev, XGBE_DFE_CFG_PROPERTY)) {
7698c2ecf20Sopenharmony_ci		ret = device_property_read_u32_array(pdata->phy_dev,
7708c2ecf20Sopenharmony_ci						     XGBE_DFE_CFG_PROPERTY,
7718c2ecf20Sopenharmony_ci						     phy_data->dfe_tap_cfg,
7728c2ecf20Sopenharmony_ci						     XGBE_SPEEDS);
7738c2ecf20Sopenharmony_ci		if (ret) {
7748c2ecf20Sopenharmony_ci			dev_err(pdata->dev, "invalid %s property\n",
7758c2ecf20Sopenharmony_ci				XGBE_DFE_CFG_PROPERTY);
7768c2ecf20Sopenharmony_ci			return ret;
7778c2ecf20Sopenharmony_ci		}
7788c2ecf20Sopenharmony_ci	} else {
7798c2ecf20Sopenharmony_ci		memcpy(phy_data->dfe_tap_cfg, xgbe_phy_dfe_tap_cfg,
7808c2ecf20Sopenharmony_ci		       sizeof(phy_data->dfe_tap_cfg));
7818c2ecf20Sopenharmony_ci	}
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_ci	if (device_property_present(pdata->phy_dev, XGBE_DFE_ENA_PROPERTY)) {
7848c2ecf20Sopenharmony_ci		ret = device_property_read_u32_array(pdata->phy_dev,
7858c2ecf20Sopenharmony_ci						     XGBE_DFE_ENA_PROPERTY,
7868c2ecf20Sopenharmony_ci						     phy_data->dfe_tap_ena,
7878c2ecf20Sopenharmony_ci						     XGBE_SPEEDS);
7888c2ecf20Sopenharmony_ci		if (ret) {
7898c2ecf20Sopenharmony_ci			dev_err(pdata->dev, "invalid %s property\n",
7908c2ecf20Sopenharmony_ci				XGBE_DFE_ENA_PROPERTY);
7918c2ecf20Sopenharmony_ci			return ret;
7928c2ecf20Sopenharmony_ci		}
7938c2ecf20Sopenharmony_ci	} else {
7948c2ecf20Sopenharmony_ci		memcpy(phy_data->dfe_tap_ena, xgbe_phy_dfe_tap_ena,
7958c2ecf20Sopenharmony_ci		       sizeof(phy_data->dfe_tap_ena));
7968c2ecf20Sopenharmony_ci	}
7978c2ecf20Sopenharmony_ci
7988c2ecf20Sopenharmony_ci	/* Initialize supported features */
7998c2ecf20Sopenharmony_ci	XGBE_ZERO_SUP(lks);
8008c2ecf20Sopenharmony_ci	XGBE_SET_SUP(lks, Autoneg);
8018c2ecf20Sopenharmony_ci	XGBE_SET_SUP(lks, Pause);
8028c2ecf20Sopenharmony_ci	XGBE_SET_SUP(lks, Asym_Pause);
8038c2ecf20Sopenharmony_ci	XGBE_SET_SUP(lks, Backplane);
8048c2ecf20Sopenharmony_ci	XGBE_SET_SUP(lks, 10000baseKR_Full);
8058c2ecf20Sopenharmony_ci	switch (phy_data->speed_set) {
8068c2ecf20Sopenharmony_ci	case XGBE_SPEEDSET_1000_10000:
8078c2ecf20Sopenharmony_ci		XGBE_SET_SUP(lks, 1000baseKX_Full);
8088c2ecf20Sopenharmony_ci		break;
8098c2ecf20Sopenharmony_ci	case XGBE_SPEEDSET_2500_10000:
8108c2ecf20Sopenharmony_ci		XGBE_SET_SUP(lks, 2500baseX_Full);
8118c2ecf20Sopenharmony_ci		break;
8128c2ecf20Sopenharmony_ci	}
8138c2ecf20Sopenharmony_ci
8148c2ecf20Sopenharmony_ci	if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
8158c2ecf20Sopenharmony_ci		XGBE_SET_SUP(lks, 10000baseR_FEC);
8168c2ecf20Sopenharmony_ci
8178c2ecf20Sopenharmony_ci	pdata->phy_data = phy_data;
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci	return 0;
8208c2ecf20Sopenharmony_ci}
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_civoid xgbe_init_function_ptrs_phy_v1(struct xgbe_phy_if *phy_if)
8238c2ecf20Sopenharmony_ci{
8248c2ecf20Sopenharmony_ci	struct xgbe_phy_impl_if *phy_impl = &phy_if->phy_impl;
8258c2ecf20Sopenharmony_ci
8268c2ecf20Sopenharmony_ci	phy_impl->init			= xgbe_phy_init;
8278c2ecf20Sopenharmony_ci	phy_impl->exit			= xgbe_phy_exit;
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ci	phy_impl->reset			= xgbe_phy_reset;
8308c2ecf20Sopenharmony_ci	phy_impl->start			= xgbe_phy_start;
8318c2ecf20Sopenharmony_ci	phy_impl->stop			= xgbe_phy_stop;
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci	phy_impl->link_status		= xgbe_phy_link_status;
8348c2ecf20Sopenharmony_ci
8358c2ecf20Sopenharmony_ci	phy_impl->valid_speed		= xgbe_phy_valid_speed;
8368c2ecf20Sopenharmony_ci
8378c2ecf20Sopenharmony_ci	phy_impl->use_mode		= xgbe_phy_use_mode;
8388c2ecf20Sopenharmony_ci	phy_impl->set_mode		= xgbe_phy_set_mode;
8398c2ecf20Sopenharmony_ci	phy_impl->get_mode		= xgbe_phy_get_mode;
8408c2ecf20Sopenharmony_ci	phy_impl->switch_mode		= xgbe_phy_switch_mode;
8418c2ecf20Sopenharmony_ci	phy_impl->cur_mode		= xgbe_phy_cur_mode;
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_ci	phy_impl->an_mode		= xgbe_phy_an_mode;
8448c2ecf20Sopenharmony_ci
8458c2ecf20Sopenharmony_ci	phy_impl->an_config		= xgbe_phy_an_config;
8468c2ecf20Sopenharmony_ci
8478c2ecf20Sopenharmony_ci	phy_impl->an_advertising	= xgbe_phy_an_advertising;
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	phy_impl->an_outcome		= xgbe_phy_an_outcome;
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci	phy_impl->kr_training_pre	= xgbe_phy_kr_training_pre;
8528c2ecf20Sopenharmony_ci	phy_impl->kr_training_post	= xgbe_phy_kr_training_post;
8538c2ecf20Sopenharmony_ci}
854