brintos

brintos / linux-shallow public Read only

0
0
Text · 25.8 KiB · d16eae4 Raw
854 lines · c
1/*2 * AMD 10Gb Ethernet driver3 *4 * This file is available to you under your choice of the following two5 * licenses:6 *7 * License 1: GPLv28 *9 * Copyright (c) 2016 Advanced Micro Devices, Inc.10 *11 * This file is free software; you may copy, redistribute and/or modify12 * it under the terms of the GNU General Public License as published by13 * the Free Software Foundation, either version 2 of the License, or (at14 * your option) any later version.15 *16 * This file is distributed in the hope that it will be useful, but17 * WITHOUT ANY WARRANTY; without even the implied warranty of18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU19 * General Public License for more details.20 *21 * You should have received a copy of the GNU General Public License22 * along with this program.  If not, see <http://www.gnu.org/licenses/>.23 *24 * This file incorporates work covered by the following copyright and25 * permission notice:26 *     The Synopsys DWC ETHER XGMAC Software Driver and documentation27 *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,28 *     Inc. unless otherwise expressly agreed to in writing between Synopsys29 *     and you.30 *31 *     The Software IS NOT an item of Licensed Software or Licensed Product32 *     under any End User Software License Agreement or Agreement for Licensed33 *     Product with Synopsys or any supplement thereto.  Permission is hereby34 *     granted, free of charge, to any person obtaining a copy of this software35 *     annotated with this license and the Software, to deal in the Software36 *     without restriction, including without limitation the rights to use,37 *     copy, modify, merge, publish, distribute, sublicense, and/or sell copies38 *     of the Software, and to permit persons to whom the Software is furnished39 *     to do so, subject to the following conditions:40 *41 *     The above copyright notice and this permission notice shall be included42 *     in all copies or substantial portions of the Software.43 *44 *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"45 *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED46 *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A47 *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS48 *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR49 *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF50 *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS51 *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN52 *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)53 *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF54 *     THE POSSIBILITY OF SUCH DAMAGE.55 *56 *57 * License 2: Modified BSD58 *59 * Copyright (c) 2016 Advanced Micro Devices, Inc.60 * All rights reserved.61 *62 * Redistribution and use in source and binary forms, with or without63 * modification, are permitted provided that the following conditions are met:64 *     * Redistributions of source code must retain the above copyright65 *       notice, this list of conditions and the following disclaimer.66 *     * Redistributions in binary form must reproduce the above copyright67 *       notice, this list of conditions and the following disclaimer in the68 *       documentation and/or other materials provided with the distribution.69 *     * Neither the name of Advanced Micro Devices, Inc. nor the70 *       names of its contributors may be used to endorse or promote products71 *       derived from this software without specific prior written permission.72 *73 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"74 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE75 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE76 * ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY77 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES78 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;79 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND80 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT81 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF82 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.83 *84 * This file incorporates work covered by the following copyright and85 * permission notice:86 *     The Synopsys DWC ETHER XGMAC Software Driver and documentation87 *     (hereinafter "Software") is an unsupported proprietary work of Synopsys,88 *     Inc. unless otherwise expressly agreed to in writing between Synopsys89 *     and you.90 *91 *     The Software IS NOT an item of Licensed Software or Licensed Product92 *     under any End User Software License Agreement or Agreement for Licensed93 *     Product with Synopsys or any supplement thereto.  Permission is hereby94 *     granted, free of charge, to any person obtaining a copy of this software95 *     annotated with this license and the Software, to deal in the Software96 *     without restriction, including without limitation the rights to use,97 *     copy, modify, merge, publish, distribute, sublicense, and/or sell copies98 *     of the Software, and to permit persons to whom the Software is furnished99 *     to do so, subject to the following conditions:100 *101 *     The above copyright notice and this permission notice shall be included102 *     in all copies or substantial portions of the Software.103 *104 *     THIS SOFTWARE IS BEING DISTRIBUTED BY SYNOPSYS SOLELY ON AN "AS IS"105 *     BASIS AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED106 *     TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A107 *     PARTICULAR PURPOSE ARE HEREBY DISCLAIMED. IN NO EVENT SHALL SYNOPSYS108 *     BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR109 *     CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF110 *     SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS111 *     INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN112 *     CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)113 *     ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF114 *     THE POSSIBILITY OF SUCH DAMAGE.115 */116 117#include <linux/module.h>118#include <linux/kmod.h>119#include <linux/device.h>120#include <linux/property.h>121#include <linux/mdio.h>122#include <linux/phy.h>123 124#include "xgbe.h"125#include "xgbe-common.h"126 127#define XGBE_BLWC_PROPERTY		"amd,serdes-blwc"128#define XGBE_CDR_RATE_PROPERTY		"amd,serdes-cdr-rate"129#define XGBE_PQ_SKEW_PROPERTY		"amd,serdes-pq-skew"130#define XGBE_TX_AMP_PROPERTY		"amd,serdes-tx-amp"131#define XGBE_DFE_CFG_PROPERTY		"amd,serdes-dfe-tap-config"132#define XGBE_DFE_ENA_PROPERTY		"amd,serdes-dfe-tap-enable"133 134/* Default SerDes settings */135#define XGBE_SPEED_1000_BLWC		1136#define XGBE_SPEED_1000_CDR		0x2137#define XGBE_SPEED_1000_PLL		0x0138#define XGBE_SPEED_1000_PQ		0xa139#define XGBE_SPEED_1000_RATE		0x3140#define XGBE_SPEED_1000_TXAMP		0xf141#define XGBE_SPEED_1000_WORD		0x1142#define XGBE_SPEED_1000_DFE_TAP_CONFIG	0x3143#define XGBE_SPEED_1000_DFE_TAP_ENABLE	0x0144 145#define XGBE_SPEED_2500_BLWC		1146#define XGBE_SPEED_2500_CDR		0x2147#define XGBE_SPEED_2500_PLL		0x0148#define XGBE_SPEED_2500_PQ		0xa149#define XGBE_SPEED_2500_RATE		0x1150#define XGBE_SPEED_2500_TXAMP		0xf151#define XGBE_SPEED_2500_WORD		0x1152#define XGBE_SPEED_2500_DFE_TAP_CONFIG	0x3153#define XGBE_SPEED_2500_DFE_TAP_ENABLE	0x0154 155#define XGBE_SPEED_10000_BLWC		0156#define XGBE_SPEED_10000_CDR		0x7157#define XGBE_SPEED_10000_PLL		0x1158#define XGBE_SPEED_10000_PQ		0x12159#define XGBE_SPEED_10000_RATE		0x0160#define XGBE_SPEED_10000_TXAMP		0xa161#define XGBE_SPEED_10000_WORD		0x7162#define XGBE_SPEED_10000_DFE_TAP_CONFIG	0x1163#define XGBE_SPEED_10000_DFE_TAP_ENABLE	0x7f164 165/* Rate-change complete wait/retry count */166#define XGBE_RATECHANGE_COUNT		500167 168static const u32 xgbe_phy_blwc[] = {169	XGBE_SPEED_1000_BLWC,170	XGBE_SPEED_2500_BLWC,171	XGBE_SPEED_10000_BLWC,172};173 174static const u32 xgbe_phy_cdr_rate[] = {175	XGBE_SPEED_1000_CDR,176	XGBE_SPEED_2500_CDR,177	XGBE_SPEED_10000_CDR,178};179 180static const u32 xgbe_phy_pq_skew[] = {181	XGBE_SPEED_1000_PQ,182	XGBE_SPEED_2500_PQ,183	XGBE_SPEED_10000_PQ,184};185 186static const u32 xgbe_phy_tx_amp[] = {187	XGBE_SPEED_1000_TXAMP,188	XGBE_SPEED_2500_TXAMP,189	XGBE_SPEED_10000_TXAMP,190};191 192static const u32 xgbe_phy_dfe_tap_cfg[] = {193	XGBE_SPEED_1000_DFE_TAP_CONFIG,194	XGBE_SPEED_2500_DFE_TAP_CONFIG,195	XGBE_SPEED_10000_DFE_TAP_CONFIG,196};197 198static const u32 xgbe_phy_dfe_tap_ena[] = {199	XGBE_SPEED_1000_DFE_TAP_ENABLE,200	XGBE_SPEED_2500_DFE_TAP_ENABLE,201	XGBE_SPEED_10000_DFE_TAP_ENABLE,202};203 204struct xgbe_phy_data {205	/* 1000/10000 vs 2500/10000 indicator */206	unsigned int speed_set;207 208	/* SerDes UEFI configurable settings.209	 *   Switching between modes/speeds requires new values for some210	 *   SerDes settings.  The values can be supplied as device211	 *   properties in array format.  The first array entry is for212	 *   1GbE, second for 2.5GbE and third for 10GbE213	 */214	u32 blwc[XGBE_SPEEDS];215	u32 cdr_rate[XGBE_SPEEDS];216	u32 pq_skew[XGBE_SPEEDS];217	u32 tx_amp[XGBE_SPEEDS];218	u32 dfe_tap_cfg[XGBE_SPEEDS];219	u32 dfe_tap_ena[XGBE_SPEEDS];220};221 222static void xgbe_phy_kr_training_pre(struct xgbe_prv_data *pdata)223{224		XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 1);225}226 227static void xgbe_phy_kr_training_post(struct xgbe_prv_data *pdata)228{229		XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 0);230}231 232static enum xgbe_mode xgbe_phy_an_outcome(struct xgbe_prv_data *pdata)233{234	struct ethtool_link_ksettings *lks = &pdata->phy.lks;235	struct xgbe_phy_data *phy_data = pdata->phy_data;236	enum xgbe_mode mode;237	unsigned int ad_reg, lp_reg;238 239	XGBE_SET_LP_ADV(lks, Autoneg);240	XGBE_SET_LP_ADV(lks, Backplane);241 242	/* Compare Advertisement and Link Partner register 1 */243	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);244	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);245	if (lp_reg & 0x400)246		XGBE_SET_LP_ADV(lks, Pause);247	if (lp_reg & 0x800)248		XGBE_SET_LP_ADV(lks, Asym_Pause);249 250	if (pdata->phy.pause_autoneg) {251		/* Set flow control based on auto-negotiation result */252		pdata->phy.tx_pause = 0;253		pdata->phy.rx_pause = 0;254 255		if (ad_reg & lp_reg & 0x400) {256			pdata->phy.tx_pause = 1;257			pdata->phy.rx_pause = 1;258		} else if (ad_reg & lp_reg & 0x800) {259			if (ad_reg & 0x400)260				pdata->phy.rx_pause = 1;261			else if (lp_reg & 0x400)262				pdata->phy.tx_pause = 1;263		}264	}265 266	/* Compare Advertisement and Link Partner register 2 */267	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);268	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);269	if (lp_reg & 0x80)270		XGBE_SET_LP_ADV(lks, 10000baseKR_Full);271	if (lp_reg & 0x20) {272		if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)273			XGBE_SET_LP_ADV(lks, 2500baseX_Full);274		else275			XGBE_SET_LP_ADV(lks, 1000baseKX_Full);276	}277 278	ad_reg &= lp_reg;279	if (ad_reg & 0x80) {280		mode = XGBE_MODE_KR;281	} else if (ad_reg & 0x20) {282		if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)283			mode = XGBE_MODE_KX_2500;284		else285			mode = XGBE_MODE_KX_1000;286	} else {287		mode = XGBE_MODE_UNKNOWN;288	}289 290	/* Compare Advertisement and Link Partner register 3 */291	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);292	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);293	if (lp_reg & 0xc000)294		XGBE_SET_LP_ADV(lks, 10000baseR_FEC);295 296	return mode;297}298 299static void xgbe_phy_an_advertising(struct xgbe_prv_data *pdata,300				    struct ethtool_link_ksettings *dlks)301{302	struct ethtool_link_ksettings *slks = &pdata->phy.lks;303 304	XGBE_LM_COPY(dlks, advertising, slks, advertising);305}306 307static int xgbe_phy_an_config(struct xgbe_prv_data *pdata)308{309	/* Nothing uniquely required for an configuration */310	return 0;311}312 313static enum xgbe_an_mode xgbe_phy_an_mode(struct xgbe_prv_data *pdata)314{315	return XGBE_AN_MODE_CL73;316}317 318static void xgbe_phy_pcs_power_cycle(struct xgbe_prv_data *pdata)319{320	unsigned int reg;321 322	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);323 324	reg |= MDIO_CTRL1_LPOWER;325	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);326 327	usleep_range(75, 100);328 329	reg &= ~MDIO_CTRL1_LPOWER;330	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);331}332 333static void xgbe_phy_start_ratechange(struct xgbe_prv_data *pdata)334{335	/* Assert Rx and Tx ratechange */336	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 1);337}338 339static void xgbe_phy_complete_ratechange(struct xgbe_prv_data *pdata)340{341	unsigned int wait;342	u16 status;343 344	/* Release Rx and Tx ratechange */345	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 0);346 347	/* Wait for Rx and Tx ready */348	wait = XGBE_RATECHANGE_COUNT;349	while (wait--) {350		usleep_range(50, 75);351 352		status = XSIR0_IOREAD(pdata, SIR0_STATUS);353		if (XSIR_GET_BITS(status, SIR0_STATUS, RX_READY) &&354		    XSIR_GET_BITS(status, SIR0_STATUS, TX_READY))355			goto rx_reset;356	}357 358	netif_dbg(pdata, link, pdata->netdev, "SerDes rx/tx not ready (%#hx)\n",359		  status);360 361rx_reset:362	/* Perform Rx reset for the DFE changes */363	XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 0);364	XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 1);365}366 367static void xgbe_phy_kr_mode(struct xgbe_prv_data *pdata)368{369	struct xgbe_phy_data *phy_data = pdata->phy_data;370	unsigned int reg;371 372	/* Set PCS to KR/10G speed */373	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);374	reg &= ~MDIO_PCS_CTRL2_TYPE;375	reg |= MDIO_PCS_CTRL2_10GBR;376	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);377 378	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);379	reg &= ~MDIO_CTRL1_SPEEDSEL;380	reg |= MDIO_CTRL1_SPEED10G;381	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);382 383	xgbe_phy_pcs_power_cycle(pdata);384 385	/* Set SerDes to 10G speed */386	xgbe_phy_start_ratechange(pdata);387 388	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_10000_RATE);389	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_10000_WORD);390	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_10000_PLL);391 392	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,393			   phy_data->cdr_rate[XGBE_SPEED_10000]);394	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,395			   phy_data->tx_amp[XGBE_SPEED_10000]);396	XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,397			   phy_data->blwc[XGBE_SPEED_10000]);398	XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,399			   phy_data->pq_skew[XGBE_SPEED_10000]);400	XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,401			   phy_data->dfe_tap_cfg[XGBE_SPEED_10000]);402	XRXTX_IOWRITE(pdata, RXTX_REG22,403		      phy_data->dfe_tap_ena[XGBE_SPEED_10000]);404 405	xgbe_phy_complete_ratechange(pdata);406 407	netif_dbg(pdata, link, pdata->netdev, "10GbE KR mode set\n");408}409 410static void xgbe_phy_kx_2500_mode(struct xgbe_prv_data *pdata)411{412	struct xgbe_phy_data *phy_data = pdata->phy_data;413	unsigned int reg;414 415	/* Set PCS to KX/1G speed */416	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);417	reg &= ~MDIO_PCS_CTRL2_TYPE;418	reg |= MDIO_PCS_CTRL2_10GBX;419	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);420 421	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);422	reg &= ~MDIO_CTRL1_SPEEDSEL;423	reg |= MDIO_CTRL1_SPEED1G;424	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);425 426	xgbe_phy_pcs_power_cycle(pdata);427 428	/* Set SerDes to 2.5G speed */429	xgbe_phy_start_ratechange(pdata);430 431	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_2500_RATE);432	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_2500_WORD);433	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_2500_PLL);434 435	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,436			   phy_data->cdr_rate[XGBE_SPEED_2500]);437	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,438			   phy_data->tx_amp[XGBE_SPEED_2500]);439	XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,440			   phy_data->blwc[XGBE_SPEED_2500]);441	XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,442			   phy_data->pq_skew[XGBE_SPEED_2500]);443	XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,444			   phy_data->dfe_tap_cfg[XGBE_SPEED_2500]);445	XRXTX_IOWRITE(pdata, RXTX_REG22,446		      phy_data->dfe_tap_ena[XGBE_SPEED_2500]);447 448	xgbe_phy_complete_ratechange(pdata);449 450	netif_dbg(pdata, link, pdata->netdev, "2.5GbE KX mode set\n");451}452 453static void xgbe_phy_kx_1000_mode(struct xgbe_prv_data *pdata)454{455	struct xgbe_phy_data *phy_data = pdata->phy_data;456	unsigned int reg;457 458	/* Set PCS to KX/1G speed */459	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);460	reg &= ~MDIO_PCS_CTRL2_TYPE;461	reg |= MDIO_PCS_CTRL2_10GBX;462	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);463 464	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);465	reg &= ~MDIO_CTRL1_SPEEDSEL;466	reg |= MDIO_CTRL1_SPEED1G;467	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);468 469	xgbe_phy_pcs_power_cycle(pdata);470 471	/* Set SerDes to 1G speed */472	xgbe_phy_start_ratechange(pdata);473 474	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_1000_RATE);475	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_1000_WORD);476	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_1000_PLL);477 478	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,479			   phy_data->cdr_rate[XGBE_SPEED_1000]);480	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,481			   phy_data->tx_amp[XGBE_SPEED_1000]);482	XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,483			   phy_data->blwc[XGBE_SPEED_1000]);484	XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,485			   phy_data->pq_skew[XGBE_SPEED_1000]);486	XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,487			   phy_data->dfe_tap_cfg[XGBE_SPEED_1000]);488	XRXTX_IOWRITE(pdata, RXTX_REG22,489		      phy_data->dfe_tap_ena[XGBE_SPEED_1000]);490 491	xgbe_phy_complete_ratechange(pdata);492 493	netif_dbg(pdata, link, pdata->netdev, "1GbE KX mode set\n");494}495 496static enum xgbe_mode xgbe_phy_cur_mode(struct xgbe_prv_data *pdata)497{498	struct xgbe_phy_data *phy_data = pdata->phy_data;499	enum xgbe_mode mode;500	unsigned int reg;501 502	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);503	reg &= MDIO_PCS_CTRL2_TYPE;504 505	if (reg == MDIO_PCS_CTRL2_10GBR) {506		mode = XGBE_MODE_KR;507	} else {508		if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)509			mode = XGBE_MODE_KX_2500;510		else511			mode = XGBE_MODE_KX_1000;512	}513 514	return mode;515}516 517static enum xgbe_mode xgbe_phy_switch_mode(struct xgbe_prv_data *pdata)518{519	struct xgbe_phy_data *phy_data = pdata->phy_data;520	enum xgbe_mode mode;521 522	/* If we are in KR switch to KX, and vice-versa */523	if (xgbe_phy_cur_mode(pdata) == XGBE_MODE_KR) {524		if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)525			mode = XGBE_MODE_KX_2500;526		else527			mode = XGBE_MODE_KX_1000;528	} else {529		mode = XGBE_MODE_KR;530	}531 532	return mode;533}534 535static enum xgbe_mode xgbe_phy_get_mode(struct xgbe_prv_data *pdata,536					int speed)537{538	struct xgbe_phy_data *phy_data = pdata->phy_data;539 540	switch (speed) {541	case SPEED_1000:542		return (phy_data->speed_set == XGBE_SPEEDSET_1000_10000)543			? XGBE_MODE_KX_1000 : XGBE_MODE_UNKNOWN;544	case SPEED_2500:545		return (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)546			? XGBE_MODE_KX_2500 : XGBE_MODE_UNKNOWN;547	case SPEED_10000:548		return XGBE_MODE_KR;549	default:550		return XGBE_MODE_UNKNOWN;551	}552}553 554static void xgbe_phy_set_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)555{556	switch (mode) {557	case XGBE_MODE_KX_1000:558		xgbe_phy_kx_1000_mode(pdata);559		break;560	case XGBE_MODE_KX_2500:561		xgbe_phy_kx_2500_mode(pdata);562		break;563	case XGBE_MODE_KR:564		xgbe_phy_kr_mode(pdata);565		break;566	default:567		break;568	}569}570 571static bool xgbe_phy_check_mode(struct xgbe_prv_data *pdata,572				enum xgbe_mode mode, bool advert)573{574	if (pdata->phy.autoneg == AUTONEG_ENABLE) {575		return advert;576	} else {577		enum xgbe_mode cur_mode;578 579		cur_mode = xgbe_phy_get_mode(pdata, pdata->phy.speed);580		if (cur_mode == mode)581			return true;582	}583 584	return false;585}586 587static bool xgbe_phy_use_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)588{589	struct ethtool_link_ksettings *lks = &pdata->phy.lks;590 591	switch (mode) {592	case XGBE_MODE_KX_1000:593		return xgbe_phy_check_mode(pdata, mode,594					   XGBE_ADV(lks, 1000baseKX_Full));595	case XGBE_MODE_KX_2500:596		return xgbe_phy_check_mode(pdata, mode,597					   XGBE_ADV(lks, 2500baseX_Full));598	case XGBE_MODE_KR:599		return xgbe_phy_check_mode(pdata, mode,600					   XGBE_ADV(lks, 10000baseKR_Full));601	default:602		return false;603	}604}605 606static bool xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed)607{608	struct xgbe_phy_data *phy_data = pdata->phy_data;609 610	switch (speed) {611	case SPEED_1000:612		if (phy_data->speed_set != XGBE_SPEEDSET_1000_10000)613			return false;614		return true;615	case SPEED_2500:616		if (phy_data->speed_set != XGBE_SPEEDSET_2500_10000)617			return false;618		return true;619	case SPEED_10000:620		return true;621	default:622		return false;623	}624}625 626static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart)627{628	unsigned int reg;629 630	*an_restart = 0;631 632	/* Link status is latched low, so read once to clear633	 * and then read again to get current state634	 */635	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);636	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);637 638	return (reg & MDIO_STAT1_LSTATUS) ? 1 : 0;639}640 641static void xgbe_phy_stop(struct xgbe_prv_data *pdata)642{643	/* Nothing uniquely required for stop */644}645 646static int xgbe_phy_start(struct xgbe_prv_data *pdata)647{648	/* Nothing uniquely required for start */649	return 0;650}651 652static int xgbe_phy_reset(struct xgbe_prv_data *pdata)653{654	unsigned int reg, count;655 656	/* Perform a software reset of the PCS */657	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);658	reg |= MDIO_CTRL1_RESET;659	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);660 661	count = 50;662	do {663		msleep(20);664		reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);665	} while ((reg & MDIO_CTRL1_RESET) && --count);666 667	if (reg & MDIO_CTRL1_RESET)668		return -ETIMEDOUT;669 670	return 0;671}672 673static void xgbe_phy_exit(struct xgbe_prv_data *pdata)674{675	/* Nothing uniquely required for exit */676}677 678static int xgbe_phy_init(struct xgbe_prv_data *pdata)679{680	struct ethtool_link_ksettings *lks = &pdata->phy.lks;681	struct xgbe_phy_data *phy_data;682	int ret;683 684	phy_data = devm_kzalloc(pdata->dev, sizeof(*phy_data), GFP_KERNEL);685	if (!phy_data)686		return -ENOMEM;687 688	/* Retrieve the PHY speedset */689	ret = device_property_read_u32(pdata->phy_dev, XGBE_SPEEDSET_PROPERTY,690				       &phy_data->speed_set);691	if (ret) {692		dev_err(pdata->dev, "invalid %s property\n",693			XGBE_SPEEDSET_PROPERTY);694		return ret;695	}696 697	switch (phy_data->speed_set) {698	case XGBE_SPEEDSET_1000_10000:699	case XGBE_SPEEDSET_2500_10000:700		break;701	default:702		dev_err(pdata->dev, "invalid %s property\n",703			XGBE_SPEEDSET_PROPERTY);704		return -EINVAL;705	}706 707	/* Retrieve the PHY configuration properties */708	if (device_property_present(pdata->phy_dev, XGBE_BLWC_PROPERTY)) {709		ret = device_property_read_u32_array(pdata->phy_dev,710						     XGBE_BLWC_PROPERTY,711						     phy_data->blwc,712						     XGBE_SPEEDS);713		if (ret) {714			dev_err(pdata->dev, "invalid %s property\n",715				XGBE_BLWC_PROPERTY);716			return ret;717		}718	} else {719		memcpy(phy_data->blwc, xgbe_phy_blwc,720		       sizeof(phy_data->blwc));721	}722 723	if (device_property_present(pdata->phy_dev, XGBE_CDR_RATE_PROPERTY)) {724		ret = device_property_read_u32_array(pdata->phy_dev,725						     XGBE_CDR_RATE_PROPERTY,726						     phy_data->cdr_rate,727						     XGBE_SPEEDS);728		if (ret) {729			dev_err(pdata->dev, "invalid %s property\n",730				XGBE_CDR_RATE_PROPERTY);731			return ret;732		}733	} else {734		memcpy(phy_data->cdr_rate, xgbe_phy_cdr_rate,735		       sizeof(phy_data->cdr_rate));736	}737 738	if (device_property_present(pdata->phy_dev, XGBE_PQ_SKEW_PROPERTY)) {739		ret = device_property_read_u32_array(pdata->phy_dev,740						     XGBE_PQ_SKEW_PROPERTY,741						     phy_data->pq_skew,742						     XGBE_SPEEDS);743		if (ret) {744			dev_err(pdata->dev, "invalid %s property\n",745				XGBE_PQ_SKEW_PROPERTY);746			return ret;747		}748	} else {749		memcpy(phy_data->pq_skew, xgbe_phy_pq_skew,750		       sizeof(phy_data->pq_skew));751	}752 753	if (device_property_present(pdata->phy_dev, XGBE_TX_AMP_PROPERTY)) {754		ret = device_property_read_u32_array(pdata->phy_dev,755						     XGBE_TX_AMP_PROPERTY,756						     phy_data->tx_amp,757						     XGBE_SPEEDS);758		if (ret) {759			dev_err(pdata->dev, "invalid %s property\n",760				XGBE_TX_AMP_PROPERTY);761			return ret;762		}763	} else {764		memcpy(phy_data->tx_amp, xgbe_phy_tx_amp,765		       sizeof(phy_data->tx_amp));766	}767 768	if (device_property_present(pdata->phy_dev, XGBE_DFE_CFG_PROPERTY)) {769		ret = device_property_read_u32_array(pdata->phy_dev,770						     XGBE_DFE_CFG_PROPERTY,771						     phy_data->dfe_tap_cfg,772						     XGBE_SPEEDS);773		if (ret) {774			dev_err(pdata->dev, "invalid %s property\n",775				XGBE_DFE_CFG_PROPERTY);776			return ret;777		}778	} else {779		memcpy(phy_data->dfe_tap_cfg, xgbe_phy_dfe_tap_cfg,780		       sizeof(phy_data->dfe_tap_cfg));781	}782 783	if (device_property_present(pdata->phy_dev, XGBE_DFE_ENA_PROPERTY)) {784		ret = device_property_read_u32_array(pdata->phy_dev,785						     XGBE_DFE_ENA_PROPERTY,786						     phy_data->dfe_tap_ena,787						     XGBE_SPEEDS);788		if (ret) {789			dev_err(pdata->dev, "invalid %s property\n",790				XGBE_DFE_ENA_PROPERTY);791			return ret;792		}793	} else {794		memcpy(phy_data->dfe_tap_ena, xgbe_phy_dfe_tap_ena,795		       sizeof(phy_data->dfe_tap_ena));796	}797 798	/* Initialize supported features */799	XGBE_ZERO_SUP(lks);800	XGBE_SET_SUP(lks, Autoneg);801	XGBE_SET_SUP(lks, Pause);802	XGBE_SET_SUP(lks, Asym_Pause);803	XGBE_SET_SUP(lks, Backplane);804	XGBE_SET_SUP(lks, 10000baseKR_Full);805	switch (phy_data->speed_set) {806	case XGBE_SPEEDSET_1000_10000:807		XGBE_SET_SUP(lks, 1000baseKX_Full);808		break;809	case XGBE_SPEEDSET_2500_10000:810		XGBE_SET_SUP(lks, 2500baseX_Full);811		break;812	}813 814	if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)815		XGBE_SET_SUP(lks, 10000baseR_FEC);816 817	pdata->phy_data = phy_data;818 819	return 0;820}821 822void xgbe_init_function_ptrs_phy_v1(struct xgbe_phy_if *phy_if)823{824	struct xgbe_phy_impl_if *phy_impl = &phy_if->phy_impl;825 826	phy_impl->init			= xgbe_phy_init;827	phy_impl->exit			= xgbe_phy_exit;828 829	phy_impl->reset			= xgbe_phy_reset;830	phy_impl->start			= xgbe_phy_start;831	phy_impl->stop			= xgbe_phy_stop;832 833	phy_impl->link_status		= xgbe_phy_link_status;834 835	phy_impl->valid_speed		= xgbe_phy_valid_speed;836 837	phy_impl->use_mode		= xgbe_phy_use_mode;838	phy_impl->set_mode		= xgbe_phy_set_mode;839	phy_impl->get_mode		= xgbe_phy_get_mode;840	phy_impl->switch_mode		= xgbe_phy_switch_mode;841	phy_impl->cur_mode		= xgbe_phy_cur_mode;842 843	phy_impl->an_mode		= xgbe_phy_an_mode;844 845	phy_impl->an_config		= xgbe_phy_an_config;846 847	phy_impl->an_advertising	= xgbe_phy_an_advertising;848 849	phy_impl->an_outcome		= xgbe_phy_an_outcome;850 851	phy_impl->kr_training_pre	= xgbe_phy_kr_training_pre;852	phy_impl->kr_training_post	= xgbe_phy_kr_training_post;853}854