File Index
Files and directories
Sign in
FILE

xgbe-phy-v1.c

File preview with syntax highlighting.

linux-6.19.14/drivers/net/ethernet/amd/xgbe/xgbe-phy-v1.c C
  1// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause)
  2/*
  3 * Copyright (c) 2014-2025, Advanced Micro Devices, Inc.
  4 * Copyright (c) 2014, Synopsys, Inc.
  5 * All rights reserved
  6 */
  7
  8#include <linux/module.h>
  9#include <linux/kmod.h>
 10#include <linux/device.h>
 11#include <linux/property.h>
 12#include <linux/mdio.h>
 13#include <linux/phy.h>
 14
 15#include "xgbe.h"
 16#include "xgbe-common.h"
 17
 18#define XGBE_BLWC_PROPERTY		"amd,serdes-blwc"
 19#define XGBE_CDR_RATE_PROPERTY		"amd,serdes-cdr-rate"
 20#define XGBE_PQ_SKEW_PROPERTY		"amd,serdes-pq-skew"
 21#define XGBE_TX_AMP_PROPERTY		"amd,serdes-tx-amp"
 22#define XGBE_DFE_CFG_PROPERTY		"amd,serdes-dfe-tap-config"
 23#define XGBE_DFE_ENA_PROPERTY		"amd,serdes-dfe-tap-enable"
 24
 25/* Default SerDes settings */
 26#define XGBE_SPEED_1000_BLWC		1
 27#define XGBE_SPEED_1000_CDR		0x2
 28#define XGBE_SPEED_1000_PLL		0x0
 29#define XGBE_SPEED_1000_PQ		0xa
 30#define XGBE_SPEED_1000_RATE		0x3
 31#define XGBE_SPEED_1000_TXAMP		0xf
 32#define XGBE_SPEED_1000_WORD		0x1
 33#define XGBE_SPEED_1000_DFE_TAP_CONFIG	0x3
 34#define XGBE_SPEED_1000_DFE_TAP_ENABLE	0x0
 35
 36#define XGBE_SPEED_2500_BLWC		1
 37#define XGBE_SPEED_2500_CDR		0x2
 38#define XGBE_SPEED_2500_PLL		0x0
 39#define XGBE_SPEED_2500_PQ		0xa
 40#define XGBE_SPEED_2500_RATE		0x1
 41#define XGBE_SPEED_2500_TXAMP		0xf
 42#define XGBE_SPEED_2500_WORD		0x1
 43#define XGBE_SPEED_2500_DFE_TAP_CONFIG	0x3
 44#define XGBE_SPEED_2500_DFE_TAP_ENABLE	0x0
 45
 46#define XGBE_SPEED_10000_BLWC		0
 47#define XGBE_SPEED_10000_CDR		0x7
 48#define XGBE_SPEED_10000_PLL		0x1
 49#define XGBE_SPEED_10000_PQ		0x12
 50#define XGBE_SPEED_10000_RATE		0x0
 51#define XGBE_SPEED_10000_TXAMP		0xa
 52#define XGBE_SPEED_10000_WORD		0x7
 53#define XGBE_SPEED_10000_DFE_TAP_CONFIG	0x1
 54#define XGBE_SPEED_10000_DFE_TAP_ENABLE	0x7f
 55
 56/* Rate-change complete wait/retry count */
 57#define XGBE_RATECHANGE_COUNT		500
 58
 59static const u32 xgbe_phy_blwc[] = {
 60	XGBE_SPEED_1000_BLWC,
 61	XGBE_SPEED_2500_BLWC,
 62	XGBE_SPEED_10000_BLWC,
 63};
 64
 65static const u32 xgbe_phy_cdr_rate[] = {
 66	XGBE_SPEED_1000_CDR,
 67	XGBE_SPEED_2500_CDR,
 68	XGBE_SPEED_10000_CDR,
 69};
 70
 71static const u32 xgbe_phy_pq_skew[] = {
 72	XGBE_SPEED_1000_PQ,
 73	XGBE_SPEED_2500_PQ,
 74	XGBE_SPEED_10000_PQ,
 75};
 76
 77static const u32 xgbe_phy_tx_amp[] = {
 78	XGBE_SPEED_1000_TXAMP,
 79	XGBE_SPEED_2500_TXAMP,
 80	XGBE_SPEED_10000_TXAMP,
 81};
 82
 83static const u32 xgbe_phy_dfe_tap_cfg[] = {
 84	XGBE_SPEED_1000_DFE_TAP_CONFIG,
 85	XGBE_SPEED_2500_DFE_TAP_CONFIG,
 86	XGBE_SPEED_10000_DFE_TAP_CONFIG,
 87};
 88
 89static const u32 xgbe_phy_dfe_tap_ena[] = {
 90	XGBE_SPEED_1000_DFE_TAP_ENABLE,
 91	XGBE_SPEED_2500_DFE_TAP_ENABLE,
 92	XGBE_SPEED_10000_DFE_TAP_ENABLE,
 93};
 94
 95struct xgbe_phy_data {
 96	/* 1000/10000 vs 2500/10000 indicator */
 97	unsigned int speed_set;
 98
 99	/* SerDes UEFI configurable settings.
100	 *   Switching between modes/speeds requires new values for some
101	 *   SerDes settings.  The values can be supplied as device
102	 *   properties in array format.  The first array entry is for
103	 *   1GbE, second for 2.5GbE and third for 10GbE
104	 */
105	u32 blwc[XGBE_SPEEDS];
106	u32 cdr_rate[XGBE_SPEEDS];
107	u32 pq_skew[XGBE_SPEEDS];
108	u32 tx_amp[XGBE_SPEEDS];
109	u32 dfe_tap_cfg[XGBE_SPEEDS];
110	u32 dfe_tap_ena[XGBE_SPEEDS];
111};
112
113static void xgbe_phy_kr_training_pre(struct xgbe_prv_data *pdata)
114{
115		XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 1);
116}
117
118static void xgbe_phy_kr_training_post(struct xgbe_prv_data *pdata)
119{
120		XSIR0_IOWRITE_BITS(pdata, SIR0_KR_RT_1, RESET, 0);
121}
122
123static enum xgbe_mode xgbe_phy_an_outcome(struct xgbe_prv_data *pdata)
124{
125	struct ethtool_link_ksettings *lks = &pdata->phy.lks;
126	struct xgbe_phy_data *phy_data = pdata->phy_data;
127	enum xgbe_mode mode;
128	unsigned int ad_reg, lp_reg;
129
130	XGBE_SET_LP_ADV(lks, Autoneg);
131	XGBE_SET_LP_ADV(lks, Backplane);
132
133	/* Compare Advertisement and Link Partner register 1 */
134	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE);
135	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA);
136	if (lp_reg & 0x400)
137		XGBE_SET_LP_ADV(lks, Pause);
138	if (lp_reg & 0x800)
139		XGBE_SET_LP_ADV(lks, Asym_Pause);
140
141	if (pdata->phy.pause_autoneg) {
142		/* Set flow control based on auto-negotiation result */
143		pdata->phy.tx_pause = 0;
144		pdata->phy.rx_pause = 0;
145
146		if (ad_reg & lp_reg & 0x400) {
147			pdata->phy.tx_pause = 1;
148			pdata->phy.rx_pause = 1;
149		} else if (ad_reg & lp_reg & 0x800) {
150			if (ad_reg & 0x400)
151				pdata->phy.rx_pause = 1;
152			else if (lp_reg & 0x400)
153				pdata->phy.tx_pause = 1;
154		}
155	}
156
157	/* Compare Advertisement and Link Partner register 2 */
158	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 1);
159	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 1);
160	if (lp_reg & 0x80)
161		XGBE_SET_LP_ADV(lks, 10000baseKR_Full);
162	if (lp_reg & 0x20) {
163		if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
164			XGBE_SET_LP_ADV(lks, 2500baseX_Full);
165		else
166			XGBE_SET_LP_ADV(lks, 1000baseKX_Full);
167	}
168
169	ad_reg &= lp_reg;
170	if (ad_reg & 0x80) {
171		mode = XGBE_MODE_KR;
172	} else if (ad_reg & 0x20) {
173		if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
174			mode = XGBE_MODE_KX_2500;
175		else
176			mode = XGBE_MODE_KX_1000;
177	} else {
178		mode = XGBE_MODE_UNKNOWN;
179	}
180
181	/* Compare Advertisement and Link Partner register 3 */
182	ad_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_ADVERTISE + 2);
183	lp_reg = XMDIO_READ(pdata, MDIO_MMD_AN, MDIO_AN_LPA + 2);
184	if (lp_reg & 0xc000)
185		XGBE_SET_LP_ADV(lks, 10000baseR_FEC);
186
187	return mode;
188}
189
190static void xgbe_phy_an_advertising(struct xgbe_prv_data *pdata,
191				    struct ethtool_link_ksettings *dlks)
192{
193	struct ethtool_link_ksettings *slks = &pdata->phy.lks;
194
195	XGBE_LM_COPY(dlks, advertising, slks, advertising);
196}
197
198static int xgbe_phy_an_config(struct xgbe_prv_data *pdata)
199{
200	/* Nothing uniquely required for an configuration */
201	return 0;
202}
203
204static enum xgbe_an_mode xgbe_phy_an_mode(struct xgbe_prv_data *pdata)
205{
206	return XGBE_AN_MODE_CL73;
207}
208
209static void xgbe_phy_pcs_power_cycle(struct xgbe_prv_data *pdata)
210{
211	unsigned int reg;
212
213	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
214
215	reg |= MDIO_CTRL1_LPOWER;
216	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
217
218	usleep_range(75, 100);
219
220	reg &= ~MDIO_CTRL1_LPOWER;
221	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
222}
223
224static void xgbe_phy_start_ratechange(struct xgbe_prv_data *pdata)
225{
226	/* Assert Rx and Tx ratechange */
227	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 1);
228}
229
230static void xgbe_phy_complete_ratechange(struct xgbe_prv_data *pdata)
231{
232	unsigned int wait;
233	u16 status;
234
235	/* Release Rx and Tx ratechange */
236	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, RATECHANGE, 0);
237
238	/* Wait for Rx and Tx ready */
239	wait = XGBE_RATECHANGE_COUNT;
240	while (wait--) {
241		usleep_range(50, 75);
242
243		status = XSIR0_IOREAD(pdata, SIR0_STATUS);
244		if (XSIR_GET_BITS(status, SIR0_STATUS, RX_READY) &&
245		    XSIR_GET_BITS(status, SIR0_STATUS, TX_READY))
246			goto rx_reset;
247	}
248
249	netif_dbg(pdata, link, pdata->netdev, "SerDes rx/tx not ready (%#hx)\n",
250		  status);
251
252rx_reset:
253	/* Perform Rx reset for the DFE changes */
254	XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 0);
255	XRXTX_IOWRITE_BITS(pdata, RXTX_REG6, RESETB_RXD, 1);
256}
257
258static void xgbe_phy_kr_mode(struct xgbe_prv_data *pdata)
259{
260	struct xgbe_phy_data *phy_data = pdata->phy_data;
261	unsigned int reg;
262
263	/* Set PCS to KR/10G speed */
264	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
265	reg &= ~MDIO_PCS_CTRL2_TYPE;
266	reg |= MDIO_PCS_CTRL2_10GBR;
267	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
268
269	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
270	reg &= ~MDIO_CTRL1_SPEEDSEL;
271	reg |= MDIO_CTRL1_SPEED10G;
272	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
273
274	xgbe_phy_pcs_power_cycle(pdata);
275
276	/* Set SerDes to 10G speed */
277	xgbe_phy_start_ratechange(pdata);
278
279	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_10000_RATE);
280	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_10000_WORD);
281	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_10000_PLL);
282
283	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
284			   phy_data->cdr_rate[XGBE_SPEED_10000]);
285	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
286			   phy_data->tx_amp[XGBE_SPEED_10000]);
287	XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
288			   phy_data->blwc[XGBE_SPEED_10000]);
289	XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
290			   phy_data->pq_skew[XGBE_SPEED_10000]);
291	XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
292			   phy_data->dfe_tap_cfg[XGBE_SPEED_10000]);
293	XRXTX_IOWRITE(pdata, RXTX_REG22,
294		      phy_data->dfe_tap_ena[XGBE_SPEED_10000]);
295
296	xgbe_phy_complete_ratechange(pdata);
297
298	netif_dbg(pdata, link, pdata->netdev, "10GbE KR mode set\n");
299}
300
301static void xgbe_phy_kx_2500_mode(struct xgbe_prv_data *pdata)
302{
303	struct xgbe_phy_data *phy_data = pdata->phy_data;
304	unsigned int reg;
305
306	/* Set PCS to KX/1G speed */
307	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
308	reg &= ~MDIO_PCS_CTRL2_TYPE;
309	reg |= MDIO_PCS_CTRL2_10GBX;
310	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
311
312	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
313	reg &= ~MDIO_CTRL1_SPEEDSEL;
314	reg |= MDIO_CTRL1_SPEED1G;
315	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
316
317	xgbe_phy_pcs_power_cycle(pdata);
318
319	/* Set SerDes to 2.5G speed */
320	xgbe_phy_start_ratechange(pdata);
321
322	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_2500_RATE);
323	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_2500_WORD);
324	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_2500_PLL);
325
326	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
327			   phy_data->cdr_rate[XGBE_SPEED_2500]);
328	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
329			   phy_data->tx_amp[XGBE_SPEED_2500]);
330	XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
331			   phy_data->blwc[XGBE_SPEED_2500]);
332	XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
333			   phy_data->pq_skew[XGBE_SPEED_2500]);
334	XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
335			   phy_data->dfe_tap_cfg[XGBE_SPEED_2500]);
336	XRXTX_IOWRITE(pdata, RXTX_REG22,
337		      phy_data->dfe_tap_ena[XGBE_SPEED_2500]);
338
339	xgbe_phy_complete_ratechange(pdata);
340
341	netif_dbg(pdata, link, pdata->netdev, "2.5GbE KX mode set\n");
342}
343
344static void xgbe_phy_kx_1000_mode(struct xgbe_prv_data *pdata)
345{
346	struct xgbe_phy_data *phy_data = pdata->phy_data;
347	unsigned int reg;
348
349	/* Set PCS to KX/1G speed */
350	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
351	reg &= ~MDIO_PCS_CTRL2_TYPE;
352	reg |= MDIO_PCS_CTRL2_10GBX;
353	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL2, reg);
354
355	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
356	reg &= ~MDIO_CTRL1_SPEEDSEL;
357	reg |= MDIO_CTRL1_SPEED1G;
358	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
359
360	xgbe_phy_pcs_power_cycle(pdata);
361
362	/* Set SerDes to 1G speed */
363	xgbe_phy_start_ratechange(pdata);
364
365	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, DATARATE, XGBE_SPEED_1000_RATE);
366	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, WORDMODE, XGBE_SPEED_1000_WORD);
367	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, PLLSEL, XGBE_SPEED_1000_PLL);
368
369	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, CDR_RATE,
370			   phy_data->cdr_rate[XGBE_SPEED_1000]);
371	XSIR1_IOWRITE_BITS(pdata, SIR1_SPEED, TXAMP,
372			   phy_data->tx_amp[XGBE_SPEED_1000]);
373	XRXTX_IOWRITE_BITS(pdata, RXTX_REG20, BLWC_ENA,
374			   phy_data->blwc[XGBE_SPEED_1000]);
375	XRXTX_IOWRITE_BITS(pdata, RXTX_REG114, PQ_REG,
376			   phy_data->pq_skew[XGBE_SPEED_1000]);
377	XRXTX_IOWRITE_BITS(pdata, RXTX_REG129, RXDFE_CONFIG,
378			   phy_data->dfe_tap_cfg[XGBE_SPEED_1000]);
379	XRXTX_IOWRITE(pdata, RXTX_REG22,
380		      phy_data->dfe_tap_ena[XGBE_SPEED_1000]);
381
382	xgbe_phy_complete_ratechange(pdata);
383
384	netif_dbg(pdata, link, pdata->netdev, "1GbE KX mode set\n");
385}
386
387static enum xgbe_mode xgbe_phy_cur_mode(struct xgbe_prv_data *pdata)
388{
389	struct xgbe_phy_data *phy_data = pdata->phy_data;
390	enum xgbe_mode mode;
391	unsigned int reg;
392
393	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL2);
394	reg &= MDIO_PCS_CTRL2_TYPE;
395
396	if (reg == MDIO_PCS_CTRL2_10GBR) {
397		mode = XGBE_MODE_KR;
398	} else {
399		if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
400			mode = XGBE_MODE_KX_2500;
401		else
402			mode = XGBE_MODE_KX_1000;
403	}
404
405	return mode;
406}
407
408static enum xgbe_mode xgbe_phy_switch_mode(struct xgbe_prv_data *pdata)
409{
410	struct xgbe_phy_data *phy_data = pdata->phy_data;
411	enum xgbe_mode mode;
412
413	/* If we are in KR switch to KX, and vice-versa */
414	if (xgbe_phy_cur_mode(pdata) == XGBE_MODE_KR) {
415		if (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
416			mode = XGBE_MODE_KX_2500;
417		else
418			mode = XGBE_MODE_KX_1000;
419	} else {
420		mode = XGBE_MODE_KR;
421	}
422
423	return mode;
424}
425
426static enum xgbe_mode xgbe_phy_get_mode(struct xgbe_prv_data *pdata,
427					int speed)
428{
429	struct xgbe_phy_data *phy_data = pdata->phy_data;
430
431	switch (speed) {
432	case SPEED_1000:
433		return (phy_data->speed_set == XGBE_SPEEDSET_1000_10000)
434			? XGBE_MODE_KX_1000 : XGBE_MODE_UNKNOWN;
435	case SPEED_2500:
436		return (phy_data->speed_set == XGBE_SPEEDSET_2500_10000)
437			? XGBE_MODE_KX_2500 : XGBE_MODE_UNKNOWN;
438	case SPEED_10000:
439		return XGBE_MODE_KR;
440	default:
441		return XGBE_MODE_UNKNOWN;
442	}
443}
444
445static void xgbe_phy_set_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
446{
447	switch (mode) {
448	case XGBE_MODE_KX_1000:
449		xgbe_phy_kx_1000_mode(pdata);
450		break;
451	case XGBE_MODE_KX_2500:
452		xgbe_phy_kx_2500_mode(pdata);
453		break;
454	case XGBE_MODE_KR:
455		xgbe_phy_kr_mode(pdata);
456		break;
457	default:
458		break;
459	}
460}
461
462static bool xgbe_phy_check_mode(struct xgbe_prv_data *pdata,
463				enum xgbe_mode mode, bool advert)
464{
465	if (pdata->phy.autoneg == AUTONEG_ENABLE) {
466		return advert;
467	} else {
468		enum xgbe_mode cur_mode;
469
470		cur_mode = xgbe_phy_get_mode(pdata, pdata->phy.speed);
471		if (cur_mode == mode)
472			return true;
473	}
474
475	return false;
476}
477
478static bool xgbe_phy_use_mode(struct xgbe_prv_data *pdata, enum xgbe_mode mode)
479{
480	struct ethtool_link_ksettings *lks = &pdata->phy.lks;
481
482	switch (mode) {
483	case XGBE_MODE_KX_1000:
484		return xgbe_phy_check_mode(pdata, mode,
485					   XGBE_ADV(lks, 1000baseKX_Full));
486	case XGBE_MODE_KX_2500:
487		return xgbe_phy_check_mode(pdata, mode,
488					   XGBE_ADV(lks, 2500baseX_Full));
489	case XGBE_MODE_KR:
490		return xgbe_phy_check_mode(pdata, mode,
491					   XGBE_ADV(lks, 10000baseKR_Full));
492	default:
493		return false;
494	}
495}
496
497static bool xgbe_phy_valid_speed(struct xgbe_prv_data *pdata, int speed)
498{
499	struct xgbe_phy_data *phy_data = pdata->phy_data;
500
501	switch (speed) {
502	case SPEED_1000:
503		if (phy_data->speed_set != XGBE_SPEEDSET_1000_10000)
504			return false;
505		return true;
506	case SPEED_2500:
507		if (phy_data->speed_set != XGBE_SPEEDSET_2500_10000)
508			return false;
509		return true;
510	case SPEED_10000:
511		return true;
512	default:
513		return false;
514	}
515}
516
517static int xgbe_phy_link_status(struct xgbe_prv_data *pdata, int *an_restart)
518{
519	unsigned int reg;
520
521	*an_restart = 0;
522
523	/* Link status is latched low, so read once to clear
524	 * and then read again to get current state
525	 */
526	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
527	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_STAT1);
528
529	return (reg & MDIO_STAT1_LSTATUS) ? 1 : 0;
530}
531
532static void xgbe_phy_stop(struct xgbe_prv_data *pdata)
533{
534	/* Nothing uniquely required for stop */
535}
536
537static int xgbe_phy_start(struct xgbe_prv_data *pdata)
538{
539	/* Nothing uniquely required for start */
540	return 0;
541}
542
543static int xgbe_phy_reset(struct xgbe_prv_data *pdata)
544{
545	unsigned int reg, count;
546
547	/* Perform a software reset of the PCS */
548	reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
549	reg |= MDIO_CTRL1_RESET;
550	XMDIO_WRITE(pdata, MDIO_MMD_PCS, MDIO_CTRL1, reg);
551
552	count = 50;
553	do {
554		msleep(20);
555		reg = XMDIO_READ(pdata, MDIO_MMD_PCS, MDIO_CTRL1);
556	} while ((reg & MDIO_CTRL1_RESET) && --count);
557
558	if (reg & MDIO_CTRL1_RESET)
559		return -ETIMEDOUT;
560
561	return 0;
562}
563
564static void xgbe_phy_exit(struct xgbe_prv_data *pdata)
565{
566	/* Nothing uniquely required for exit */
567}
568
569static int xgbe_phy_init(struct xgbe_prv_data *pdata)
570{
571	struct ethtool_link_ksettings *lks = &pdata->phy.lks;
572	struct xgbe_phy_data *phy_data;
573	int ret;
574
575	phy_data = devm_kzalloc(pdata->dev, sizeof(*phy_data), GFP_KERNEL);
576	if (!phy_data)
577		return -ENOMEM;
578
579	/* Retrieve the PHY speedset */
580	ret = device_property_read_u32(pdata->phy_dev, XGBE_SPEEDSET_PROPERTY,
581				       &phy_data->speed_set);
582	if (ret) {
583		dev_err(pdata->dev, "invalid %s property\n",
584			XGBE_SPEEDSET_PROPERTY);
585		return ret;
586	}
587
588	switch (phy_data->speed_set) {
589	case XGBE_SPEEDSET_1000_10000:
590	case XGBE_SPEEDSET_2500_10000:
591		break;
592	default:
593		dev_err(pdata->dev, "invalid %s property\n",
594			XGBE_SPEEDSET_PROPERTY);
595		return -EINVAL;
596	}
597
598	/* Retrieve the PHY configuration properties */
599	if (device_property_present(pdata->phy_dev, XGBE_BLWC_PROPERTY)) {
600		ret = device_property_read_u32_array(pdata->phy_dev,
601						     XGBE_BLWC_PROPERTY,
602						     phy_data->blwc,
603						     XGBE_SPEEDS);
604		if (ret) {
605			dev_err(pdata->dev, "invalid %s property\n",
606				XGBE_BLWC_PROPERTY);
607			return ret;
608		}
609	} else {
610		memcpy(phy_data->blwc, xgbe_phy_blwc,
611		       sizeof(phy_data->blwc));
612	}
613
614	if (device_property_present(pdata->phy_dev, XGBE_CDR_RATE_PROPERTY)) {
615		ret = device_property_read_u32_array(pdata->phy_dev,
616						     XGBE_CDR_RATE_PROPERTY,
617						     phy_data->cdr_rate,
618						     XGBE_SPEEDS);
619		if (ret) {
620			dev_err(pdata->dev, "invalid %s property\n",
621				XGBE_CDR_RATE_PROPERTY);
622			return ret;
623		}
624	} else {
625		memcpy(phy_data->cdr_rate, xgbe_phy_cdr_rate,
626		       sizeof(phy_data->cdr_rate));
627	}
628
629	if (device_property_present(pdata->phy_dev, XGBE_PQ_SKEW_PROPERTY)) {
630		ret = device_property_read_u32_array(pdata->phy_dev,
631						     XGBE_PQ_SKEW_PROPERTY,
632						     phy_data->pq_skew,
633						     XGBE_SPEEDS);
634		if (ret) {
635			dev_err(pdata->dev, "invalid %s property\n",
636				XGBE_PQ_SKEW_PROPERTY);
637			return ret;
638		}
639	} else {
640		memcpy(phy_data->pq_skew, xgbe_phy_pq_skew,
641		       sizeof(phy_data->pq_skew));
642	}
643
644	if (device_property_present(pdata->phy_dev, XGBE_TX_AMP_PROPERTY)) {
645		ret = device_property_read_u32_array(pdata->phy_dev,
646						     XGBE_TX_AMP_PROPERTY,
647						     phy_data->tx_amp,
648						     XGBE_SPEEDS);
649		if (ret) {
650			dev_err(pdata->dev, "invalid %s property\n",
651				XGBE_TX_AMP_PROPERTY);
652			return ret;
653		}
654	} else {
655		memcpy(phy_data->tx_amp, xgbe_phy_tx_amp,
656		       sizeof(phy_data->tx_amp));
657	}
658
659	if (device_property_present(pdata->phy_dev, XGBE_DFE_CFG_PROPERTY)) {
660		ret = device_property_read_u32_array(pdata->phy_dev,
661						     XGBE_DFE_CFG_PROPERTY,
662						     phy_data->dfe_tap_cfg,
663						     XGBE_SPEEDS);
664		if (ret) {
665			dev_err(pdata->dev, "invalid %s property\n",
666				XGBE_DFE_CFG_PROPERTY);
667			return ret;
668		}
669	} else {
670		memcpy(phy_data->dfe_tap_cfg, xgbe_phy_dfe_tap_cfg,
671		       sizeof(phy_data->dfe_tap_cfg));
672	}
673
674	if (device_property_present(pdata->phy_dev, XGBE_DFE_ENA_PROPERTY)) {
675		ret = device_property_read_u32_array(pdata->phy_dev,
676						     XGBE_DFE_ENA_PROPERTY,
677						     phy_data->dfe_tap_ena,
678						     XGBE_SPEEDS);
679		if (ret) {
680			dev_err(pdata->dev, "invalid %s property\n",
681				XGBE_DFE_ENA_PROPERTY);
682			return ret;
683		}
684	} else {
685		memcpy(phy_data->dfe_tap_ena, xgbe_phy_dfe_tap_ena,
686		       sizeof(phy_data->dfe_tap_ena));
687	}
688
689	/* Initialize supported features */
690	XGBE_ZERO_SUP(lks);
691	XGBE_SET_SUP(lks, Autoneg);
692	XGBE_SET_SUP(lks, Pause);
693	XGBE_SET_SUP(lks, Asym_Pause);
694	XGBE_SET_SUP(lks, Backplane);
695	XGBE_SET_SUP(lks, 10000baseKR_Full);
696	switch (phy_data->speed_set) {
697	case XGBE_SPEEDSET_1000_10000:
698		XGBE_SET_SUP(lks, 1000baseKX_Full);
699		break;
700	case XGBE_SPEEDSET_2500_10000:
701		XGBE_SET_SUP(lks, 2500baseX_Full);
702		break;
703	}
704
705	if (pdata->fec_ability & MDIO_PMA_10GBR_FECABLE_ABLE)
706		XGBE_SET_SUP(lks, 10000baseR_FEC);
707
708	pdata->phy_data = phy_data;
709
710	return 0;
711}
712
713void xgbe_init_function_ptrs_phy_v1(struct xgbe_phy_if *phy_if)
714{
715	struct xgbe_phy_impl_if *phy_impl = &phy_if->phy_impl;
716
717	phy_impl->init			= xgbe_phy_init;
718	phy_impl->exit			= xgbe_phy_exit;
719
720	phy_impl->reset			= xgbe_phy_reset;
721	phy_impl->start			= xgbe_phy_start;
722	phy_impl->stop			= xgbe_phy_stop;
723
724	phy_impl->link_status		= xgbe_phy_link_status;
725
726	phy_impl->valid_speed		= xgbe_phy_valid_speed;
727
728	phy_impl->use_mode		= xgbe_phy_use_mode;
729	phy_impl->set_mode		= xgbe_phy_set_mode;
730	phy_impl->get_mode		= xgbe_phy_get_mode;
731	phy_impl->switch_mode		= xgbe_phy_switch_mode;
732	phy_impl->cur_mode		= xgbe_phy_cur_mode;
733
734	phy_impl->an_mode		= xgbe_phy_an_mode;
735
736	phy_impl->an_config		= xgbe_phy_an_config;
737
738	phy_impl->an_advertising	= xgbe_phy_an_advertising;
739
740	phy_impl->an_outcome		= xgbe_phy_an_outcome;
741
742	phy_impl->kr_training_pre	= xgbe_phy_kr_training_pre;
743	phy_impl->kr_training_post	= xgbe_phy_kr_training_post;
744}
~/ Read-only file preview.